【发布时间】:2013-01-24 16:43:19
【问题描述】:
我有以下 XML 文件:
<?xml version="1.0" encoding="utf-8"?>
<gexf>
<graph>
<nodes>
<node id="0" label="0" start="0" end="25"/>
<node id="1" label="1" start="1"/>
<node id="2" label="2" start="2"/>
...
</nodes>
<edges>
<edge id="0" source="0" target="1" start="7" end="19"/>
<edge id="1" source="0" target="2" start="8" end="20"/>
...
</edges>
</graph>
</gexf>
我想从带有source="0" 和target="1" 的边缘删除start 和end 属性。
我尝试这样做的方法是在以下代码中。假设 XML 文件名为 ptree_test.gexf,我将其读入,在树中找到正确的边,然后尝试使用 erase 去除属性。
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <iostream>
using boost::property_tree::ptree;
int main(int argc, char *argv[]) {
ptree pt;
read_xml("ptree_test.gexf", pt);
// Now find edge (0, 1) and delete the start and end attributes
ptree edge;
int id1, id2;
id1 = 0;
id2 = 1;
for(auto &e : pt.get_child("gexf.graph.edges")) {
int s, t;
s = e.second.get<int>("<xmlattr>.source");
t = e.second.get<int>("<xmlattr>.target");
// Check if this is the correct edge
// Two checks because it can be reversed
if((id1 == s && id2 == t) || (id1 == t && id2 == s)) {
edge = e.second;
break;
}
}
for(auto & attr : edge.get_child("<xmlattr>")) {
if(attr.first == "end" || attr.first == "start") {
edge.erase(attr.first);
}
}
write_xml(std::cout, pt);
return 0;
}
这不起作用。它不会删除该属性。事实上,如果我输入一个打印返回 edge.erase(attr.first) 的调试语句,它会显示 0。
【问题讨论】:
-
Boost.PropertyTree 不是一个快速而简单的 XML 解析器。不要像现在这样对待它。 XML 序列化程序用于存储和取消存储数据。它并不意味着以任意方式加载或修改 XML。简而言之,如果您需要操作 GEFX XML 文件,use a real XML parser.
-
@NicolBolas 我实际上从未阅读过该文件。我只是这样写了这个例子,因为它使它更短更容易理解。在我的库中,我在内存中编写 XML 文件,然后在完成后将其写出。在此过程中,可能会出现我需要以指定方式更改它的情况。我正在使用 boost 属性树,因为 boost 已经是我的库的依赖项。而不是引入另一个依赖项,我想我会坚持使用它来处理 XML 的东西。如果这是不可能的,我会使用别的东西。你是说这是不可能的吗?
标签: c++ c++11 boost boost-propertytree