2010-11-10 6 views
0

J'utilise libxml2 pour analyser la chaîne XML suivante:résultats XML d'analyse syntaxique Doublons utilisant libxml2

<?xml version=\"1.0\"?> 
<note> 
    <to> 
     <name>Tove</name> 
     <name>Tovi</name> 
    </to> 
    <from>Jani</from> 
    <heading>Reminder</heading> 
    <body>Don't forget me this weekend!</body> 
</note> 

Formaté comme une chaîne C-style:

"<?xml version=\"1.0\"?><note><to><name>Tove</name><name>Tovi</name></to><from>Jani</from><heading>Reminder</heading><body>Don't forget me this weekend!</body></note>" 

Ceci est basé sur l'exemple du site du W3C sur XML; J'ai seulement ajouté les noms imbriqués dans le champ "à".

J'ai le code récursive suivante en C++ pour analyser dans un arbre d'objets:

RBCXMLNode * RBCXMLDoc::recursiveProcess(xmlNodePtr node) { 
    RBCXMLNode *rNode = new RBCXMLNode(); 
    xmlNodePtr childIterator = node->xmlChildrenNode; 

    const char *chars = (const char *)(node->name); 
    string name(chars); 
    const char *content = (const char *)xmlNodeGetContent(node); 
    rNode->setName(name); 
    rNode->setUTF8Data(content); 
    cout << "Just parsed " << rNode->name() << ": " << rNode->stringData() << endl; 
    while (childIterator != NULL) { 
     RBCXMLNode *rNode2 = recursiveProcess(childIterator); 
     rNode->addChild(rNode2); 
     childIterator = childIterator->next; 
    } 
    return rNode; 
} 

Ainsi, pour chaque nœud, il crée l'objet correspondant, définit son nom et son contenu, récursif puis pour ses enfants. Notez que chaque noeud n'est traité qu'une seule fois. Cependant, je reçois les points suivants (aucun sens, du moins pour moi) Sortie:

Note Juste analysable: ToveToviJaniReminderDon't me oublier ce week-end!
Juste parsé à: ToveTovi
Juste Nom analysable: Tove
texte juste analysable: Tove
Nom Juste analysable: Tovi
texte juste analysable: Tovi
Juste analysé à partir de: Jani
Tout texte analysé: Jani
A peine analysé en-tête: Rappel
Texte juste analysé: Rappel
Juste analysé corps: Ne m'oublie pas ce week-end!
Texte juste analysé: Ne m'oublie pas ce week-end!

Notez que chaque élément est en cours d'analyse deux fois; une fois que l'on donne le nom comme "texte" et qu'on lui donne ce qu'il devrait être. En outre, le noeud racine "note" fait également analyser ses données; c'est indésirable. Notez également que ce nœud racine n'est pas analysé deux fois, comme les autres le sont.

J'ai donc deux questions:

  1. Comment puis-je éviter l'analyse syntaxique des données de nœud racine, et ont simplement son nom et non son contenu? Cela se produira probablement également avec des nœuds imbriqués plus profondément.
  2. Comment éviter l'analyse en double sur les autres noeuds? Évidemment, je veux garder les versions correctement nommées, tout en conservant la possibilité (improbable) qu'un noeud soit nommé "text". En outre, il peut y avoir des nœuds en double qui sont souhaités, donc vérifier simplement si le nœud a déjà été analysé n'est pas une option.

Merci d'avance.

Répondre

2

Le principal problème que je vois dans votre code est que vous appelez xmlNodeGetContent(). Cela vous renvoie le texte entier à l'intérieur l'étiquette et son homologue de fin.

Lors de l'analyse avec libxml2, vous obtenez des nœuds dont le contenu est complexe, donc vous ne pouvez pas compter sur xmlNodeGetContent() pour récupérer le contenu. Vous devez faire la fonction récursive différemment.Par exemple, vous la solution la plus rapide à votre fonction serait d'imprimer uniquement le nom de nœud pour les nœuds qui ne sont pas texte (testé avec xmlNodeIsText()), et d'écrire seulement le xmlNodeGetContent() pour les nœuds qui sont du texte. Cela vous donne une chose de sortie comme:

Just parsed note 
Just parsed to 
Just parsed name 
Just parsed text: Tove 
Just parsed name 
Just parsed text: Tovi 
... 

Notez que maintenant vous seuls éléments d'impression, et seul texte lorsque vous avez un type d'élément de texte.

Cela a également du sens sur le plan conceptuel, car le contenu d'un nœud autre que du texte (et non du texte) est si complexe que comment l'imprimer? Vous pouvez seulement imprimer son étiquette (nom). Cependant, les nœuds de texte sont si simples que vous pouvez imprimer leur contenu.

+0

Cela fonctionnerait sauf que j'ai besoin de tous les types de contenu; Je dois être en mesure d'obtenir la chaîne XML réelle pour tous les types de valeurs. Ainsi, par exemple, je peux avoir un noeud qui contient un nombre à virgule flottante; cela doit aller pour que je puisse ensuite l'analyser dans mon code. De plus, votre méthode associe chaque élément au nom "texte", ce qui ne fonctionne pas. Je dois, par exemple, rechercher un objet par son nom, puis récupérer ses données. –

+0

C'était juste un exemple. Vous devez tester manuellement si un nœud est "texte" et ensuite agir en conséquence (je viens de copier/éditer la sortie). Si vous avez des valeurs à virgule flottante, vous devez savoir "où" elles sont (nom de la balise, par exemple), car comme XML apparaîtra sous forme de texte, et vous devrez les décoder. Notez que vous traitez tout, * mais * le contenu des nœuds complexes est simplement complexe, de sorte que vous ne pouvez pas le traiter comme une chaîne. –

+0

@ jfm429 XML est un langage de balisage de texte. Il n'a pas de concept de nombres à virgule flottante. Soit vous avez ' 1,23' qui est un élément dont le nom de tag est "a" avec un seul noeud de texte enfant contenant le texte "1.23", ou vous avez un élément avec des attributs nommés. Je n'ai pas utilisé libxml2, mais il semble y avoir un membre nommé dans xmlNode. –

Questions connexes