【问题标题】:Boost.PropertyTree subpath processingBoost.PropertyTree 子路径处理
【发布时间】: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;

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

【问题讨论】:

    标签: c++ boost boost-propertytree


    【解决方案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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-05
      • 2015-01-30
      • 2021-08-09
      相关资源
      最近更新 更多