我应该在C ++中使用什么XMLparsing器?

我有XML文档,我需要parsing和/或我需要build立XML文档,并将其写入文本(文件或内存)。 由于C ++标准库没有这个库,我应该使用什么?

注意:这是一个明确的,C ++ – FAQ风格的问题。 所以是的,这是其他人的重复。 我不是简单地适合那些其他的问题,因为他们倾向于要求更具体的东西。 这个问题更通用。

就像标准库容器一样,你应该使用什么库取决于你的需求。 这是一个方便的stream程图:

在这里输入图像描述

所以第一个问题是: 你需要什么?

我需要完整的XML合规性

好的,所以你需要处理XML。 不玩XML, 真正的 XML。 您需要能够读取和写入所有的XML规范,而不仅仅是低位的,易于parsing的位。 您需要命名空间,DocTypes,实体replace,作品。 完整的W3C XML规范。

接下来的问题是: 你的API是否需要符合DOM或SAX?

我需要准确的DOM和/或SAX一致性

好的,所以你真的需要API是DOM和/或SAX。 它不能只是一个SAX风格的推式parsing器,或者是一个DOM风格的保留parsing器。 它必须是实际的DOM或实际的SAX,只要C ++允许。

你已经select:

的Xerces

这是你的select。 它几乎是唯一的C ++ XMLparsing器/书写器,它具有完整的(或接近C ++允许的)DOM和SAX一致性。 它还具有XInclude支持,XML Schema支持以及其他许多function。

它没有真正的依赖性。 它使用Apache许可证。

我不关心DOM和/或SAX一致性

你已经select:

libxml2的

LibXML2提供了一个C风格的界面(如果真的让你感到困扰,就去使用Xerces),尽pipe这个界面至less有一些基于对象的容易包装。 它提供了许多function,比如XInclude支持(带callback,以便你可以告诉它从哪里获取文件),XPath 1.0识别器,RelaxNG和Schematron支持(虽然错误消息有很多不足之处),等等。

它确实对iconv有依赖性,但是可以在没有依赖关系的情况下进行configuration。 虽然这确实意味着你可以parsing更多的可能的文本编码。

它使用MIT许可证。

我不需要完整的XML合规性

好的,如此完整的XML合规性对您无关紧要。 您的XML文档完全在您的控制之下,或者保证使用XML的“基本子集”:没有名称空间,实体等

那么对你有什么影响? 接下来的问题是: 在你的XML工作中,对你来说最重要的什么?

最大的XMLparsing性能

您的应用程序需要将XML转换为C ++数据结构,并尽可能快地进行转换。

你已经select:

RapidXML

这个XMLparsing器正是它所说的:快速XML。 它甚至不涉及将文件拉入内存; 这是怎么回事呢? 它所处理的是将其parsing为一系列可以访问的C ++数据结构。 而且它的执行速度与逐字节地扫描文件所花费的时间一样快。

当然,没有免费的午餐。 像大多数不关心XML规范的XMLparsing器一样,Rapid XML不会触及命名空间,DocType,实体(除了字符实体和6个基本的XML实体),等等。 所以基本上是节点,元素,属性等。

另外,它是一个DOM风格的parsing器。 所以它需要你阅读所有的文本。但是,它没有做的是复制任何文本(通常)。 RapidXML获得最大速度的方式是通过就地引用string。 这需要更多的内存pipe理(当RapidXML正在查看时,您必须保持该string的存在)。

RapidXML的DOM是毫不起眼的。 你可以得到string值的东西。 您可以按名称search属性。 就是这样。 没有便利function将属性转换为其他值(数字,date等)。 你只是得到string。

使用RapidXML的另外一个缺点是编写 XML是很痛苦的。 它需要你做很多显式的内存分配的string名称才能构build它的DOM。 它确实提供了一种string缓冲区,但仍然需要大量的显式工作。 这当然是function性的,但这是一个痛苦的使用。

它使用MIT许可证。 这是一个只有标题的库,没有依赖关系。

  • 有一个RapidXML的“GitHub补丁” ,允许它也可以使用命名空间。

我关心的performance,但不是很多

是的,性能对你很重要。 但是,也许你需要less一点骨子里的东西。 也许有些东西可以处理更多的Unicode,或者不需要这么多的用户控制的内存pipe理。 性能仍然是重要的,但是你想要的东西不那么直接。

你已经select:

PugiXML

从历史上看,这是RapidXML的灵感来源。 但是这两个项目已经发生了分歧,Pugi提供了更多的function,而RapidXML则完全侧重于速度。

PugiXML提供了对Unicode转换的支持,所以如果你有一些UTF-16文档,并且想把它们作为UTF-8读取,Pugi会提供。 它甚至有一个XPath 1.0实现,如果你需要这样的事情。

但普吉还是挺快的 像RapidXML一样,它没有依赖性,在MIT许可证下分发。

阅读巨大的文件

