boost recognize a child

烈酒焚心 提交于 2020-01-06 01:29:31

问题


My question is related to : boost

Some of the boost code is working correctly to find that a node has child, but if one node have two other nodes it didn't recognize the children.

It's recursive call to be able to read all the tree nodes and then apply the copy of the value to the google protocol buffer

void ReadXML(iptree& tree, string doc)
{
    const GPF* gpf= pMessage->GetGPF();
    for(int i = 0 ; i < gpf->field_count(); ++i)
    { 
          string fieldName = GetName(i);
          boost::optional< iptree & > chl =  pt.get_child_optional(fieldName); 
          if(chl) { 
          for( auto a : *chl ){
             boost::property_tree::iptree subtree = (boost::property_tree::iptree) a.second ;
             assignDoc(doc);
                 ReadXML(subtree, doc);
             }
           }
      }     
}

the XML file

<?xml version="1.0" encoding="utf-8"?>
<nodeA xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <nodeA.1>This is the Adresse</nodeA.1>
    <nodeA.2>
    <node1>
      <node1.1>
        <node1.1.1>Female</node1.1.1>
        <node1.1.2>23</node1.1.2>
        <node1.1.3>Engineer</node1.1.3>
      </node1.1>
      <node1.1>
        <node1.2.1>Female</node1.2.1>
        <node1.2.2>35</node1.2.2>
        <node1.2.3>Doctors</node1.2.3>
      </node1.1>
    </node1>
</nodeA.2>
<nodeA.3>Car 1</nodeA.3>
</nodeA>

My problem is that node1 is not recognised as having child. I don't know if it's because there are two children nodes with the same name.

Note that the XML files may change from one client to another. I may have different nodes.

Do I have to use a.second or a.first?


回答1:


Here

boost::optional< iptree & > chl =  pt.get_child_optional(fieldName);

you explicitly search for a child with a given name. This name never seems the change during recursion. On every level you look for children with the same name it seems.




回答2:


I think you could/should be looking at this problem from a higher level.

Boost Property Tree uses RapidXML under the hood. PugiXML is a similar, but more modern library that can also be used in header-only mode. With PugiXML you could write:

pugi::xml_document doc;
doc.load(iss);

for (auto& node : doc.select_nodes("*/descendant::*[count(*)=3]/*[count(*)=0]/.."))
{
    auto values = node.node().select_nodes("*/text()");
    std::cout << "Gender    " << values[0].node().value() << "\n";
    std::cout << "Age       " << values[1].node().value() << "\n";
    std::cout << "Job Title " << values[2].node().value() << "\n";
}

It selects all descendants of the root node (nodeA) that three leaf child nodes, and interprets them as Gender, Age and Job Title. It prints:

Gender    Female
Age       23
Job Title Engineer
Gender    Female
Age       35
Job Title Doctors

I hope you will find this constructive.


Full Demo

On my system to build, simply:

sudo apt-get install libpugixml-dev
g++ -std=c++11 demo.cpp -lpugixml -o demo
./demo

demo.cpp:

#include <pugiconfig.hpp>
#define PUGIXML_HEADER_ONLY
#include <pugixml.hpp>

#include <iostream>
#include <sstream>

int main()
{
    std::istringstream iss("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
            "<nodeA xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">"
                "<nodeA.1>This is the Adresse</nodeA.1>"
                "<nodeA.2>"
                    "<node1>"
                        "<node1.1>"
                            "<node1.1.1>Female</node1.1.1>"
                            "<node1.1.2>23</node1.1.2>"
                            "<node1.1.3>Engineer</node1.1.3>"
                        "</node1.1>"
                        "<node1.2>"
                            "<node1.2.1>Female</node1.2.1>"
                            "<node1.2.2>35</node1.2.2>"
                            "<node1.2.3>Doctors</node1.2.3>"
                        "</node1.2>"
                    "</node1>"
                "</nodeA.2>"
            "<nodeA.3>Car 1</nodeA.3>"
        "</nodeA>");

    pugi::xml_document doc;
    doc.load(iss);

    for (auto& node : doc.select_nodes("*/descendant::*[count(*)=3]/*[count(*)=0]/.."))
    {
        auto values = node.node().select_nodes("*/text()");
        std::cout << "Gender    " << values[0].node().value() << "\n";
        std::cout << "Age       " << values[1].node().value() << "\n";
        std::cout << "Job Title " << values[2].node().value() << "\n";
    }

    //doc.save(std::cout);
}


来源:https://stackoverflow.com/questions/26785787/boost-recognize-a-child

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!