我有以下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读取所有的孩子吗?
提前谢谢。
发布于 2017-11-30 17:16:22
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", "");
}
}
发布于 2018-06-02 08:20:32
检查此示例:
#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;
}
https://stackoverflow.com/questions/47568808
复制相似问题