【问题标题】:Using Boost to read and write XML files使用 Boost 读写 XML 文件
【发布时间】:2010-11-05 18:49:28
【问题描述】:

有没有什么好的方法(也有简单的方法)使用Boost来读写XML文件?

我似乎找不到任何简单的示例来使用 Boost 读取 XML 文件。你能给我一个简单的例子,它使用 Boost 来读写 XML 文件吗?

如果不是 Boost,有没有什么好的简单的读写 XML 文件的库可以推荐? (必须是 C++ 库)

【问题讨论】:

标签: c++ xml boost


【解决方案1】:

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

pugixml 最棒的地方在于对 XPath 的支持,这是 TinyXML 和 RapidXML 所缺乏的。

引用 RapidXML 的作者“我要感谢 Arseny Kapoulkine 在 pugixml 上所做的工作,这是这个项目的灵感来源”和“比 pugixml 快 5% - 30%,这是我所知道的最快的 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 相关问题除外)
  • 几乎不知道错误(它不会像你和我一样,像 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 或类似的东西。

【讨论】:

  • pugixml 现在有 UTF-8、UTF-16、UTF-32 解析。
  • @CristianAdam 我不知道它是否支持 SAX 解析或不...超过 4GiB 的内存。
  • TinyXpath 确实为 TinyXML 添加了 xpath 支持
  • @fizzbuzz 确实如此,但根据 TinyXPath 文档,“在 Linux 下,还没有库”。只有命令行工具。
  • pugixml 很好,但这并不能回答关于 Boost 的问题?
【解决方案2】:

TinyXML 可能是一个不错的选择。至于升压:

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

Daniel Nuffer 为 Boost Spirit 实现了 xml parser

【讨论】:

  • 另外,使用 TinyXpath 和 TinyXML
【解决方案3】:

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

【讨论】:

  • 另外,使用 TinyXpath 和 TinyXML
【解决方案4】:

Boost 使用RapidXML,如chapter XML Parser of page How to Populate a Property Tree 中所述:

不幸的是,截至撰写本文时,Boost 中还没有 XML 解析器。 因此,该库包含快速而小巧的 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);
}

【讨论】:

    【解决方案5】:

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

    Easier XML with Boost

    【讨论】:

    • 有趣的是,在对 XML & Boost 进行搜索后,我正要发布这个确切的链接。
    【解决方案6】:

    在 boost 中没有用于 XML 解析的特定库,但是有很多替代方案,这里有几个: libxml, Xerces, Expat

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

    这里是a whole article IBM 的主题。

    【讨论】:

      【解决方案7】:

      Boost 不提供 XML 解析器 atm。

      Poco XML(Poco C++ libs 的一部分)既好又简单。

      【讨论】:

      • 我无法评论 Poco C++ 库的质量,但在风格上它与 Boost 非常不同。对于想要与其他 Boost 组件和 STL 进行良好互操作的人来说,这可能不是一个很好的匹配。我不是指命名约定(尽管它们可能会令人讨厌);而是大量使用继承、虚函数以及缺少字符类型的模板。这些设计决策可能会或可能不会变得更好;但它们肯定与 Boost 和 STL 完全不同。
      【解决方案8】:

      一定要使用 TinyXML *竖起大拇指*

      【讨论】:

        【解决方案9】:

        如果您只是在寻找 DOM 功能,则此线程中已有一些建议。我个人可能不会为缺乏 XPath 支持的库而烦恼,而在 C++ 中,会使用 Qt。还有 TinyXPath,Arabica 声称支持 XPath,但我对此无话可说。

        【讨论】:

          【解决方案10】:

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

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

          关于 RapidXML 的有趣链接。我去看看。

          【讨论】:

            【解决方案11】:

            看看Arabica

            【讨论】:

              【解决方案12】:

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

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

              【讨论】:

              • 嗨,我已经尝试过 pugixml,并且该库的最大问题(当然对我来说)是缺少一些将模式转换为 C++ 的工具,所以我回到“重" xerces :) 并与这个很有趣的codesynthesis.com/projects/xsd 一起使用
              【解决方案13】:

              有一个 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

              【讨论】:

                【解决方案14】:
                <?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;
                }
                

                【讨论】:

                  【解决方案15】:

                  boost.spirit 呢?

                  Here,他们展示了一个“Mini XML”解析器

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 2013-03-16
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2017-01-12
                    相关资源
                    最近更新 更多