2010-07-21 6 views
3

J'ai quelques simples code de gestion XML qui est censé trouver un nœud enfant d'un passé dans le nœud basé sur une valeur d'attribut:Que se passe-t-il avec ces nœuds XML nommés "#text"?

function GetNodeByAttributeValue(
    const AParentNode: IXMLNode; 
    const AttributeName: string; AttributeValue: Variant): IXMLNode; 
var 
    i: integer; 
    value: Variant; 
begin 
    result := nil; 
    if (not Assigned(AParentNode)) or (AttributeName = '') then 
    exit; 
    for i := 0 to AParentNode.ChildrenCount-1 do 
    begin 
    result := AParentNode.Children[i]; 
    value := result.GetAttributeValue(AttributeName, UnAssigned); 
    if not VarIsEmpty(value) then 
     exit; 
    end; 
    result := nil; 
end; 

assez simple, non? Mais quand j'essaye d'exécuter ceci, dans certaines circonstances il se bloque avec une violation d'accès. Voici ce qui se passe:

L'implémentation IXML * est fournie par la bibliothèque SDK RemObjects. result.GetAttributeValue appels uROMSXMLImpl.TROMSXMLNode.GetAttributeValue, qui appelle TROMSXMLNode.GetAttributeByName, qui dit

node := fNode.attributes.getNamedItem(anAttributeName); 

Et cette tombe en panne parce que fNode.attributes rendements néant. Si je comprends bien, cela ne devrait jamais arriver. La chose étrange est, retournant à la boucle for dans la fonction d'origine, AParentNode.ChildrenCount renvoie 3. Mais le nœud dans le document XML d'origine a seulement un nœud enfant. Cela correspond aux critères que je cherche.

<ParentNode> 
    <namespace:ChildNode name="right-name"> 

Mais AParentNode.ChildrenCount retours 3. Je les ouvrir dans le débogueur et obtenez ceci:

AParentNode.Children[0].name: '#text' 
AParentNode.Children[1].name: 'namespace:ChildNode' 
AParentNode.Children[2].name: '#text' 

Que dans le monde sont ces nœuds "#text"? Ils ne sont pas dans le document XML et je n'ai pas écrit de code pour les insérer. Pourquoi sont-ils là, et pourquoi sont-ils bogués, et est-ce que je peux faire quelque chose pour les empêcher de foirer ma recherche d'attributs? Les noeuds #text sont les bits des espaces avant et après <namespace:ChildNode>

Répondre

7

Les nœuds de texte sont les espaces renvoyés par l'analyseur.
dire que l'indentation <namespace:ChildNode name="right-name">

Ces éléments sont considérés comme des espaces blancs enfants de <ParentNode>

1

Puisque les noeuds #text ne sont que des morceaux de texte, ils n'ont aucun attribut. Si vous voulez vous débarrasser de ces nœuds, essayez d'utiliser xsl:strip-space dans une transformation XSL, ou vérifiez simplement si le nœud est entièrement composé d'espaces.

2

Vous avez deux choix. Vous pouvez définir une option dans l'analyseur pour supprimer les espaces (désactiver l'option pour préserver les espaces) - ou mieux vous pouvez vérifier si le nœud que vous examinez pour les attributs est réellement un élément, car seuls les éléments peuvent avoir des attributs. Cela vaut mieux aussi parce que si XML a une instruction de traitement comme celle-ci: <?some wired stuff?>, alors même les espaces blancs ne sont pas utiles car la recherche d'attributs dans l'instruction de traitement donne également AV dans cet analyseur. J'ai donc ajouté à votre état de code NodeType ici:

function GetNodeByAttributeValue(
    const AParentNode: IXMLNode; 
    const AttributeName: string; AttributeValue: Variant): IXMLNode; 
var 
    i: integer; 
    value: Variant; 
begin 
    result := nil; 
    if (not Assigned(AParentNode)) or (AttributeName = '') then 
    exit; 
    for i := 0 to AParentNode.ChildrenCount-1 do 
    begin 
    result := AParentNode.Children[i]; 
    if result.NodeType = ntElement then 
    begin 
     value := Result.GetAttributeValue(AttributeName, UnAssigned); 
     if not VarIsEmpty(value) and (value = AttributeValue) then 
     exit; 
    end; 
    end; 
    result := nil; 
end; 

Le filtrage que vous faites peut également être fait facilement dans XSLT et/ou XPath, mais je ne sais pas si cet analyseur prend en charge XPath et ne sais pas si XSLT serait réellement pratique pour vous.