我在ubuntu 12.04lts上使用boost 1.55.0 with clang 3.4。
我有一个boost::property_tree::ptree
,其xml输入如下:
<root>
<persons>
<person>
<name>dad</name>
<age>43</age>
</person>
<person>
<name>me</name>
<age>4</age>
</person>
</persons>
</root>
所以我有一个具有相同标签的节点列表。
为了阅读它们,我遍历树,并根据我要删除节点的条件。这看起来像:
boost::property_tree::ptree pt;
boost::property_tree::read_xml(inputFileName, pt);
boost::property_tree::ptree& persons = pt.get_child("root");
for(boost::property_tree::ptree::const_iterator it = persons.begin(); it != persons.end(); ++it)
{
std::string name = it->second.get<std::string>("name");
if(name == "dad")
// erase that name node from pt
persons.erase(it->second.find("name"); // this doesn't work
}
[编辑]正如pmr的回答所说,我写了以下代码:
boost::property_tree::ptree::iterator i = persons.begin();
auto assoc_i = it->second.find("name");
auto ci = persons.to_iterator(assoc_i);
std::advance(i, std::distance<boost::property_tree::ptree::const_iterator>(iterator, ci)); // --> here it hangs
persons.erase(i);
现在它编译,应用程序不会崩溃,但它挂在上述位置。我不知道为什么。 [ /修改
非常感谢提前。
答案 0 :(得分:3)
容器的C ++ 11 API指定成员函数iterator container::erase(const_iterator, const_iterator)
。不幸的是,basic_ptree
没有这样做,因此您仍然坚持使用旧的C ++方式将const_iterator
转换为iterator
:
// tree is your ptree, my_const_iter a ptree::const_iterator
ptree::iterator i = tree.begin();
advance (i, std::distance<ConstIter>(i,my_const_iter));
答案 1 :(得分:3)
你手头的问题与迭代器的常量几乎没有关系,你只是用错误的ptree迭代器擦除。
ptree& persons = pt.get_child("root.persons");
for(auto it = persons.begin(); it != persons.end();) {
if(it->second.get<string>("name") == "dad")
it = persons.erase(it);
else
++it;
}
ptree对子节点使用multi_index,并且为了使迭代在擦除时保持稳定,必须使用从erase()操作返回的迭代器来继续迭代,这是一种常见模式。
注意,问题中的XML缺少/
(</age>
)终止,它无法验证。我没有编辑修复它的问题,因为这可能是您在执行程序时遇到的问题之一。
使用上述代码通过write_xml(std::out, pt)
输出处理ptree:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<persons>
<person>
<name>me</name>
<age>4</age>
</person>
</persons>
</root>