子路径处理Boost.PropertyTree [英] Boost.PropertyTree subpath processing

查看:183
本文介绍了子路径处理Boost.PropertyTree的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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.

推荐答案

这样的函数不存在。

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

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;
}

现在你可以这样写:

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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