在没有附加库的情况下,在标准C/C++中解析XML

Parse an XML in standard C/C++ without additional libraries

本文关键字:C++ XML 标准 情况下      更新时间:2023-10-16

我有一个XML(假设它是有效的),我必须解析它并将其存储在树中。

在不使用其他库的情况下,只使用字符串的基本操作,解析它的最佳方法是什么

请记住,我不必验证它,只需将它解析并记忆到树中即可。

XML的基本结构非常简单:

<tagname [attribute[="value"] ...]>content</tagname>

其中内容可以包含普通文本和更多的XML结构,或者特殊形式的

<tagname [attribute[="value"] ...]/>

相当于

<tagname [attribute[="value"] ...]></tagname>

也就是说,。空内容。

因此,如果您不需要解释DTD或做其他花哨的事情,您可以执行以下操作:

  1. 检查第一个非空白字符是否为<。如果没有,那么您就没有XML,只能给出一个错误并退出。

  2. 现在跟随标签名称,直到第一个空格,或者/>字符。把它储存起来。

  3. 如果下一个非空白字符是/,请检查它后面是否跟有>。如果是,那么您已经完成了解析,可以返回结果。否则,您将得到格式错误的XML,并且可能会退出并返回错误。

  4. 如果字符是>,那么您已经找到了begin标记的末尾。下面是内容。继续执行步骤6。

  5. 否则,接下来就是一场争论。对其进行分析,存储结果,然后继续执行步骤3。

  6. 阅读内容,直到找到<字符。

  7. 如果该字符后面跟有/,那么它就是结束标记。检查后面是否跟有标签名称和>,如果是,则返回结果。否则,抛出一个错误。

  8. 如果您到达这里,您已经找到了嵌套XML的开始。用这个算法分析它,然后在6继续。

阅读XML看起来很简单,但正确阅读会涉及到一些你并不想处理的复杂性。实际上,编写一个简单的XML解析器实际上相当于创建另一个XML库。我已经完成了,我的磁盘上有一个不完整的版本。即使您不需要验证您的XML结构:

  • 无论是否验证,都需要处理像&lt;这样的实体引用以及像&#65;&#xa;这样的各种字符实体引用
  • XML文档的纯体相对简单,但头是处理DTD的主要难点:有两个版本略有不同,您可能需要处理内联DTD
  • 由于这些令人讨厌的字符数据段,即使是主体也并非完全微不足道
  • 即使没有验证,您也可能需要支持外部实体引用
  • XML的各个部分要接受和/或拒绝的字符也有些有趣
  • 请注意,XML是根据Unicode定义的,正确处理这一点也并非易事:仅仅使用charwchar_t并不能解决问题

我实现的第一个版本是一个不错的小迭代器,旨在弹出遇到的所有元素。这使得可以根据迭代器用户的选择轻松地停止和继续解析。不幸的是,在尝试使用各种实体引用进行复制时,我并没有让它飞起来。它可以很好、快速地解析简单的XML文件,但规范中的一些怪癖我没有理解。

对我来说效果最好的是创建一个简单的递归体面的解析器,并结合一个合适的缓冲区堆栈,在某种程度上透明地处理实体引用。然而,要完全完成这项工作,我仍然需要处理一些编码问题,最终我只有更高优先级的项目要做(也就是说,在业余时间)。

总之:很明显,这是可以做到的,就像其他人一样。这可能是一个毫无意义的练习,除非你有一个真正聪明的想法,使你的实现比替代方案更适合。

最好且仅方法是在不使用任何其他库的情况下从头开始重新实现这样的库。。。

例如,欢迎您使用pugixml等现有库。它的安装很简单,只需将文件添加到项目中并开始使用即可。与Xerces等其他验证解析器相比,它是轻量级的。