如果是双重注册,如何从Boost树中删除孩子



您能帮我帮助我吗?

我填充了此finaltree = treea treeb

但是,问题是TreeB的某些元素在某些Trea中具有相同的名称。结果,我可能会为某些孩子提供双重注册。

即。

    <category>
        <fruit type="banana">
              <characteristic>
                 <point v="0"/>
              </characteristic>
        </fruit>
        <fruit type="orange">
              <characteristic>
                 <point v="1"/>
               </characteristic>
        </fruit>
        <fruit type="banana">
              <characteristic>
                  <point v="2"/>
              </characteristic>
        </fruit>
        <fruit type="fig">
              <characteristic>
                <point v="3"/>
              </characteristic>
        </fruit>
    </category>

我想实现的是删除香蕉的第一个条目并保留最后一个。到目前为止,我这样做:

boost::property_tree::ptree  & node = informationTree.add("information.fruitTypes", "");
node.add("<xmlattr>.type", fruit);
node.add_child("characteristic", char);

问题是我不知道如何删除它,因为我不知道下次是香蕉还是其他东西。我应该复制填充树吗?您建议什么?

如果您只是构建树,则可以使用put_*而不是add_*,如果元素已经以该名称存在。

,它将覆盖它。

如果您有一棵树并想在某个子树处删除重复项,则必须手动进行,例如:

活在coliru

#include <boost/property_tree/xml_parser.hpp>
#include <iostream>
#include <map>
using boost::property_tree::ptree;
template <typename KeyF>
ptree nodup(ptree const& pt, KeyF key_accessor) {
    ptree filtered;
    std::map<std::string, std::reference_wrapper<ptree> > seen;
    for (auto& entry : pt) {
        auto key      = key_accessor(entry);
        auto previous = seen.find(key);
        if (seen.end() == previous)
            seen.emplace(key, filtered.add_child(entry.first, entry.second));
        else
            previous->second.get() = entry.second; // overwrite
    }
    return filtered;
}
int main() {
    ptree pt;
    {
        std::istringstream iss( "<category><fruit type="banana"><characteristic><point v="0"/></characteristic></fruit><fruit type="orange"><characteristic><point v="1"/></characteristic></fruit><fruit type="banana"><characteristic><point v="2"/></characteristic></fruit><fruit type="fig"><characteristic><point v="3"/></characteristic></fruit></category>");
        read_xml(iss, pt);
    }
    write_xml(std::cout, pt, boost::property_tree::xml_writer_make_settings<std::string>(' ', 4, "utf-8"));
    auto& subtree = pt.get_child("category");
    subtree = nodup(subtree, [](ptree::value_type const& item) { return item.second.get("<xmlattr>.type", ""); });
    write_xml(std::cout, pt, boost::property_tree::xml_writer_make_settings<std::string>(' ', 4, "utf-8"));
}

如果您的性能更高,则可以向后迭代并避免进行一些覆盖的动作:

活在coliru

template <typename KeyF>
ptree nodup(ptree const& pt, KeyF key_accessor) {
    ptree filtered;
    std::map<std::string, std::reference_wrapper<ptree> > seen;
    for (auto entry = pt.rbegin(), last = pt.rend(); entry != last; ++entry) {
        auto key      = key_accessor(*entry);
        auto previous = seen.find(key);
        if (seen.end() == previous)
            seen.emplace(key, filtered.add_child(entry->first, entry->second));
    }
    return filtered;
}

但是,请记住这可能会改变果实出现在子树中的顺序。

最新更新