本文由即将出版的 XML by Example第二版中的一章改编,介绍了 SAX,它是用于处理 XML 的基于事件的 API,SAX 是对“文档对象模型”或者 DOM 的补充,DOM 是用于由 W3C 发布的 XML 语法分析器的基于对象的 API。
您将了解到,SAX:
是基于事件的 API。
在一个比 DOM 低的级别上操作。
为您提供比 DOM 更多的控制。
几乎总是比 DOM 更有效率。
但不幸的是,需要比 DOM 更多的工作。
为什么出现另一个 API?不要被名称欺骗。SAX 可能是 Simple API for XML,但它需要比 DOM 更多的工作。其回报 - 更紧凑的代码 - 是值得努力的。
图 1 显示了典型 XML 程序的两个组件:
语法分析器,代表应用程序解码 XML 文件的软件组件。语法分析器有效地使开发者避开复杂的 XML 语法。
应用程序,它使用文件内容。
图 1. XML 程序的体系结构显然,应用程序可以很简单(例如,在欧元和美元之间转换价格的应用程序)也可以非常复杂,例如,通过因特网订购货物的分布式电子贸易应用程序。
本章集中讨论图 1 中的虚线 - 语法分析器和应用程序之间的接口或 API(应用程序编程接口)。
基于对象和基于事件的接口
您可能已经知道语法分析器有两类接口 - 基于对象的和基于事件的接口。
在拙作的另一章中详细讨论了由 W3C 开发并发布的 DOM,它是基于对象的语法分析器的标准 API。这个关于 DOM 的简要概述只为您提供背景知识,以便您更好地全面理解 SAX。
作为基于对象的接口,DOM 通过在内存中显示地构建对象树来与应用程序通信。对象树是 XML 文件中元素树的精确映射。
DOM 易于学习和使用,因为它与基本 XML 文档紧密匹配。它对于我称为以 XML 为中心的应用程序(例如,浏览器和编辑器)也是很理想的。以 XML 为中心的应用程序为了操纵 XML 文档而操纵 XML 文档。
然而,对于大多数应用程序,处理 XML 文档只是其众多任务中的一种。例如,记帐软件包可能导入 XML 发票,但这不是其主要活动。计算帐户余额、跟踪支出以及使付款与发票匹配才是主要活动。记帐软件包可能已经具有一个数据结构(最有可能是数据库)。DOM 模型不太适合记帐应用程序,因为在那种情况下,应用程序必须在内存中维护数据的两份副本(一个是 DOM 树,另一个是应用程序自己的结构)。至少,在内存维护两次数据会使效率下降。对于桌面应用程序来说,这可能不是主要问题,但是它可能导致服务器瘫痪。
对于不以 XML 为中心的应用程序,SAX 是明智的选择。实际上,SAX 并不在内存中显式地构建文档树。它使应用程序能用最有效率的方法存储数据。
图 2 说明了应用程序如何在 XML 树及其自身数据结构之间进行映射。
图 2. 将 XML 结构映射成应用程序结构 基于事件的接口正如其名称所暗示的,,基于事件的语法分析器将事件发送给应用程序。这些事件类似于用户界面事件,例如,浏览器中的 ONCLICK 事件或者 Java 中的 AWT/Swing 事件。
事件通知应用程序发生了某件事并需要应用程序作出反应。在浏览器中,通常为响应用户操作而生成事件:当用户单击按钮时,按钮产生一个ONCLICK 事件。
在 XML 语法分析器中,事件与用户操作无关,而与正在读取的 XML 文档中的元素有关。有对于以下方面的事件:
元素开始和结束标记
元素内容
实体
语法分析错误
图 3 显示语法分析器在读取文档时如何生成事件。
图 3. 语法分析器生成事件清单 1 显示了 XML 格式的清单。它详细列出了不同公司对 XML 培训的收费。图 4 显示了价目表文档的结构。
清单 1. pricelist.xml<?xml version="1.0"?> <xbe:price-list xmlns:xbe="http://www.psol.com/xbe2/listing8.1"> <xbe:product>XML Training</xbe:product> <xbe:price-quote price="999.00" vendor="Playfield Training"/> <xbe:price-quote price="699.00" vendor="XMLi"/> <xbe:price-quote price="799.00" vendor="WriteIT"/> <xbe:price-quote price="1999.00" vendor="Emailaholic"/> </xbe:price-list>
图 4. 价目表的结构XML 语法分析器读取并解释该文档。每当它识别出文档中的某些内容,就会生成一个事件。