I have the following XML document:
<root>
<scenario name="ScenarioA">
<param name="ParamA">1</param>
<param name="ParamB">2</param>
<param name="ParamC">3</param>
</scenario>
<scenario name="ScenarioB">
<param name="ParamA">1</param>
<param name="ParamB">2</param>
<param name="ParamC">3</param>
</scenario>
<scenario name="ScenarioC">
<param name="ParamA">1</param>
<param name="ParamB">2</param>
<param name="ParamC">3</param>
</scenario>
</root>
Using boost::property_tree::ptree
, I can do the following to iterate through the top-level elements:
ptree scenarioTree = myTree.get_child("root");
for (const auto& itr : scenarioTree) {
if (itr.second.get<std::string>(<xmlattr>.name) == "ScenarioA") {
// additional logic
}
}
I am unable to retrieve any attributes of the "param" tags under each scenario, using the same method on itr.second
:
ptree scenarioTree = myTree.get_child("root");
for (const auto& itr : scenarioTree) {
if (itr.second.get<std::string>(<xmlattr>.name) == "ScenarioA") {
ptree paramTree = itr.second;
// Iterate through "param" tags
for (const auto& paramItr: paramTree) {
if (paramItr.second.get<std::string>(<xmlattr>.name) == "ParamA") {
// doesn't exist
}
}
}
}
What am I doing wrong? My theory is this a casting issue between what the ptree iterator returns (self) versus a standard ptree, but I'm not sure how else to retrieve the inner child attributes. I am able to retrieve param tag names (via first) and param values (via second.data()), just no attributes.
Attributes in property tree are added as sub-nodes. Below node can be translated
<scenario name="ScenarioA">
<param name="ParamA">1</param>
<param name="ParamB">2</param>
<param name="ParamC">3</param>
</scenario>
into something like this:
scenario
xmlattr.name ScenarioA // this node doesn't have subnode with attribute name
param
xmlattr.name -> ParamA
param
xmlattr.name -> ParamB
param
xmlattr.name -> ParamC
When you found scenario with ScenarioA
as attribute you are iterating over its children. This node has 4 children. For each child you want to find name
attribute, but one of them doesn't have this attribute. Method get
throws exception when path cannot be found. You can catch this exception or use default-value:
boost::property_tree::ptree scenarioTree = pt.get_child("root");
for (const auto& itr : scenarioTree)
{
if (itr.second.get<std::string>("<xmlattr>.name") == "ScenarioA")
{
boost::property_tree::ptree paramTree = itr.second;
for (const auto& paramItr: paramTree)
{
if (paramItr.second.get<std::string>("<xmlattr>.name","") == "ParamA")
{ ^^^^ default value
cout << "ParamA was found in ScenarioA" << endl;
}
}
}
}
as result I got ParamA was found in ScenarioA.