问题
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