xerces-c
Xerces-C ++是非常强大的XML解析器,提供了验证以及SAX和DOM API。 文档类型定义(DTD)很好地支持XML验证,并且在2001年12月添加了对W3C XML Schema的实质上完全开放标准的支持。
Xerces-C ++:胶囊生物
Xerces-C ++起源于IBM的XML4C项目。 XML4C是XML4J的一个配套项目,这也是Xerces-J(Java实现)的起源。 IBM将这两个项目的源代码都发布给了Apache软件基金会,并在此分别将其重命名为Xerces-C ++和Xerces-J。 这两个是Apache XML组的核心项目。 (如果看到的是“ Xerces-C”而不是“ Xerces-C ++”,那是同一回事;该项目从一开始就是用C ++编写的。)
XML4C项目在IBM的Xerces-C ++基础上继续进行。 XML4C相对于Xerces-C ++的显着优点是对我探索的版本中的大量国际字符编码提供了更好的现成支持(请参阅参考资料 )。
验证方式
指定XML文档结构的两种主要方法是DTD和W3C XML Schema,其中DTD是两者中较老的一种。 XML Schema基本上是表示为XML的DTD。 Xerces-C ++提供了强大的现成验证功能,可确保XML文档符合DTD。
发牌
Xerces-C ++是根据Apache软件许可(请参阅参考资料 )的条款提供的,该许可恰好是周围更具可读性的开源许可之一。 它与BSD许可证相比非常好。 本质上,您可以在您的(或公司的)软件中免费使用Xerces-C ++,而仅向客户和用户披露您的软件包含Apache代码并包含适当的版权声明即可。 在网页上查看许可证的确切文本。
SAX:事件API模型
您可能知道,SAX是一种用于分析XML文档的面向事件的编程API。 解析引擎使用XML顺序数据,并在发现传入XML数据的结构时对应用程序进行回调。 这些回调称为事件处理程序。 SAX实际上是两个API:SAX 1.0是原始API,SAX 2.0是当前的修订规范。 两者是相似的,但又有足够的不同,以至于大多数基于SAX 1.0的应用程序在移至更新的规范时都会中断。
SAX API规范已作为其自己的项目移至SourceForge(请参阅参考资料 )。 我稍后在本文中提供的SAX示例将使用SAX 2.0。
DOM:文档对象模型
与SAX不同,DOM API允许编辑XML文档并将其保存回文件或流中。 它还允许以编程方式从头开始构建新的XML文档。 这样做的原因是DOM为文档提供了内存模型。 您可以遍历文档树,修剪节点或嫁接新的树。
科技残骸
DOM是W3C技术建议的一族,也被称为技术残骸 。 DOM具有三个级别,其中第1级和第2级处于完全技术推荐状态,第3级处于工作草案状态。
DOM 1级核心定义了基本XML功能所需的大多数功能:构造XML文档表示的能力。 DOMString
类型被明确指定为包含宽UTF-16字符。 级别1继续定义用于以编程方式与DOM树的各个部分进行交互的接口。 级别1故意省略了XML的序列化。DOM级别1 HTML定义超出了级别1的核心。 该区域尝试使用较早的Dynamic HTML对象模型(通常称为Level 0)来解析DOM Level 1核心。
DOM 2级添加了名称空间,事件和迭代器,以及视图和样式表支持。 对于某些应用程序,您需要DOM Level 2:例如,将XML模式分配给名称空间对于RDF之类的应用程序至关重要,因为RDF中XML标签来自不同的模式,并且名称冲突的可能性很高。 级别2将一对createDocument
方法添加到DOMImplementation
接口。 示例之一将说明为什么这很重要。 就在您认为自己可以安全使用SAX中的回调和事件处理程序时,这里它们又位于Event
接口中。 与用于解析的SAX事件不同,DOM事件可以反映用户与文档的交互以及对活动文档的更改。 反映文档结构变化的DOM事件称为变异事件 。 TreeWalkers
和NodeIterators
增强DOM树遍历。 程序可以通过StyleSheet
界面检查样式信息。 最后,视图支持允许XML应用程序以原始和样式表呈现的形式检查文档。 这些之前和之后的视图称为文档视图和抽象视图。
DOM 3级核心将getInterface
方法添加到DOMImplementation
接口。 在3级文档中,您可以指定文档的字符编码或设置其一些基本XML声明,例如version
和standalone
。 级别2不允许将DOM节点从一个文档移动到另一个文档。 级别3取消了此限制。 级别3添加了用户数据 -可以选择性地附加到任何节点的额外应用程序数据。 Level 3具有许多其他高级功能,但是W3C委员会仍在研究Level 3草案。 在参考资料中找到一个链接,以阅读委员会的进度。
下载并安装
您可以将Xerces-C ++作为压缩的tarball或预编译的二进制文件下载(请参阅参考资料 )。 通过Perl,Python,VBScript或JavaScript访问该库的脚本用户可以下载其平台的二进制文件,以快速开始安装。 C ++程序员很可能会喜欢从源代码压缩包构建自己的二进制文件。 Apache XML组网站上的构建说明编写得很好; 在本文的更远的地方,我讨论了一些我发现的细微问题-一个pthread链接问题以及一个针对Windows平台上潜在的内存泄漏的修复程序。 第2部分将包括在SVG示例中指定DOCTYPE的技巧。 如果您想在阅读本文时构建库,请先查看Apache站点上的Xerces构建文档(请参阅参考资料 ),然后再回到此处以了解有关将Xerces链接到您自己的应用程序的信息。
您可以下载压缩包并脱机工作(例如,使用笔记本电脑)。 压缩文件中包含完整HTML文档,因此您无需继续参考该网站以获取相关说明。
为Win32构建
在Visual Studio dot-NET或Win64上安装软件的步骤与在Win32上构建的这些步骤几乎相同。
- 将Xerces源压缩包解压缩并解压缩到工作目录。 Xerces-C ++具有其自己的目录结构,因此您应确保在此步骤中保留相对路径名。
- 使用Windows资源管理器或您喜欢的文件管理器,深入到
\xerces-c-src_2_3_0\Projects\Win32\VC6\xerces-all\
文件夹,然后单击xerces-all.dsw
工作区文件以启动Microsoft Developer Studio。
注意:这些说明假定您在Visual Studio 6中构建Win32应用程序。对于Visual Studio dot-NET或Win64应用程序,请在目录的Win64或VC7变体中重复步骤1和2。 - 在Developer Studio中,将XercesLib设置为当前活动项目,然后按F7键构建DLL。 在去年的硬件上,这需要一两分钟。
- 将Xerces头文件的路径添加到您的项目中。 (想要针对Xerces-C ++进行链接的应用程序需要在其工作区中包括XercesLib DSP项目文件,或者在其项目文件中添加LIB文件以允许链接。)选择“ 项目”>“设置”以打开项目设置对话框。 从“ 设置”组合框中选择“ 所有配置 ”,单击“ C ++”选项卡,选择“ 预处理器”类别,然后将“ Xerces包含”路径(类似
\xerces-c-sr2_2_0\src
)添加到“ 其他包含目录”文本框。 - 如果您已将XercesLib DSP添加到工作区,请记住将您自己的项目标记为依赖XercesLib项目; 否则,您会遇到链接错误。
- 创建一个存根C ++源文件,该文件不执行任何操作,只包含读取
#include <xercesc/sax/HandlerBase.hpp>
。 如果可以编译此单行C ++文件,则包含路径可能正确。 完成后保存您的工作区。 要运行和调试您的应用程序,请将Xerces DLL的副本放在工作目录中。
Linux版
按照doc/html
文件夹中的详尽说明来构建Xerces-C ++共享库。 以下命令说明了如何从压缩源中构建Xerces-C ++库。 这假定xerces-c-src_2_3_0.tar.gz
文件存在于/home/user
类的目录中。 无论选择哪个目录,都应匹配XERCESCROOT
变量; configure
脚本需要它。
# cd /home/user
# gunzip xerces-c-src_2_3_0.tar.gz
# tar -xvf xerces-c-src_2_3_0.tar
# export XERCESCROOT=/home/user/xerces-c-src_2_3_0
# cd $(XERCESCROOT)/src/xercesc
# ./configure
# make all
对于本示例的其余部分,我假设源代码树位于/home/user/xerces-c-src_2_3_0
目录下。 如果一切顺利,则共享库应出现在lib
文件夹中。 如果有问题,请查看/doc/html
文件夹中的构建说明。 此时,您可以将库(和符号链接)复制到/usr/lib
或定义适当的环境变量,以便加载程序可以找到新编译的库。
测试新库的简单方法是构建并运行以下示例之一:
# export XERCESCROOT=/home/user/xerces-c-src_2_3_0
# cd $(XERCESCROOT)/samples
# ./configure
# make all
我遇到了一个小问题,即在全新安装的Slackware Linux 9.0上构建示例之一。 链接器抱怨缺少一些与pthreads相关的导出。 我编辑了Makefile.in
文件,以包含对-lpthread
的引用,然后再次运行configure
。 第二次,键入make all
工作正常。
一旦知道该库可以工作,就可以启动自己的Xerces-C ++项目。 使用-I
编译器选项可帮助编译器找到Xerces头文件。 使用-L
和-l
链接器选项可帮助链接器找到Xerces-C ++库。 清单1为您提供了一个最小的makefile入门。
清单1.一个最小的makefile
APP = example
XERCES = /home/user/xerces-c-src_2_3_0
INCS = ${XERCES}/src
${APP} :: ${APP}.cpp
${CC} -lxerces-c-src_2_3_0 -I${INCS} ${APP}.cpp -o ${APP}
开始清单1的命令是make
或gmake
。 您可以将APP
变量更改为适合您的任何源文件。 本文中的示例使用类似的makefile。
从版本2.2.0开始,Xerces C ++添加了C ++名称空间支持(不要与XML名称空间混淆)。 如果您的代码可以在2.1.0上运行,并且希望利用新版本,请在包含Xerces C ++标头之后,在代码中添加以下三行。
清单2. Xerces C ++名称空间支持
#ifdef XERCES_CPP_NAMESPACE_USE
XERCES_CPP_NAMESPACE_USE
#endif
当然,您可以在所有Xerces-C ++对象的XERCES_CPP_NAMESPACE::
加上XERCES_CPP_NAMESPACE::
名称空间。
样例应用
为了使事情有趣,在我解释使用Xerces-C ++的基础时,我将使用XML作为数据格式创建一个简单的条形图。 为了躲避平台GUI细节的跨平台项目符号,我正在使用ASCII艺术绘制条形图。 毕竟,这是一篇有关XML的文章,而不是GTK,OpenGL或Direct-X。 如果您对使用图形数据的XML表示感兴趣,请查看SVG和SMIL(请参阅参考资料 )。 我在第2部分中描述的DOM示例输出SVG。 我将从简单的纯文本应用程序开始。
清单3是数据的DTD。 接下来,我将构造一个程序来加载数据,确定要使用的比例,然后将数据实际绘制到屏幕上。
清单3.示例应用程序数据的DTD
APP = example
<?xml version="1.0" ?>
<!ELEMENT figures (PCDATA) >
<!ATTLIST figures type (sales | inventory | labor) >
<!ATTLIST figures value CDATA >
<!ELEMENT department (figures*) >
<!ATTLIST department name CDATA>
<!ELEMENT corporate (department*) >
<!ATTLIST corporate name CDATA >
清单4显示了数据外观的样本。
清单4.示例输入XML数据
APP = example
<?xml version="1.0" ?>
<corporate name="Big Biz">
<department name="North">
<figures type="sales" value="125000.00"/>
<figures type="inventory" value="90000.00"/>
<figures type="labor" value="110000.00">estimated</figures>
</department>
<department name="South">
<figures type="sales" value="980000.00"/>
<figures type="inventory" value="110000.00"/>
<figures type="labor" value="115000.00">estimated</figures>
</department>
<department name="East">
<figures type="sales" value="210000.00"/>
<figures type="inventory" value="80000.00"/>
<figures type="labor" value="95000.00">estimated</figures>
</department>
<department name="West">
<figures type="sales" value="160000.00"/>
<figures type="inventory" value="75000.00"/>
<figures type="labor" value="130000.00">estimated</figures>
</department>
<department name="Central">
<figures type="sales" value="723000.00"/>
<figures type="inventory" value="11000.00"/>
<figures type="labor" value="221000.00">estimated</figures>
</department>
</corporate>
SAX2实施
清单5是基线SAX实现。 这不是一个完整的程序,因为它缺少处理程序的实现,但确实显示了将框架正确放置所需的内容。 对XMLPlatformUtils:Initialize()
和XMLPlatformUtils::Terminate()
的调用非常重要。 该库可防止通过抛出异常无法正确初始化库的应用程序。
为了使清单5中的程序成为一个完整的应用程序,您需要在清单6中添加event-handler类。 SAX2带有一个名为DefaultHandler
的默认事件处理程序类,该类在同名的C ++头文件中定义。 默认处理程序不执行任何操作-只是一个存根实现-但它是完整的,因此我在这里将其用作图形化事件处理程序类的基类。
清单7中的该文件是清单6中 event-handler类的实际实现。 尽管程序的其余部分几乎只是使SAX2解析器运行的样板代码,但清单7中的部分定义了应用程序的个性。
Xerces-C ++使用XMLCh
作为类型定义的字符表示。 在某些平台上,它与C类型wchar_t
兼容,该类型通常为两个字节,但有时为四个字节宽。 由于这种可能性,文档不鼓励互换wchar_t
和XMLCh
的做法。 您可以在某些平台上使用它,但在其他平台上则无法使用。 Xerces-C ++使用更大的字符表示形式将文本作为UTF-16交换,而不是UTF-8或ISO-8859。 为了调试该程序,我使用XMLString::transcode
函数转换宽字符串以在控制台上显示,如图1所示。
图1. SAX解析器输出的屏幕截图
![SAX解析器输出的屏幕截图](https://i-blog.csdnimg.cn/blog_migrate/97d47f9ed4a514f5b6bae63b9dc5bf69.png)
我在Microsoft Windows上使用Xerces内部字符串类发现了一个问题。 XMLString.hpp
的注释要求replicate
和其他类似函数的调用者释放返回的内存。 问题来自将您的应用程序作为DLL链接到Xerces-C ++库。 字符串是从DLL的本地堆分配的。 如果您的应用程序和XercesLib DLL都使用完全相同的C运行时(CRT)库DLL,那么一切都很好。 但是,如果您的程序使用单线程CRT,而XercesLib使用多线程CRT,则会发生DLL问题。 当您的程序尝试释放字符串内存时,C运行时会注意到该内存不是来自应用程序的本地堆。 对于调试版本,它会引发异常,但对于发行版本,则可能会静默地泄漏内存。 在Xerces早期版本(如1_5_1)中找到的示例程序通过简单地不释放内存来避免这种情况。
我的解决方法是向XMLString
类添加一对静态丢弃函数。 因为字符串内存是由DLL中执行的代码释放的,所以使用了正确的本地堆,并且没有调试声明。 我很高兴看到Xerces开发人员Tinny Ng将其添加到XMLString
类中,并进一步使字符串指针为空(请参阅参考资料 )。 另一个不错的功能是程序员不必担心XMLString
的实现如何分配内存。 不必猜测是否应该使用delete[]
或free
,而是可以调用XMLString::release
。 当然,您可以确保应用程序期望的CRT与XercesLib DLL使用的CRT相同。
下一步是什么?
在第1部分中,您已经看到了如何将Xerces-C ++ XML库链接到用Linux和Windows编写的应用程序中,并且我已经通过创建ASCII艺术的条形图演示了使用SAX API进行解析。 在第2部分中 ,我将向您展示如何加载,操作或合成DOM文档,以及如何使用可伸缩矢量图形(SVG)创建相同的条形图。
翻译自: https://www.ibm.com/developerworks/xml/library/x-xercc/index.html
xerces-c