boost property_tree: перебирая атрибуты повторяющихся дочерних элементов внутри повторяющихся дочерних элементов
У меня есть следующий документ XML:
<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>
С помощью boost::property_tree::ptree
Я могу сделать следующее, чтобы перебрать элементы верхнего уровня:
ptree scenarioTree = myTree.get_child("root");
for (const auto& itr : scenarioTree) {
if (itr.second.get<std::string>(<xmlattr>.name) == "ScenarioA") {
// additional logic
}
}
Я не могу получить какие-либо атрибуты тегов "param" для каждого сценария, используя тот же метод на 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
}
}
}
}
Что я делаю неправильно? Моя теория заключается в том, что это проблема приведения между тем, что итератор ptree возвращает (self), и стандартным ptree, но я не уверен, как еще получить внутренние дочерние атрибуты. Я могу получить имена тегов param (через first) и значения параметров (через second.data()), только без атрибутов.
1 ответ
Атрибуты в дереве свойств добавляются как подузлы. Ниже узел можно перевести
<scenario name="ScenarioA">
<param name="ParamA">1</param>
<param name="ParamB">2</param>
<param name="ParamC">3</param>
</scenario>
во что-то вроде этого:
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
Когда вы нашли сценарий с ScenarioA
в качестве атрибута вы перебираете его дочерние элементы. Этот узел имеет 4 детей. Для каждого ребенка, которого вы хотите найти name
атрибут, но один из них не имеет этого атрибута. метод get
выдает исключение, когда путь не может быть найден. Вы можете перехватить это исключение или использовать значение по умолчанию:
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;
}
}
}
}
в результате я получил ParamA был найден в сценарии A.