您需要阅读以千兆字节为单位测量的文档。 也许你从标准input中得到它们,被其他进程所吸引。 或者你正在阅读大量的文件。 pipe他呢。 重点是,你需要的是不必一次将整个文件读入内存,以便处理它。

你已经select:

libxml2的

Xerces的SAX风格的API将以这种方式工作,但是LibXML2在这里是因为使用起来更容易一些。 一个SAX风格的API是一个push-API:它开始分析一个stream,只是触发事件,你必须赶上。 你被迫pipe理上下文,状态等等。 读取SAX风格API的代码比人们希望的要多得多。

LibXML2的xmlReader对象是一个pull-API。 您要求转到下一个XML节点或元素; 你没有被告知。 这允许您按照您认为合适的方式来存储上下文,以便在代码中处理不同实体的方式比在一堆callback中更具可读性。

备择scheme

外籍人士

Expat是一个使用pull-parser API的着名的C ++parsing器。 它是由詹姆斯·克拉克写的。

目前的状态是…不活跃。 最近的版本是3年前发布的2.1.0。 这并不意味着它不可用。 但这确实意味着,如果有错误, 将不得不修复它们。

你仍然可以使用它。 只要知道你所得到的。

LlamaXML

它是一个StAX风格的API的实现。 这是一个pull-parser,类似于LibXML2的xmlReaderparsing器。

但是自从2005年以来它一直没有更新。所以再次,警告Emptor。

XPath支持

XPath是查询XML树中的元素的系统。 使用标准化语法,通过公共属性有效地命名元素或元素集合是一种方便的方法。 许多XML库提供XPath支持。

这里有三个有效的select:

  • LibXML2 :它提供了完整的XPath 1.0支持。 再次,它是一个C API,所以如果这困扰你,有其他select。
  • PugiXML :它也支持XPath 1.0。 如上所述,它比LibXML2更像是一个C ++ API,所以你可能更喜欢它。
  • TinyXML :它不支持XPath,但有TinyXPath库提供它。 TinyXML正在转换到2.0版本,这会显着改变API,所以TinyXPath可能无法使用新的API。 就像TinyXML本身一样,TinyXPath是在zLib许可下分发的。

只是完成工作

所以,你不关心XML的正确性。 性能不是你的问题。 stream式传输是无关紧要的。 所有你想要的是将XML存入内存,并允许你再次将其粘贴到磁盘上。 关心的是API。

你想要一个XMLparsing器,这个parsing器很小,易于安装,使用起来很小,而且足够小,与你的最终可执行文件的大小无关。

你已经select:

TinyXML的

我把TinyXML放在这个插槽中,因为它就像XMLparsing器得到的那样简单易用。 是的,这很慢,但很简单明显。 它有很多方便的function来转换属性等等。

在TinyXML中编写XML是没有问题的。 您只需要new一些对象,将它们连接在一起,将文档发送到std::ostream ,大家都很开心。

TinyXML还有一些生态系统,它们具有更好的迭代器友好的API,甚至还有一个XPath 1.0实现。

TinyXML使用zLib许可证,这或多或less是MIT许可证的不同名称。

还有另一种处理XML的方法,您可能需要考虑,称为XML数据绑定。 特别是如果您已经有了XML词汇表的正式说明,例如在XML模式中。

XML数据绑定允许您使用XML,而无需实际执行任何XMLparsing或序列化。 数据绑定编译器会自动生成所有低级代码,并将parsing的数据显示为与您的应用程序域对应的C ++类。 然后通过调用函数和使用C ++types(int,double等)来处理这些数据,而不是比较string和parsing文本(这就是使用低级XML访问API(如DOM或SAX)所做的工作)。

例如,参见我编写的开源XML数据绑定实现CodeSynthesis XSD,以及用于轻量级无依赖版本CodeSynthesis XSD / e的实现 。

把我的。

http://www.codeproject.com/Articles/998388/XMLplusplus-version-The-Cplusplus-update-of-my-XML

没有XMLvalidationfunction,但速度很快。

在Secured Globe ,Inc.我们使用rapidxml 。 我们尝试了所有其他的,但rapidxml似乎是我们的最佳select。

这里是一个例子:

  rapidxml::xml_document<char> doc; doc.parse<0>(xmlData); rapidxml::xml_node<char>* root = doc.first_node(); rapidxml::xml_node<char>* node_account = 0; if (GetNodeByElementName(root, "Account", &node_account) == true) { rapidxml::xml_node<char>* node_default = 0; if (GetNodeByElementName(node_account, "default", &node_default) == true) { swprintf(result, 100, L"%hs", node_default->value()); free(xmlData); return true; } } free(xmlData); 

另外一个关于Expat的说明:值得关注的是embedded式系统的工作。 但是,您可能在networking上find的文档是古老而错误的。 源代码实际上有相当全面的function级别的评论,但是需要仔细阅读它们才有意义。