Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/142.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用TinyXML在XML文档中查找特定节点_C++_Xml_Parsing_Tinyxml - Fatal编程技术网

C++ 使用TinyXML在XML文档中查找特定节点

C++ 使用TinyXML在XML文档中查找特定节点,c++,xml,parsing,tinyxml,C++,Xml,Parsing,Tinyxml,我想用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"/>

我想用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>
也许我错过了库中可以完成这项工作的一个特殊函数(getElementByName函数)。我只想得到一个指向元素的指针,其中的值就是我要查找的值。有人能帮我吗?提前感谢您的帮助。

试试这个

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);
}

Adi的回答不起作用,我只是把它复制粘贴到我的代码中, 但是我修改了它,现在它对我来说很好。 因为我做了很多修改,所以我想我应该在这里发布我的最终代码

    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
    }
void parseXML(tinyxml2::XMLDocument&xXmlDocument,std::string-ssearch-string,std::function-fFoundSomeElement)
{
if(xXmlDocument.ErrorID()!=tinyxml2::XML\u成功)
{
//XML文件不正常…我们抛出了一些异常
抛出DataReceiverException(“XML文件解析失败”);
}//如果
//被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);
}
/*
*我们按照以下规则在XML树中移动(基本上按树漫游的顺序):
*   
*(1)如果有一个或多个子元素,请访问第一个子元素
*否则
*(2)如果有一个或多个下一个兄弟元素,请访问第一个
*否则
*(3)移动到父元素,直到有一个或多个下一个同级元素
*(4)如果我们到达终点,就打破循环
*/
如果(xElem->FirstChildElement())/(1)
xElem=xElem->FirstChildElement();
else if(xElem->NextSiblingElement())/(2)
xElem=xElem->NextSiblingElement();
其他的
{
而(xElem->Parent()&&!xElem->Parent()->NextSiblingElement())/(3)
xElem=xElem->Parent();
if(xElem->Parent()&&xElem->Parent()->NextSiblingElement())
xElem=xElem->Parent()->NextSiblingElement();
else/(4)
打破
}//否则
}//当
}
(完整性)如何调用函数的示例:

        tinyxml2::XMLDocument xXmlDocument;

        xXmlDocument.Parse(sXmlDocument.c_str());

        parseXML(xXmlDocument, "user",[](tinyxml2::XMLNode* xElem)
        {
            int iPass;
            xElem->QueryIntAttribute( "pass", &iPass );
            std::cout << iPass << "\n";
        });
tinyxml2::XMLDocument xXmlDocument;
xXmlDocument.Parse(sXmlDocument.c_str());
parseXML(xXmlDocument,“用户”,[](tinyxml2::XMLNode*xElem)
{
int iPass;
xElem->QueryStatAttribute(“通行证”和iPass);

std::cout您还可以使用递归函数和lamda函数作为处理程序,逐个迭代XML元素

// 
// This function will iterate through your XML tree and call the 'parseElement' function for each found element.
//
void RecursiveXMLParse(TiXmlElement* element, std::function<void(TiXmlElement*)>& parseElement)
{
    if (element != nullptr)
    {
        parseElement(element);
        auto child = element->FirstChildElement();
        if (child != nullptr)
        {
            RecursiveXMLParse(child, parseElement);
        }

        for (auto sibling = element->NextSiblingElement(); sibling != nullptr; sibling = sibling->NextSiblingElement())
        {
            RecursiveXMLParse(sibling, parseElement);
        }
    }
}
//
//此函数将遍历XML树,并为每个找到的元素调用“parseElement”函数。
//
void RecursiveXMLParse(tixmlement*元素、std::function和parseElement)
{
if(元素!=nullptr)
{
元素(element);
auto-child=element->FirstChildElement();
if(child!=nullptr)
{
RecursiveXMLParse(子元素,parseElement);
}
对于(auto sibling=element->NextSiblingElement();sibling!=nullptr;sibling=sibling->NextSiblingElement())
{
递归XMLParse(同级,parseElement);
}
}
}
用法:只需将XML根元素和数据处理程序lambda函数传递给递归解析器函数

int main()
{
    //
    // Define your data handler labmda
    //
    std::function<void(TiXmlElement*)>parseElement = [&](TiXmlElement* e) -> void
    {
        if (std::string(elem->Value()).compare("user"))
        {
             // Parse your user data
        }
    };

    // Pass the root element along with the above defined lambda to the recursive function 
    RecursiveXMLParse(doc.RootElement(), parseElement);

    return 0;
}
intmain()
{
//
//定义数据处理程序labmda
//
std::functionparseElement=[&](TiXmlElement*e)->void
{
if(std::string(elem->Value())。比较(“用户”))
{
//解析您的用户数据
}
};
//将根元素和上面定义的lambda一起传递给递归函数
RecursiveXMLParse(doc.RootElement(),parseElement);
返回0;
}

//上面给定的解决方案中的一个小调整

看起来就是您想要的。实现,并且
TiXmlNode
将为您执行树遍历。这里有一个bug,如果您有一个结构,其中最深的元素没有“同级”,则if将在不移动/c的情况下向下流动,这将导致递归永远不会结束悬而未决的元素-所以while永远不会结束这是一个有效的解决方案,Adi不会因为没有处理边缘案例(在if的最后一部分)而感谢David清理混乱。
// 
// This function will iterate through your XML tree and call the 'parseElement' function for each found element.
//
void RecursiveXMLParse(TiXmlElement* element, std::function<void(TiXmlElement*)>& parseElement)
{
    if (element != nullptr)
    {
        parseElement(element);
        auto child = element->FirstChildElement();
        if (child != nullptr)
        {
            RecursiveXMLParse(child, parseElement);
        }

        for (auto sibling = element->NextSiblingElement(); sibling != nullptr; sibling = sibling->NextSiblingElement())
        {
            RecursiveXMLParse(sibling, parseElement);
        }
    }
}
int main()
{
    //
    // Define your data handler labmda
    //
    std::function<void(TiXmlElement*)>parseElement = [&](TiXmlElement* e) -> void
    {
        if (std::string(elem->Value()).compare("user"))
        {
             // Parse your user data
        }
    };

    // Pass the root element along with the above defined lambda to the recursive function 
    RecursiveXMLParse(doc.RootElement(), parseElement);

    return 0;
}
XMLElement *getElementByName(XMLDocument &ele, std::string const &elemt_value)
    {
    XMLElement *elem = ele.FirstChildElement(); //Tree root

    while (elem)
    {
        if (!std::string(elem->Value()).compare(elemt_value))
            return elem;
        if (elem->FirstChildElement())
        {
            elem = elem->FirstChildElement();
        }
        else if (elem->NextSiblingElement())
        {
            elem = elem->NextSiblingElement();
        }
        else
        {
            if (elem->Parent()->ToElement()->NextSiblingElement())
            {
                elem = elem->Parent()->ToElement()->NextSiblingElement();
            }
            else if (elem->Parent()->ToElement()->FirstChildElement()
                        &&  strcmp(elem->Name(), elem->Parent()->ToElement()->FirstChildElement()->Name()))
            {
                elem = elem->Parent()->ToElement()->FirstChildElement();
            }
            else {
                break;
            }
        }
    }
    return NULL;
}