使用const迭代器进行属性树put / erase,或者如何将const_iterator转换为迭代器

时间:2014-01-29 09:56:17

标签: c++ xml boost iterator boost-propertytree

我在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);

现在它编译,应用程序不会崩溃,但它挂在上述位置。我不知道为什么。 [ /修改

非常感谢提前。

2 个答案:

答案 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>