Boost 和 xml 解析

Posted

技术标签:

【中文标题】Boost 和 xml 解析【英文标题】:Boost and xml parsing 【发布时间】:2017-11-30 08:20:18 【问题描述】:

我有以下 xml 数据,我想通过 boost xml 解析器进行解析。

<?xml version="1.0" encoding="UTF-8"?>
<applications>
    <application>
            <id>1</id>
            <platform>linux-x64</platform>
            <version>2.4</version>
    </application>
    <application>
            <id>2</id>
            <platform>windows</platform>
            <version>2.5</version>
    </application>
    <application>
            <id>3</id>
            <platform>linux</platform>
            <version>2.6</version>
    </application>
</applications>

我在下面编写了 boost 代码,但我只读取了“应用程序”的第一个孩子,而无法阅读其他两个孩子。每次内循环获取第一个孩子的数据。

boost::property_tree::ptree pt;
boost::property_tree::read_xml(sModel, pt); // sModel is filename which contains above xml data

BOOST_FOREACH(boost::property_tree::ptree::value_type &v, pt.get_child("applications"))

    std::string key = v.first.data();       
    std::string Id, platform, version;

    if (key == std::string("application"))
    
        BOOST_FOREACH(boost::property_tree::ptree::value_type &v_, pt.get_child("applications.application"))
        
            std::string app_key = v_.first.data();
            std::string app_value = v_.second.data();

            if (app_key == std::string("id"))
                pkgId = app_value;
            else if (app_key == std::string("platform"))
                platform = app_value;
            else if (app_key == std::string("version"))
                version = app_value;
        
    

在这里,每次我将平台设为“linux-x64”。 有人可以指导如何通过这个 boost xml 阅读所有孩子吗?

提前致谢。

【问题讨论】:

没有真正的 Boost XML 解析器。 PropertyTree 对通过修改后的 RapidXML 解析器从 XML 加载提供了一些基本支持,但它不支持大部分 XML,而且正如您所见,在访问数据时有点不确定。 @SebastianRedl 感谢您传播福​​音。我很高兴它已成为常识。我不会说数据访问是不确定的。事实上,它非常适合访问属性。 (参见例如avoiding loop frenzy 和translators)。 【参考方案1】:

get_child(以及所有其他基于路径的访问函数)不太擅长处理多个相同的键。它将选择具有给定密钥的第一个孩子并返回,忽略所有其他孩子。

但是你不需要get_child,因为你已经把你想要的节点拿在手上了。

pt.get_child("applications") 给你一个ptree。迭代它会给你一个ptree::value_type,它是一个std::pair&lt;std::string, ptree&gt;

那么,第一个奇怪的事情就是这一行:

std::string key = v.first.data();

您在这里调用的data() 函数是std::string::data,而不是ptree::data。你可以写

std::string key = v.first;

接下来奇怪的是比较:

if (key == std::string("application"))

您无需在此处显式构造std::string。实际上,这样做是一种悲观,因为它必须分配一个字符串缓冲区并将字符串复制到那里,而std::string 具有 C 风格字符串的比较运算符。

然后你迭代 pt.get_child("applications.application"),但你不需要做这个查找 - v.second 已经是你想要的树。

此外,您根本不需要遍历孩子,您可以使用它的查找函数来获取您需要的内容。

std::string pkgId = v.second.get("id", "");

总而言之,这是我要写的代码:

boost::property_tree::ptree pt;
boost::property_tree::read_xml(sModel, pt);

BOOST_FOREACH(boost::property_tree::ptree::value_type &v, pt.get_child("applications"))

    // You can even omit this check if you can rely on all children
    // being application nodes.
    if (v.first == "application")
    
        std::string pkgId = v.second.get("id", "");
        std::string platform = v.second.get("platform", "");
        std::string version = v.second.get("version", "");
    

【讨论】:

感谢 Sebastian 的详细回复。我已经尝试了您提供的总结代码,但每次它打印“id:1”。平台:linux-x64 和版本:2.4。有什么想法吗? 至少打印三遍吗?我目前没有带 Boost 的计算机,因此无法调试我的代码。 是的。它打印了三遍。 是的。工作正常。我在阅读文件方面的错。非常感谢您的回复。【参考方案2】:

检查这个例子:

#include <boost/property_tree/xml_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/foreach.hpp>

struct Application

    int          m_id
    std::string  m_platform;
    float        m_version;
;

typedef std::vector<Application> AppList;

AppList Read()

    using boost::property_tree::ptree;

    // Populate tree structure (pt):

    ptree pt;
    read_xml("applications.xml", pt); // For example.

    // Traverse pt:

    AppList List;
    BOOST_FOREACH(ptree::value_type const& v, pt.get_child("applications"))
    
        if (v.first == "application")
        
            Application App;
            App.id = v.second.get<int>("id");
            App.platform = v.second.get<std::string>("platform");
            App.version = v.second.get<float>("version");

            List.push_back(App);
        
    

    return List;

【讨论】:

一般来说,如果答案包含对代码的用途的解释,以及为什么在不介绍其他人的情况下解决问题的原因,答案会更有帮助。 页面顶部的请求是:“我有以下xml数据,我想通过boost xml解析器解析”。因此,代码打算解析给定的 XML 文件,列出“应用程序”(对于每个应用程序:id、平台和版本),并返回列表。

以上是关于Boost 和 xml 解析的主要内容,如果未能解决你的问题,请参考以下文章

Boost属性树xml解析No such node()

如何使 boost ptree 以相同的方式解析 xml 和 json?

boost中的属性是如何解析的?肥皂xml解析?

使用boost解析xml

使用 Boost 属性树解析 SVG (XML)

使用 boost 属性树解析 XML