gpt4 book ai didi

c++ - 遍历不包含标签名称的 PTree 子项

转载 作者:行者123 更新时间:2023-12-02 10:11:42 28 4
gpt4 key购买 nike

我想知道是否有一种方法可以通过遍历父节点的 vector 来获取子节点中的数据。我有一个我计划经常更改的 XML 文件,因此我想避免对属性名称进行硬编码。因此,我想在我的子节点中提取数据而不使用 pt.get_child(myparentNodes) 说明节点的标签名称。 .我主要有这个。
非常感谢任何帮助!

vector<string> parentNodes;
ptree pt;
ifstream fileName("myxml");
read_xml(fileName, pt);

for(const ptree::value_type &parent : pt)
{
cout << parent.first << std::endl;
parentNodes.push_back(parent.first);

}
for(int i=0; i<parentNodes.size();i++)
{
BOOST_FOREACH(boost::property_tree::ptree::value_type const &node,pt.get_child(parentNodes[i]))

/* I'm having trouble properly accessing the children nodes here */

最佳答案

在您的代码段中(稍微清理一下):

std::vector<std::string> parentNodes;
for(auto const& parent : pt) {
std::cout << parent.first << std::endl;
parentNodes.push_back(parent.first);
}
似乎正在将树节点的名称收集到 parentNodes .但是,这假定名称是唯一的或非空的。

Property names need not be unique, nor are they guaranteed to be non-empty. In fact arrays in Property Tree are frequently modeled as nodes with only unnamed child nodes.


那么你在获取相应节点的子节点时遇到了麻烦。让我们首先以乏味的方式进行(再次假设名称是唯一的):
for (size_t i = 0; i < parentNodes.size(); i++) {
auto& parent = pt.get_child(parentNodes[i]);

for (auto const& child : parent) {
std::cout << child.first << std::endl;
}
}
当然使用 ranged-for 要容易得多:
for (auto const& name : parentNodes) {
auto& parent = pt.get_child(name);

for (auto const& child : parent) {
std::cout << child.first << std::endl;
}
}
更好的是
您可以避免关于命名以及第二个循环和 vector 存储的假设:
for (auto const& parent : pt) {
std::cout << parent.first << std::endl;

auto& node = parent.second;
for (auto const& child : node) {
std::cout << child.first << std::endl;
}
}
这是因为迭代器指向一对 (key, value) .事实上,在最近的编译器上,您可以使用结构化绑定(bind)编写循环:
for (auto const& [name, node] : pt) {
std::cout << name << std::endl;

for (auto const& child : node) {
std::cout << child.first << std::endl;
}
}
仍然在做同样的事情。
概括
你说你想让这个通用。但是,假设父/子关系的两层层次结构并不让我觉得“通用”。我将您链接到一些显示通用遍历的示例(例如,在整个树中寻找模式) last time ,例如 Iterating on xml file with boost - 该示例中的一个函数:
Live On Wandbox
#include <boost/property_tree/xml_parser.hpp>
#include <iostream>

using boost::property_tree::ptree;
static auto settings = boost::property_tree::xml_writer_make_settings<std::string>(' ', 4);

template <typename Out>
Out enumerate_nodes(ptree const& pt, ptree::path_type path, Out out) {
if (path.empty())
return out;

if (path.single()) {
auto name = path.reduce();
for (auto& child : pt) {
if (child.first == name)
*out++ = child.second;
}
} else {
auto head = path.reduce();
for (auto& child : pt) {
if (head == "*" || child.first == head) {
out = enumerate_nodes(child.second, path, out);
}
}
}

return out;
}

int main() {
std::ifstream fileName("input.xml");
ptree pt;
read_xml(fileName, pt);

for (auto const& [name, node] : pt) {
std::cout << name << std::endl;

for (auto const& child : node)
std::cout << child.first << std::endl;
}

std::vector<std::reference_wrapper<ptree const>> matched;
enumerate_nodes(pt, "root.parent2.child3", back_inserter(matched));

for (ptree const& match : matched)
std::cout << "Matched: " << match.get_value<std::string>() << "\n";
}
使用 input.xml 时:
<?xml version="1.0"?>
<root>
<parent1>
<child1>parent1/child1</child1>
<child2>parent1/child2</child2>
<child3>parent1/child3</child3>
<child4>parent1/child4</child4>
</parent1>
<parent2>
<child1>parent2/child1</child1>
<child2>parent2/child2</child2>
<child3>parent2/child3</child3>
<child4>parent2/child4</child4>
</parent2>
<parent3>
<child1>parent3/child1</child1>
<child2>parent3/child2</child2>
<child3>parent3/child3</child3>
<child4>parent3/child4</child4>
</parent3>
<parent4>
<child1>parent4/child1</child1>
<child2>parent4/child2</child2>
<child3>parent4/child3</child3>
<child4>parent4/child4</child4>
</parent4>
</root>
打印
root
parent1
parent2
parent3
parent4
Matched: parent2/child3

关于c++ - 遍历不包含标签名称的 PTree 子项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63288270/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com