2012-08-12 7 views
2

Je souhaite analyser certaines données d'un fichier XML avec TinyXML.Trouver un nœud spécifique dans un document XML avec TinyXML

Voilà le contenu de mon fichier text.xml:

<?xml version="1.0" encoding="iso-8859-1"?> 
<toto> 
    <tutu> 
    <tata> 
     <user name="toto" pass="13" indice="1"/> 
     <user name="tata" pass="142" indice="2"/> 
     <user name="titi" pass="azerty" indice="1"/> 
    </tata> 
    </tutu> 
</toto> 

Je veux accéder au premier élément « utilisateur ». La manière de procéder est la suivante:

TiXmlDocument doc("test.xml"); 

    if (doc.LoadFile()) 
    { 
     TiXmlNode *elem = doc.FirstChildElement()->FirstChildElement()->FirstChildElement()->FirstChildElement(); 
std::cout << elem->Value() << std::endl; 
} 

En sortie: utilisateur.

Mais le code est plutôt moche et pas générique. J'ai essayé le code ci-dessous pour simuler le même comportement que le code ci-dessus mais cela ne fonctionne pas et une erreur est survenue. Peut-être que j'ai manqué une fonction spéciale dans la bibliothèque qui peut faire ce travail (une fonction getElementByName). Je veux juste obtenir un pointeur vers l'élément où la valeur est celle que je cherche. Est-ce que quelqu'un peut m'aider? Merci d'avance pour votre aide.

+1

On dirait que le [ 'virtual bool TiXmlNode :: accept()' méthode] (http://www.grinninglizard.com /tinyxmldocs/classTiXmlNode.html#cc0f88b7462c6cb73809d410a4f5bb86) est ce que vous voulez. Implémentez l'interface ['Visitor'] (http://www.grinninglizard.com/tinyxmldocs/classTiXmlVisitor.html) et le' TiXmlNode' fera marcher l'arbre pour vous. – Tomalak

Répondre

3

Essayez cette

TiXmlElement * getElementByName(TiXmlDocument & doc, std::string const & elemt_value) { 

    TiXmlElement * elem = doc.RootElement(); //Tree root 
    while (elem) { 
     if (!std::string(elem - > Value()).compare(elemt_value)) return (elem); 
     /*elem = elem->NextSiblingElement();*/ 
     if (elem - > FirstChildElement()) { 
     elem = elem - > FirstChildElement(); 
     } else if (elem - > NextSiblingElement()) { 
     elem = elem - > NextSiblingElement(); 
     } else { 
     while (!elem - > Parent() - > NextSiblingElement()) { 
      if (elem - > Parent() - > ToElement() == doc.RootElement()) { 
       return NULL; 
      } 
      elem = elem - > Parent() - > NextSiblingElement(); 
     } 
     } 
    } 
    return (NULL); 
} 
1

Adi de réponse n'a pas fonctionné quand je viens copier collé dans mon code, mais je l'ai modifié et maintenant il fonctionne très bien pour moi. depuis que j'ai fait beaucoup de changements, j'ai pensé que je devrais poster mon code final ici.

void parseXML(tinyxml2::XMLDocument& xXmlDocument, std::string sSearchString, std::function<void(tinyxml2::XMLNode*)> fFoundSomeElement) 
    { 
      if (xXmlDocument.ErrorID() != tinyxml2::XML_SUCCESS) 
      { 
       // XML file is not ok ... we throw some exception 
       throw DataReceiverException("XML file parsing failed"); 
      } // if 

      //ispired by http://stackoverflow.com/questions/11921463/find-a-specific-node-in-a-xml-document-with-tinyxml 
      tinyxml2::XMLNode * xElem = xXmlDocument.FirstChild(); 
      while(xElem) 
      { 
       if (xElem->Value() && !std::string(xElem->Value()).compare(sSearchString)) 
       { 
        fFoundSomeElement(xElem); 
       } 

       /* 
       * We move through the XML tree following these rules (basically in-order tree walk): 
       * 
       * (1) if there is one or more child element(s) visit the first one 
       *  else 
       * (2)  if there is one or more next sibling element(s) visit the first one 
       *    else 
       * (3)    move to the parent until there is one or more next sibling elements 
       * (4)    if we reach the end break the loop 
       */ 
       if (xElem->FirstChildElement()) //(1) 
        xElem = xElem->FirstChildElement(); 
       else if (xElem->NextSiblingElement()) //(2) 
        xElem = xElem->NextSiblingElement(); 
       else 
       { 
        while(xElem->Parent() && !xElem->Parent()->NextSiblingElement()) //(3) 
         xElem = xElem->Parent(); 
        if(xElem->Parent() && xElem->Parent()->NextSiblingElement()) 
         xElem = xElem->Parent()->NextSiblingElement(); 
        else //(4) 
         break; 
       }//else 
      }//while 
    } 

(pour être complet) par exemple comment appeler la fonction:

 tinyxml2::XMLDocument xXmlDocument; 

     xXmlDocument.Parse(sXmlDocument.c_str()); 

     parseXML(xXmlDocument, "user",[](tinyxml2::XMLNode* xElem) 
     { 
      int iPass; 
      xElem->QueryIntAttribute("pass", &iPass); 
      std::cout << iPass << "\n"; 
     }); 
Questions connexes