使用Boost读写XML文件

时间:2009-06-25 09:23:21

标签: c++ xml boost

使用Boost读取和写入XML文件有什么好方法(也是一种简单的方法)吗?

我似乎无法使用Boost找到任何简单的示例来读取XML文件。您能指出一个使用Boost读取和编写XML文件的简单示例吗?

如果不是Boost,是否有任何好的和简单的库可以读取和编写您可以推荐的XML文件? (它必须是C ++库)

15 个答案:

答案 0 :(得分:63)

你应该尝试pugixml 轻量级,简单快速的C ++ XML解析器

关于pugixml的最好的事情是 XPath 支持,TinyXML和RapidXML缺乏。

引用RapidXML的作者“我要感谢Arseny Kapoulkine在pugixml上的工作,这是该项目的灵感”并且比pugixml快5%-3%,这是我所知道的最快的XML解析器“他已经测试过针对pugixml的0.3版,已达到最近版本0.42。

以下是pugixml文档的摘录:

主要特点是:

  • 低内存消耗和碎片化(胜过pugxml约为1.3倍,TinyXML - 约2.5倍,Xerces(DOM) - 约4.3倍1)。在与现有解析器部分的比较中可以看到确切的数字。
  • 极高的解析速度(胜过pugxml约6倍,TinyXML - 约10倍,Xerces-DOM - 约17.6倍1
  • 极高的解析速度(好吧,我正在重复自己,但速度非常快,在测试XML上它比Expat高出2.8倍)2
  • 或多或少符合标准(它将正确解析任何符合标准的文件,但DTD相关问题除外)
  • 几乎没有错误(它不会像You& Me那样窒息,就像expat一样;它会用错误编码的数据解析文件;依此类推)
  • 干净的界面(一个重构的pugxml的一个)
  • 或多或少地识别Unicode(实际上,它假定输入数据的UTF-8编码,尽管它很容易使用ANSI - 现在没有UTF-16(参见未来工作),带有辅助转换函数(UTF- 8<-> UTF-16/32(无论std :: wstring& wchar_t的默认值是什么))
  • 完全符合标准的C ++代码(由Comeau严格模式批准);该库是多平台的(参见平台列表参考)
  • 灵活性高。您可以通过解析选项控制文件解析和DOM树构建的许多方面。

好的,你可能会问 - 捕获的是什么?一切都很可爱 - 它是解析XML的小巧,快速,强大,干净的解决方案。缺什么?好的,我们是公平的开发人员 - 所以这是一个错误的列表:

  • 内存消耗。它击败了我所知道的每个基于DOM的解析器 - 但是当SAX解析器出现时,没有机会。您无法处理内存小于4 Gb的2 Gb XML文件 - 并且可以快速完成。虽然pugixml比其他所有基于DOM的解析器都表现得更好,所以如果你坚持使用DOM,那就不是问题了。
  • 内存消耗。好的,我在重复自己。再次。当其他解析器允许您在常量存储(或甚至作为内存映射区域)中提供XML文件时,pugixml将不会。因此,您必须将整个数据复制到非常量存储中。此外,它应该在解析器的生命周期中持续存在(其原因和更多关于生命期的内容写在下面)。再说一次,如果你对DOM没问题 - 这应该不是问题,因为整体内存消耗较少(好吧,虽然你需要一块连续的内存,这可能是一个问题)。
  • 缺乏验证,DTD处理,XML命名空间,正确处理编码。如果你需要那些 - 请使用MSXML或XercesC或类似的东西。

答案 1 :(得分:23)

TinyXML可能是个不错的选择。至于Boost:

Property_Tree中有Boost Repository个库。它已被接受,但目前似乎缺乏支持(编辑:Property_Tree现在是Boost since version 1.41的一部分,关于其XML功能阅读the documentation。)

Daniel Nuffer为Boost Spirit实施了xml parser

答案 2 :(得分:16)

还有TinyXML,这是一个不错的小C ++库。如果您正在寻找一个较低级别的库,RapidXML是一个很好的起点。

答案 3 :(得分:10)

提升使用RapidXML中描述的chapter XML Parser of page How to Populate a Property Tree

  

不幸的是,截至撰写本文时,XML中没有Boost解析器。   因此,该库包含快速且小巧的RapidXML解析器(目前在   版本1.13)提供XML解析支持。 RapidXML并不完全支持   XML标准;它无法解析DTD,因此无法解析   完全实体替代。

另请参阅XML boost tutorial

由于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's homepage

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

答案 4 :(得分:4)

在XML解析的提升中没有特定的库,但是有很多替代方案,这里有几个: libxmlXercesExpat

当然,您可以使用boost中的其他一些库来帮助您创建自己的库,但这可能是一项艰巨的任务。

这是IBM关于这个问题的a whole article

答案 5 :(得分:4)

Boost不提供XML解析器atm。

Poco XML(Poco C++ libs的一部分)非常简单。

答案 6 :(得分:4)

似乎boost序列化可以读取和写入XML中的存档,如果这足以满足您的需要。

Easier XML with Boost

答案 7 :(得分:3)

明确使用TinyXML *竖起大拇指*

答案 8 :(得分:2)

查看Arabica

答案 9 :(得分:2)

如果您只是在寻找DOM功能,那么此主题中已有一些建议。我个人可能不会打扰缺乏XPath支持的库,而在C ++中,会使用Qt。还有TinyXPath,阿拉比卡声称有XPath支持,但我不能对这些做任何事情。

答案 10 :(得分:1)

根据我在Boost邮件列表中潜伏的经验,似乎每当XML出现作为主题时,它都会被转移到关于Unicode的讨论中。但是,由于现在有一个潜在的Unicode库迫在眉睫,我认为XML库不会花太长时间出现在那里。

与此同时,我也一直在使用TinyXML。

有关RapidXML的有趣链接。我会看一下。

答案 11 :(得分:1)

警告。我喜欢RapidXML,但在解析UTF16时它有一个非常讨厌的错误。一些有效值会导致崩溃。

我很乐意推荐pugixml - 但它缺少命名空间支持,我知道这会给我带来麻烦。

答案 12 :(得分:1)

有一项GSoC提议工作要改进现有的Boost.XML提案:https://github.com/stefanseefeld/boost.xml但是Andrzej建议Boost.PropertyTree很适合这项任务。具体取决于xml大小和所需的验证支持。

最近在Boost邮件列表中提出了一个图书馆: http://www.codesynthesis.com/projects/libstudxml/doc/intro.xhtml

答案 13 :(得分:0)

boost.spirit怎么样?

Here,他们会显示“迷你XML ”解析器

答案 14 :(得分:0)

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