您能帮我帮助我吗?
我填充了此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;
}
但是,请记住这可能会改变果实出现在子树中的顺序。