65.9K
CodeProject 正在变化。 阅读更多。
Home

简单的 C++ XML 解析器

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.56/5 (17投票s)

2010年9月21日

CPOL

5分钟阅读

viewsIcon

190057

downloadIcon

6705

一个仅具有基本功能的简单 C++ XML 解析器

引言

我写这篇文章是因为我需要一个基本的 XML 解析器,并且在互联网上找不到适合我需求的解析器(一个轻量级的解析器)。

现有的解析器的复杂性相当令人望而生畏,需要大量的知识才能理解。如果你不是一个经验丰富的 C++ 程序员,很难弄懂代码,如果你是,那你可能已经写了自己的解析器。

我编写了 parse 函数,然后是一系列用于存储解析数据的类,以及一个关于如何使用它的示例(基于 MFC 对话框和树状视图)。这个解析器非常简单,只有基本的功能,没有花哨的东西。它有一些限制。

  • 该解析器在一定程度上识别注释。如果 XML 文件中的任何注释出现在根节点之外,都会生成一个错误。
  • 截至 2010 年 9 月 29 日,已添加了一些 CDATA 支持。它仍然是有限的(例如
    //<![CDATA[
    将生成一个错误)。另外,CDATA 节只能作为节点值存在。如果需要,可以轻松添加额外的实现,但考虑到此项目的目的,我宁愿保持原样,以免将 parse 函数复杂化到难以修改的程度。
  • 不支持处理指令
  • 不支持 DTD 和实体

新增功能

此项目在设计时考虑了简洁性,以便能够快速轻松地理解代码库,并添加每个特定应用程序所需的功能。

这些类只提供基本功能,因此是我能找到的所有解析器中最轻量级的:解析器(包括一些未使用的 base64 函数,如果需要可以删除)有 500 行代码,而二叉树结构有另外 500 行代码。如果需要更多功能,则需要添加这些功能以满足需求。

作为进一步开发的基础,它非常易于理解和使用。

解析函数是迭代的,它只遍历一次 XML 字符串,因此性能相当令人满意。内存需求低,每个对象只分配实际所需的内存。还有很大的改进空间,但这并非本项目的目标。

工作原理

我个人认为关于这一点不必多说,因为代码本身就能说明一切,并且它的设计易于阅读和理解。如果认为有必要,我可以详细说明它是如何工作的,以及如何进行丰富。

Using the Code

处理 XML 格式时,有三个类(用红点标记)

CxmlCAttribute CNode

class_struct.JPG

Cxml 类是该项目的“主力”,包含 parse 函数

bool Cxml::ParseString(_TCHAR* szXML); 

解析后,需要将信息以易于使用的方式存储在内存中,因此存在 Node Attribute 类。

Node 类具有类似树的结构,包含一个父指针和子节点列表。它还包含一个属性列表。

除了这些类之外,还有一组 Utils 文件(.h & .cpp),其中包含一些实用函数。

如何使用?

好的,要使用它,您需要执行以下操作

  • Add
     #include "Cxml.h"  

    到您的项目中。

  • 创建一个类的实例
    Cxml *oxml = new Cxml();
  • 将包含 XML 代码的 string 的指针传递给 parse 函数
    oxml->ParseString(szXML); 

ParseString 返回后,XML 的结构将复制到类中,并且可以通过...来检索 XML 根节点。

oxml->GetRootNode(); 

...调用。

这里有一个特点。因为我采用了“后进先出”的方式,所以节点将以与它们在原始 XML 字符串中出现的顺序相反的顺序组织。

可以使用 Node 对象的 public 函数进行导航。但请记住,GetNextChild() 函数会增加计数器的位置,而我没有实现重置它的方法。

理解内部工作原理的最佳方法是获取演示项目并自行测试。您需要 Visual Studio 2008 来编译现有项目,而无需重建。如果您重建,请记住:它尚未经过 Unicode 测试。

下载项目并解压。编译。运行它并按加载按钮。

exe_print_screen.JPG

选择提供的 XML 文件之一。点击打开。

tree_print_screen.JPG

这是提供的其中一个 XML 文件得到的结果。

<CATALOG>
...
    <PLANT>
        <COMMON>Snakeroot</COMMON>
        <BOTANICAL>Cimicifuga</BOTANICAL>
        <ZONE>Annual</ZONE>
        <LIGHT>Shade</LIGHT>
        <PRICE>$5.63</PRICE>
        <AVAILABILITY>071199</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>Cardinal Flower</COMMON>
        <BOTANICAL>Lobelia cardinalis</BOTANICAL>
        <ZONE>2</ZONE>
        <LIGHT>Shade</LIGHT>
        <PRICE>$3.02</PRICE>
        <AVAILABILITY>022299</AVAILABILITY>
    </PLANT>
</CATALOG>

历史

  • 2010 年 9 月 20 日
    • Added
  • 2010 年 9 月 21 日
    • 修订
  • 2010 年 9 月 22 日
    • 新版本项目已更新
      • 修正了多个属性的错误
      • 添加了“一些”注释支持。根节点外的注释将产生错误
  • 2010 年 9 月 28 日
    • 经过 Unicode 测试,并为测试添加了 Unicode XML
    • 从项目中删除了智能感知文件
    • 修正了 Lorenzo Gatti 发现的混淆单引号和双引号与实际分隔符的错误
  • 2010 年 9 月 29 日
    • 添加了对 UNICODE 字符集的运行时支持!程序必须使用此字符集编译

    unicode.JPG

  • 2010 年 9 月 29 日
    • 已添加对 CDATA 节的一些支持
    • 我还发现 Parse 函数需要一些重构,因为它变得庞大且难以理解。
  • 2010 年 10 月 1 日
    • 用动态分配的替换了项目中的所有固定大小的 char 数组。
    • 添加了对处理指令的支持。所有处理指令现在都被视为一种特殊类型的节点,就像注释一样。
    • 注释现在也可以存在于 XML 的根节点之外,因为现在最低级别的节点是 XML_DOC 节点,而不是 XML 的根节点。
© . All rights reserved.