Boost.PropertyTree 子路径处理

Posted

技术标签:

【中文标题】Boost.PropertyTree 子路径处理【英文标题】:Boost.PropertyTree subpath processing 【发布时间】:2015-03-22 19:27:50 【问题描述】:

以下是我想用Boost.PropertyTree 库处理的实际 xml 的简化示例。实际上,原始 xml 文件中还有很多其他字段

<?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>

我需要遍历所有link 标签。有一个所需代码的示例。

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;

这对于简单的目的来说太丑陋了。 有没有办法简化它?例如,我可以等待下一个代码有效:

for (auto item: pt.get_child("foo.bar.item.link"))
  std::cout << item.second.get_value<std::string>() << std::endl;

此代码不起作用,但它说明了我想要得到什么。

【问题讨论】:

【参考方案1】:

这样的功能不存在。

坦率地说,如果您想要 XPath,只需使用支持它的库即可:

#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";

否则,您总是可以自己努力:

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;

现在你可以把它写成例如:

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"));

打印

http://www.one.com
http://www.two.net
http://www.sex.gov

【讨论】:

以上是关于Boost.PropertyTree 子路径处理的主要内容,如果未能解决你的问题,请参考以下文章

迭代一些空树时,Boost.PropertyTree 崩溃

boost propertyTree

Boost/Property Tree 确定值类型

C++使用boost 1.75版本来读写JSON文件

当值部分不存在时使用 Boost 属性树读取 INI 文件

TinyXML2的快速实践