问题
The following is a reduced sample of actual xml I would like to process with Boost.PropertyTree
library. Actually, there are a lot of other fields in an original xml-file
<?xml version="1.0" encoding="UTF-8"?>
<foo>
<bar>
<item>
<link>http://www.one.com</link>
</item>
<item>
<link>http://www.two.net</link>
</item>
<item>
<link>http://www.sex.gov</link>
</item>
...
</bar>
</foo>
I need to iterate through all link
tags. There is an example of the required code.
for (auto item: pt.get_child("foo.bar"))
if ("item" == item.first)
for (auto prop: item.second)
if ("link" == prop.first)
std::cout << prop.second.get_value<std::string>() << std::endl;
This is too ugly code for simple purpose. Is there a way to simplify it? For example, I could wait next code to be valid for the purpose:
for (auto item: pt.get_child("foo.bar.item.link"))
std::cout << item.second.get_value<std::string>() << std::endl;
This code does not work, but it illustrates, what I would like to get.
回答1:
Such a function doesn't exist.
Frankly, if you want XPath, just use a library that supports it:
#include <pugixml.hpp>
#include <iostream>
int main() {
pugi::xml_document doc;
doc.load(std::cin);
for (auto item: doc.select_nodes("//foo/bar/item/link/text()"))
std::cout << "Found: '" << item.node().value() << "'\n";
}
Otherwise, you can always make the effort yourself:
template <typename Tree, typename Out, typename T = std::string>
Out enumerate_path(Tree const& pt, typename Tree::path_type path, Out out) {
if (path.empty())
return out;
if (path.single()) {
*out++ = pt.template get<T>(path);
} else {
auto head = path.reduce();
for (auto& child : pt)
if (child.first == head)
out = enumerate_path(child.second, path, out);
}
return out;
}
Now you can write it as e.g.:
Live On Coliru
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <iostream>
template <typename Tree, typename Out, typename T = std::string>
Out enumerate_path(Tree const& pt, typename Tree::path_type path, Out out) {
if (path.empty())
return out;
if (path.single()) {
*out++ = pt.template get<T>(path);
} else {
auto head = path.reduce();
for (auto& child : pt)
if (child.first == head)
out = enumerate_path(child.second, path, out);
}
return out;
}
int main() {
using namespace boost::property_tree;
ptree pt;
read_xml("input.txt", pt);
enumerate_path(pt, "foo.bar.item.link",
std::ostream_iterator<std::string>(std::cout, "\n"));
}
Prints
http://www.one.com
http://www.two.net
http://www.sex.gov
来源:https://stackoverflow.com/questions/29198853/boost-propertytree-subpath-processing