Boost和XML解析

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (102)

我有以下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;
        }
    }
}

在这里,每次我得到的平台是“Linux64”。有人能指导如何通过这个Boost XML来读取所有的孩子吗?

提问于
用户回答回答于

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

但你不需要get_child,因为已经将想要的节点保存在手中。

pt.get_child("applications")给你一个ptree。迭代,这将为提供一个ptree::value_type,这是std::pair<std::string, ptree>

第一件奇怪的事,就是这句话:

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", "");
    }
}
用户回答回答于

请检查此示例:

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

扫码关注云+社区

领取腾讯云代金券