使用Boost来读写XML文件有什么好的方法(也是一种简单的方法)?
我似乎找不到任何简单的示例来使用Boost读取XML文件。您能指出一个使用Boost读写XML文件的简单示例吗?
如果没有Boost,是否有任何您可以推荐的良好简单的库来读写XML文件?(必须是C ++库)
Answers:
您应该尝试pugixml C ++的轻量,简单和快速的XML解析器
pugixml最好的东西是TinyXML和RapidXML缺少的XPath支持。
引用RapidXML的作者“我要感谢Arseny Kapoulkine在pugixml上所做的工作,这是该项目的灵感”,并且“比我知道的最快的XML解析器pugixml快5%-30%”,他已针对0.3版进行了测试的pugixml版本,最近已经达到0.42版。
以下是pugixml文档的摘录:
主要特点是:
好吧,你可能会问-有什么收获?一切都很可爱-它是用于解析XML的小型,快速,健壮,简洁的解决方案。什么东西少了?好的,我们是公平的开发人员-这是功能不全的清单:
TinyXML可能是一个不错的选择。至于升压:
Boost存储库中有Property_Tree库。它已经被接受,但是目前似乎缺乏支持(编辑:Property_Tree自1.41版以来就是Boost的一部分,请阅读有关其XML功能的文档)。
Daniel Nuffer为Boost Spirit实现了一个xml解析器。
Boost如页面如何填充属性树中的XML解析器一章所述使用RapidXML:
不幸的是,在撰写本文时,Boost中还没有XML解析器。因此,该库包含快速而纤巧的RapidXML解析器(当前版本为1.13),以提供XML解析支持。RapidXML不完全支持XML标准。它无法解析DTD,因此无法进行完整的实体替换。
另请参阅XML boost教程。
由于OP需要一种“使用boost读取和写入xml文件的简单方法”,因此我在下面提供了一个非常基本的示例:
<main>
<owner>Matt</owner>
<cats>
<cat>Scarface Max</cat>
<cat>Moose</cat>
<cat>Snowball</cat>
<cat>Powerball</cat>
<cat>Miss Pudge</cat>
<cat>Needlenose</cat>
<cat>Sweety Pie</cat>
<cat>Peacey</cat>
<cat>Funnyface</cat>
</cats>
</main>
(猫名来自Matt Mahoney的主页)
C ++中的相应结构:
struct Catowner
{
std::string owner;
std::set<std::string> cats;
};
read_xml()
用法:
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
Catowner load(const std::string &file)
{
boost::property_tree::ptree pt;
read_xml(file, pt);
Catowner co;
co.owner = pt.get<std::string>("main.owner");
BOOST_FOREACH(
boost::property_tree::ptree::value_type &v,
pt.get_child("main.cats"))
co.cats.insert(v.second.data());
return co;
}
write_xml()
用法:
void save(const Catowner &co, const std::string &file)
{
boost::property_tree::ptree pt;
pt.put("main.owner", co.owner);
BOOST_FOREACH(
const std::string &name, co.cats)
pt.add("main.cats.cat", name);
write_xml(file, pt);
}
Boost不提供XML解析器atm。
Poco XML(Poco C ++库的一部分)既好又简单。
一个警告。我喜欢RapidXML,但是在解析UTF16时有一个非常讨厌的错误。一些有效值导致它崩溃。
我想推荐pugixml-但它缺少名称空间支持,我知道这会给我带来麻烦。
有GSoC提出的工作来改进Boost.XML的现有提议:https : //github.com/stefanseefeld/boost.xml,但是正如Andrzej提出的Boost.PropertyTree可以很好地完成此任务。自然取决于xml大小和所需的验证支持。
最近在Boost Mailing List上还提议了一个库:http : //www.codesynthesis.com/projects/libstudxml/doc/intro.xhtml
<?xml version="1.0"?>
<Settings>
<GroupA>
<One>4</One>
<Two>7</Two>
<Three>9</Three>
</GroupA>
<GroupA>
<One>454</One>
<Two>47</Two>
<Three>29</Three>
</GroupA>
<GroupB>
<A>String A</A>
<B>String B</B>
</GroupB>
</Settings>
有一种使用BOOST读取XML的简单方法。这个例子是与std :: wstring:
#include <string>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/foreach.hpp>
bool CMyClass::ReadXML(std::wstring &full_path)
{
using boost::property_tree::wptree;
// Populate tree structure pt:
wptree pt;
std::wstringstream ss; ss << load_text_file(full_path); // See below for ref.
read_xml(ss, pt);
// Traverse pt:
BOOST_FOREACH(wptree::value_type const& v, pt.get_child(L"Settings"))
{
if (v.first == L"GroupA")
{
unsigned int n1 = v.second.get<unsigned int>(L"One");
unsigned int n2 = v.second.get<unsigned int>(L"Two");
unsigned int n3= v.second.get<unsigned int>(L"Three");
}
else if (v.first == L"GroupB")
{
std::wstring wstrA = v.second.get<std::wstring>(L"A");
std::wstring wstrB = v.second.get<std::wstring>(L"B");
}
};
}
读取属性稍微复杂一点。
--
仅供参考:
std::wstring load_text_file(std::wstring &full_path)
{
std::wifstream wif(full_path);
wif.seekg(0, std::ios::end);
buffer.resize(wif.tellg());
wif.seekg(0);
wif.read(buffer.data(), buffer.size());
return buffer;
}