2012-08-12 135 views
2

我想用TinyXML解析xml文件中的某些數據。用TinyXML在XML文檔中查找特定節點

這是我的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> 

我要訪問的第一個元素「用戶」。執行此操作的方法如下:

TiXmlDocument doc("test.xml"); 

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

輸出:用戶。

但該代碼是非常醜陋的,而不是通用的。我嘗試了下面的代碼來模擬與上面的代碼相同的行爲,但它不起作用並出現錯誤。

TiXmlElement *getElementByName(TiXmlDocument &doc, std::string const &elemt_value) 
{ 
    TiXmlElement *elem = doc.FirstChildElement(); //Tree root 

    while (elem) 
    { 
     if (!std::string(elem->Value()).compare(elemt_value)) 
      return (elem); 
     elem = elem->NextSiblingElement(); 
    } 
    return (NULL); 
} 

也許我錯過了庫中可以完成這項工作的一個特殊函數(一個getElementByName函數)。我只想獲得一個指向元素的指針,其中的值是我正在尋找的元素。有人可以幫助我嗎?在此先感謝您的幫助。

+1

貌似['虛擬BOOL TiXmlNode ::接受()'方法](http://www.grinninglizard.com /tinyxmldocs/classTiXmlNode.html#cc0f88b7462c6cb73809d410a4f5bb86)是你想要的。實現['Visitor'接口](http://www.grinninglizard.com/tinyxmldocs/classTiXmlVisitor.html),'TiXmlNode'將爲你走樹。 – Tomalak 2012-08-12 10:35:37

回答

3

嘗試時,我只是複製粘貼到我的代碼,這

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

阿迪的答案沒有工作,但我修改它,現在它爲我工作得很好。 因爲我做了很多改變,我以爲我應該在這裏發佈我的最終代碼。

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 
    } 

(出於完整性)例如如何調用該函數:

 tinyxml2::XMLDocument xXmlDocument; 

     xXmlDocument.Parse(sXmlDocument.c_str()); 

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