XML,或称为可扩展标记语言(Extensible Markup Language),是一种您可以用来创建自己的标记的标记语言。它由万维网协会(W3C)创建,用来克服 HTML(即超文本标记语言(Hypertext Markup Language),它是所有网页的基础)的局限。和 HTML 一样,XML 基于 SGML — 标准通
用标记语言(Standard Generalized Markup Language)。尽管 SGML 已在出版业使用了数十年,但其理解方面的复杂性使许多本打算使用它的人望而却步(SGML 也代表“听起来很棒,但或许以后会用(Sounds great, maybe later)”)。XML 是为 Web 设计的。
XML文档规则
有三种 XML 文档:
无效文档没有遵守 XML 规范定义的语法规则。如果开发人员已经在 DTD 或模式中定义了文档能够包含什么,而某个文档没有遵守那些规则,那
么这个文档也是无效的。(请参阅定义文档内容以获得对 XML 文档 的 DTD 和模式的专门介绍。)
有效文档既遵守 XML 语法规则也遵守在其 DTD 或模式中定义的规则。
格式良好的文档遵守 XML 语法,但没有 DTD 或模式。
根元素
XML 文档必须包含在一个单一元素中。这个单一元素称为根元素,它包含文档中所有文本和所有其它元素。在下面的示例中,XML 文档包含在一
个单一元素 <greeting> 中。请注意文档有一行注释在根元素之外;那是完全合乎规则的。
<?xml version="1.0"?>
<!-- A well-formed document -->
<greeting>
Hello, World!
</greeting>
下面是一个不包含单一根元素的文档:
<?xml version="1.0"?>
<!-- An invalid document -->
<greeting>
Hello, World!
</greeting>
<greeting>
Hola, el Mundo!
</greeting>
不管该文档可能包含什么信息,XML 解析器都会拒绝它。
元素不能重叠
XML 元素不能重叠。下面是一些不合乎规则的标记:
<!-- NOT legal XML markup -->
<p>
<b>I <i>really
love</b> XML.
</i>
</p>
如果您在 <b> 元素中开始了 <i> 元素,则必须在 <b> 元素中结束 <i> 元素。如果您希望文本 XML 以斜体出现,那么您需要添加第二个 <i>
元素以更正标记:
<!-- legal XML markup -->
<p>
<b>I <i>really
love</i></b>
<i>XML.</i>
</p>
XML 解析器将只接受这种标记;大多数 Web 浏览器中的 HTML 解析器对于两者都接受。
结束标记是必需的
不能省去任何结束标记。在下面第一个示例中,标记是不合乎规则的,因为没有结束段落(</p>)标记。尽管这在 HTML(以及某些情况下在
SGML)中可以接受,但 XML 解析器将拒绝它。
<!-- NOT legal XML markup -->
<p>Yada yada yada...
<p>Yada yada yada...
<p>...
如果一个元素根本不包含标记,则称为空元素;HTML 换行(<br>)和图像(<img>)元素就是两个例子。在 XML 文档的空元素中,您可以把结束
斜杠放在开始标记中。下面的两个换行元素和两个图像元素对于 XML 解析器来说是一回事:
<!-- Two equivalent break elements -->
<br></br>
<br />
<!-- Two equivalent image elements -->
<img src="../img/c.gif"></img>
<img src="../img/c.gif" />
元素是区分大小写的
XML 元素是区分大小写的。在 HTML 中,<h1> 和 <H1> 是相同的;在 XML 中,它们是不同的。如果您试图用 </H1> 标记结束 <h1> 元素,将会
出错。在下面的示例中,顶部的标题是不合乎规则的,而底部的则是正确的。
<!-- NOT legal XML markup -->
<h1>Elements are
case sensitive</H1>
<!-- legal XML markup -->
<h1>Elements are
case sensitive</h1>
属性必须有用引号括起的值
XML 文档中的属性有两个规则:
属性必须有值
那些值必须用引号括起。
比较下面的两个示例。顶部的标记在 HTML 中是合乎规则的,但在 XML 中则不是。为了在 XML 中取得相同结果,您必须给属性赋值,而且必须
把值括在引号中。
<!-- NOT legal XML markup -->
<ol compact>
<!-- legal XML markup -->
<ol compact="yes">
您可以使用单引号,也可以使用双引号,但要始终保持一致。
如果属性值包含单引号或双引号,则您可以使用另一种引号来括起该值(如 name="Doug's car"),或使用实体 " 代表双引号,使用
' 代表单引号。实体是一个符号(如 "),XML 解析器会用其它文本代替该符号(如 ")。
XML 声明
大多数 XML 文档以 XML 声明作为开始,它向解析器提供了关于文档的基本信息。建议使用 XML 声明,但它不是必需的。如果有的话,那么它一
定是文档的第一样东西。
声明最多可以包含三个名称-值对(许多人称它们为属性,尽管在技术上它们并不是)。version 是使用的 XML 版本;目前该值必须是 1.0。
encoding 是该文档所使用的字符集。该声明中引用的 ISO-8859-1 字符集包括大多数西欧语言用到的所有字符。如没有指定 encoding,XML 解
析器会假定字符在 UTF-8 字符集中,这是一个几乎支持世界上所有语言的字符和象形文字的 Unicode 标准。
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
最后,standalone(可以是 yes 或 no)定义了是否可以在不读取任何其它文件的情况下处理该文档。例如,如果 XML 文档没有引用任何其它文
件,则您可以指定 standalone="yes"。如果 XML 文档引用其它描述该文档可以包含什么的文件(马上会详细介绍这些文件),则您可以指定
standalone="no"。因为 standalone="no" 是缺省的,所以您很少会在 XML 声明中看到 standalone。
XML 文档中的其它项
您或许会在一个 XML 文档中发现其它几项:
注释:注释可以出现在文档的任何位置;它们甚至可以出现在根元素的前面或后面。注释以 <!-- 开始,以 --> 结束。注释不能在结束部分以外
包含双连字符(--);除此之外,注释可以包含任何内容。最重要的是,注释内的任何标记都被忽略;如果您希望除去 XML 文档的一块较大部分
,只需用注释括住那个部分即可。(要恢复这个注释掉的部分,只需除去注释标记即可。)下面是包含注释的标记:
<!-- Here's a PI for Cocoon: -->
<?cocoon-process type="sql"?>
处理指令:处理指令是为使用一段特殊代码而设计的标记。在上面的示例中,有一个用于 Cocoon 的处理指令(有时称为 PI),Cocoon 是来自
Apache 软件基金会(Apache Software Foundation)的 XML 处理框架。当 Cocoon 处理 XML 文档时,它会寻找以 cocoon-process 开头的处理
指令,然后相应地处理 XML 文档。在该示例中,type="sql" 属性告诉 Cocoon:XML 文档包含一个 SQL 语句。
<!-- Here's an entity: -->
<!ENTITY dw "developerWorks">
实体:上面的示例为文档定义了一个实体。无论 XML 处理器在何处找到字符串 &dw;,它都会用字符串 developerWorks 代替该实体。XML 规范
还定义了五个您可以用来替代不同的特殊字符的实体。这些实体是:
< 代表小于符号
> 代表大于符号
" 代表一个双引号
' 代表一个单引号(或撇号)
& 代表一个“与”符号。
名称空间
XML 的能力来自它的灵活性,即您和我以及数百万其他人可以定义我们自己的标记来描述我们的数据。记得表示个人姓名和地址的样本 XML 文档
吗?那个文档包括表示个人尊称的 <title> 元素,这是对元素名称非常合理的选择。如果您经营一家网上书店,您或许会创建一个表示书名的
<title> 元素。如果您经营一家网上抵押放款公司,您或许会创建表示一份财产名称的 <title> 元素。所有这些都是合理的选择,但它们都用相
同的名称创建元素。如何分辨某个特定的 <title> 元素指的是人、书籍还是一份财产呢?可以使用名称空间。
要使用名称空间,您要定义一个名称空间前缀,然后将它映射至一个特殊字符串。下面介绍如何定义我们这三个 <title> 元素的名称空间前缀:
在该示例中,三个名称空间前缀是 addr、books 和 mortgage。请注意,为特定元素定义名称空间意味着该元素的所有子元素都属于同一名称空
间。第一个 <title> 元素属于 addr 名称空间,因为其父元素 <addr:Name> 属于该名称空间。
最后要指出的是:名称空间定义中的字符串仅仅是字符串。对,这些字符串看似 URL,其实不是。您可以定义 xmlns:addr="mike",那也是有效
的。名称空间唯一的重要性在于其唯一性;这就是为什么大多数名称空间定义看起来象 URL 的原因。XML 解析器不会到
定义文档内容
在了解到了 XML 文档的基本规则之后,您需要定义将用来表示数据的元素。做到这一点的两种方法。
一种方法是使用文档类型定义(Document Type Definition),或简称 DTD。DTD 定义可以在 XML 文档中出现的元素、这些元素出现的次序、它
们可以如何相互嵌套以及 XML 文档结构的其它详细信息。DTD 是最初的 XML 规范的一部分,与 SGML DTD 非常相似。
另一种方法是使用 XML Schema。模式可以定义您能在 DTD 中使用的所有文档结构,它还可以定义数据类型和比 DTD 更复杂的规则。W3C 在提出
最初的 XML 规范的几年之后开发了 XML Schema 规范。
文档类型定义
DTD 允许您指定 XML 文档的基本结构。下面的几页将研究 DTD 片段。首先是定义本章中地址文档示例的基本结构的 DTD,XML 是什么?:
<!-- address.dtd -->
<!ELEMENT address (name, street, city, state, postal-code)>
<!ELEMENT name (title? first-name, last-name)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT first-name (#PCDATA)>
<!ELEMENT last-name (#PCDATA)>
<!ELEMENT street (#PCDATA)>
<!ELEMENT city (#PCDATA)>
<!ELEMENT state (#PCDATA)>
<!ELEMENT postal-code (#PCDATA)>
该 DTD 定义了样本文档中使用的所有元素。它定义了三个元素:
<address> 元素包含一个 <name>、一个 <street>、一个 <city>、一个 <state> 和一个 <postal-code>。所有这些元素必须出现,而且必须以
这个顺序出现。
<name> 元素包含一个可选的 <title> 元素(问号表示 title 这个元素是可选的),后面跟有一个 <first-name> 和一个 <last-name> 元素。
所有其它包含文本的元素。(#PCDATA 代表已解析字符数据;不能在这些元素中包含另一个元素。)
尽管 DTD 相当简单,但它清楚地说明了什么样的元素组合是合乎规则的。<postal-code> 元素在 <state> 元素之前的地址文档是不合乎规则的
,没有 <last-name> 元素的文档也不合乎规则。
另外,请注意,DTD 语法不同于普通的 XML 语法。(相反,XML Schema 文档本身就是 XML,这导致一些有趣的结果)。尽管 DTD 的语法不同,
但您仍可以将普通的注释放到 DTD 中。
DTD 中的符号
DTD 中有几个符号用于指出某元素在 XML 文档中可能会出现多少次(或是否出现)。下面是一些示例及其含义:
<!ELEMENT address (name, city, state)>
<address> 元素必须包含一个 <name> 元素、一个 <city> 元素和一个 <state> 元素,并且符合上面的次序。所有的元素都是必需的。逗号表示
项的列表。
<!ELEMENT name (title?, first-name, last-name)>
这意味着 <name> 元素包含一个可选的 <title> 元素,后面必须跟有一个 <first-name> 和一个 <last-name> 元素。问号表示这一项是可选的
;它可以出现一次或根本不出现。
<!ELEMENT addressbook (address+)>
<addressbook> 元素包含一个或多个 <address> 元素。您可以有任意多的 <address> 元素,但必须至少有一个。加号表示这一项必须至少出现
一次,但可出现任意次。
<!ELEMENT private-addresses (address*)>
<private-addresses> 元素包含零个或多个 <address> 元素。星号表示这一项可以出现任意次,包括零次。
<!ELEMENT name (title?, first-name, (middle-initial | middle-name)?, last-name)>
<name> 元素包含一个可选的 <title> 元素,后面跟有一个 <first-name> 元素,随后可能跟有一个 <middle-initial> 或 <middle-name> 元素
,然后跟有一个 <last-name> 元素。换句话说,<middle-initial> 和 <middle-name> 都是可选的,而且您只能选择二者中的一个。竖线符号表
示选择列表;您只能从列表选择一项。还要注意该示例用圆括号对特定元素进行分组,然后在这个组旁放上问号。
<!ELEMENT name ((title?, first-name, last-name) | (surname, mothers-name, given-name))>
这个 <name> 元素可以包含两个序列中的一个:一个可选的 <title>,后面跟有一个 <first-name> 和一个 <last-name>;或一个 <surname>、
一个 <mothers-name> 和一个 <given-name>。
定义属性
本篇介绍性教程没有很详细地研究 DTD 如何工作,但这里要介绍一个更基本的概念:定义属性。您可以定义将在 XML 文档中出现的元素的属性
。使用 DTD,您还可以:
定义哪些属性是必需的
定义属性的缺省值
列出给定属性的所有有效值
假设您要更改 DTD,使 state 成为 <city> 元素的属性。下面演示如何做到这一点:
<!ELEMENT city (#PCDATA)>
<!ATTLIST city state CDATA #REQUIRED>
和以前一样,我们定义了 <city> 元素,但修改的示例还使用了 ATTLIST 声明来列出元素的属性。属性列表中的名称 city 告诉解析器这些属性
是为 <city> 元素定义的。名称 state 是属性的名称,关键字 CDATA 和 #REQUIRED 告诉解析器 state 属性包含文本并且是必需的(如果它是
可选的,用 CDATA #IMPLIED 即可)。
要定义元素的多个属性,可象下面那样编写 ATTLIST:
<!ELEMENT city (#PCDATA)>
<!ATTLIST city state CDATA #REQUIRED
postal-code CDATA #REQUIRED>
该示例将 state 和 postal-code 都定义为 <city> 元素的属性。
最后,DTD 允许您定义属性缺省值,并列举属性的所有有效值:
<!ELEMENT city (#PCDATA)>
<!ATTLIST city state CDATA (AZ|CA|NV|OR|UT|WA) "CA">
上面的示例表明它仅支持来自亚利桑那州(AZ)、加利福尼亚州(CA)、内华达州(NV)、俄勒冈州(OR)、犹他州(UT)和华盛顿州(WA)的地址,并且缺省值是加利福尼亚州。这样,您就可以进行形式非常有限的数据验证。尽管这是有用的功能,但它只是您能用 XML 模式(请参阅
XML 模式)完成的工作的一个小子集。
XML 模式
使用 XML 模式,您会有更多的能力来定义什么样的 XML 文档是有效的。它们与 DTD 相比有几个优势:
XML 模式使用 XML 语法。换句话说,XML 模式是一个 XML 文档。这意味着您可以象处理任何其它文档一样处理模式。例如,您可以编写一个 XSLT 样式表,该样式表将 XML 模式转换成具有自动生成的 JavaScript 代码的 Web 表单,其中的 JavaScript 代码可以验证您输入的数据。
XML 模式支持数据类型。尽管 DTD 确实支持数据类型,但很明显这些数据类型是从发布的角度开发的。XML 模式支持 DTD 中的所有原始数据类型(诸如标识和标识引用之类的类型)。它们还支持整数、浮点数、日期、时间、字符串、URL 和其它对数据处理和验证有用的数据类型。
XML 模式是可扩展的。除了 XML 模式规范中定义的数据类型以外,您还可以创建自己的数据类型,并且可以基于其它数据类型派生出新的数据类型。
XML 模式有更强的表达能力。例如,您可以用 XML 模式定义任何 <state> 属性值不得超过 2 个字符,或定义任何 <postal-code> 元素的值必
须与正则表达式 [0-9]{5}(-[0-9]{4})? 相匹配。您无法用 DTD 做这些事。
样本 XML 模式
下面是与原始名称和地址 DTD 相匹配的 XML 模式。它增加了两个约束:<state> 元素的值必须刚好是两个字符长,<postal-code> 元素的值必
须与正则表达式 [0-9]{5}(-[0-9]{4})? 相匹配。尽管这个模式比 DTD 长很多,但它更清楚地表达了有效的文档看起来是什么样子。下面是模式
:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="
http://www.w3.org/2001/XMLSchema">
<xsd:element name="address">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="name"/>
<xsd:element ref="street"/>
<xsd:element ref="city"/>
<xsd:element ref="state"/>
<xsd:element ref="postal-code"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="name">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="title" minOccurs="0"/>
<xsd:element ref="first-Name"/>
<xsd:element ref="last-Name"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="title" type="xsd:string"/>
<xsd:element name="first-Name" type="xsd:string"/>
<xsd:element name="last-Name" type="xsd:string"/>
<xsd:element name="street" type="xsd:string"/>
<xsd:element name="city" type="xsd:string"/>
<xsd:element name="state">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:length value="2"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="postal-code">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:pattern value="[0-9]{5}(-[0-9]{4})?"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
</xsd:schema>
定义模式中的元素
样本 XML 模式中的 XML 模式用 <xsd:element> 元素定义了一些 XML 元素。头两个定义的元素(<address> 和 <name>)由其它元素组成。
<xsd:sequence> 元素定义了包含在这两个元素中的元素的序列。下面是示例:
<xsd:element name="address">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="name"/>
<xsd:element ref="street"/>
<xsd:element ref="city"/>
<xsd:element ref="state"/>
<xsd:element ref="postal-code"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
与 DTD 版本一样,XML 模式示例定义 <address> 包含一个 <name>、一个 <street>、一个 <city>、一个 <state> 和一个 <postal-code> 元素
,并且依照上面的次序。请注意,该模式实际上用 <xsd:complexType> 元素定义了新的数据类型。
大多数元素包含文本;定义它们很简单。您只要声明新的元素,然后指定它的数据类型为 xsd:string:
<xsd:element name="title" type="xsd:string"/>
<xsd:element name="first-Name" type="xsd:string"/>
<xsd:element name="last-Name" type="xsd:string"/>
<xsd:element name="street" type="xsd:string"/>
<xsd:element name="city" type="xsd:string"/>
定义模式中的元素内容
样本模式为两个元素的内容定义了约束:<state> 元素的内容必须是两个字符长,而 <postal-code> 元素的内容必须与正则表达式 [0-9]{5}(-
[0-9]{4})? 匹配。下面演示如何做到那一点:
<xsd:element name="state">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:length value="2"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="postal-code">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:pattern value="[0-9]{5}(-[0-9]{4})?"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
对于 <state> 和 <postal-code> 元素,模式用约束定义了新的数据类型。第一个情况使用 <xsd:length> 元素,而第二个情况则使用
<xsd:pattern> 元素定义该元素必须匹配的正则表达式。
这里概要的介绍仅仅触及 XML 模式能力的表面;有整本的书籍讨论这个主题。就这篇介绍性文章而言,我们足以说明 XML 模式是描述什么样的
XML 文档才算有效的非常强大和灵活的方式。
XML 编程接口
本章将研究 XML 的多种编程接口。这些接口为开发人员使用 XML 文档提供了一致的接口。有许多 API 可以使用;本章研究最流行和广泛使用的
API 中的四种:文档对象模型(Document Object Model (DOM))、用于 XML 的简单 API(Simple API for XML (SAX))、JDOM 和用于 XML 解
析的 Java API(Java API for XML Parsing (JAXP))。(您可以通过参考资料中的大量链接找到有关这些 API 的更多信息。)
文档对象模型
文档对象模型(通常称为 DOM)为 XML 文档的已解析版本定义了一组接口。解析器读入整个文档,然后构建一个驻留内存的树结构,然后您的代
码就可以使用 DOM 接口来操作这个树结构。您可以遍历树以了解原始文档包含了什么,您可以删除树的几个部分,还可以重新排列树和添加新的
分支,等等。
DOM 由 W3C 创建,并且是该协会的正式建议书。
DOM 问题
DOM 提供了一组丰富的功能,您可以用这些功能来解释和操作 XML 文档,但使用它们是有代价的。在开发用于 XML 文档的原始 DOM 时,XML-
DEV 邮件列表上的许多人提出了 DOM 的几个问题:
DOM 构建整个文档驻留内存的树。如果文档很大,就会要求有极大的内存。
DOM 创建表示原始文档中每个东西的对象,包括元素、文本、属性和空格。如果您只需关注原始文档的一小部分,那么创建那些永远不被使用的
对象是极其浪费的。
DOM 解析器必须在您的代码取得控制权之前读取整个文档。对于非常大的文档,这会引起显著的延迟。
这些仅仅是由文档对象模型的设计引起的问题;撇开这些问题,DOM API 是解析 XML 文档非常有用的方法。
用于 XML 的简单 API 第 4 页(共8 页)
为了解决 DOM 问题,XML-DEV 参与者们(由 David Megginson 领导)创建了 SAX 接口。SAX 的几个特征解决了 DOM 的问题:
SAX 解析器向您的代码发送事件。当解析器发现元素开始、元素结束、文本、文档的开始或结束等时,它会告诉您。您可以决定什么事件对您重
要,而且可以决定要创建什么类型的数据结构以保存来自这些事件的数据。如果您没有显式地保存来自某个事件的数据,它就被丢弃。
SAX 解析器根本不创建任何对象,它只是将事件传递给您的应用程序。如果希望基于那些事件创建对象,这将由您来完成。
SAX 解析器在解析开始的时候就开始发送事件。当解析器发现文档开始、元素开始和文本等时,代码会收到一个事件。您的应用程序可以立即开
始生成结果;您不必一直等到整个文档被解析完毕。更妙的是,如果您只查找文档中某些内容,代码一旦找到所要找的东西就可以抛出一个异常
。该异常会停止 SAX 解析器,然后代码用它找到的数据做它需要做的任何事。
该说的都已经说了,SAX 和 DOM 各有千秋。本章余下的部分将讨论为什么您可能需要使用不同的接口。
SAX 问题
公平而言,SAX 解析器也有些问题引人关注:
SAX 事件是无状态的。当 SAX 解析器在 XML 文档中发现文本时,它就向您的代码发送一个事件。该事件仅仅给您发现的文本;它不告诉您什么
元素包含那个文本。如果您想知道这一点,则必须自己编写状态管理代码。
SAX 事件不是持久的。如果应用程序需要一个数据结构来对 XML 文档建模,则必须自己编写那样的代码。如果您需要从 SAX 事件访问数据,并
且没有把那个数据存储在代码中,那么您不得不再次解析该文档。
SAX 不是由一个集中管理的组织控制的。尽管到目前为止这还没有引起什么问题,但如果 SAX 是由象 W3C 这样的一个组织控制的话,有些开发
人员会感觉更自在。
JDOM
用 DOM 和 SAX 模型完成某些任务时的困难使 Jason Hunter 和 Brett McLaughlin 感到失望,于是他们创建了 JDOM 包。JDOM 是基于 Java 技
术的开放源码项目,它试图遵循 80/20 规则:用 DOM 和 SAX 20% 的功能来满足 80% 的用户需求。JDOM 使用 SAX 和 DOM 解析器,因此它是作
为一组相对较小的 Java 类被实现的。
JDOM 的主要特性是它极大地减少了您必须编写的代码数量。尽管本篇介绍性教程并不深入讨论编程主题,但 JDOM 应用程序的长度通常是 DOM
应用程序的三分之一,大约是 SAX 应用程序的一半。(当然,坚持使用 DOM 的纯粹主义者会建议说:从长远来看,学习和使用 DOM 终会有所回
报)。JDOM 并不做所有的事,但对于大多数您要做的解析,它可能正好适合您。
用于 XML 解析的 Java API
尽管 DOM、SAX 和 JDOM 为大多数常见任务提供了标准接口,但仍有些事情是它们不能解决的。例如,在 Java 程序中创建 DOMParser 对象的过
程因 DOM 解析器的不同而不同。为了修正这个问题,Sun 发布了 JAXP(用于 XML 解析的 Java API,Java API for XML Parsing)。该 API 为
使用 DOM、SAX 和 XSLT 处理 XML 文档提供了公共接口。
JAXP 提供的诸如 DocumentBuilderFactory 和 DocumentBuilder 之类的接口为不同的解析器提供了一个标准接口。还有一些方法可以允许您控
制底层的解析器是否可以识别名称空间以及是否使用 DTD 或模式来验证 XML 文档。
哪种接口适合您?
为了确定哪种接口适合您,您需要理解所有接口的设计要点,而且需要理解应用程序用您将要处理的 XML 文档来做什么。考虑下面的问题将有助
于您找到正确的方法。
要用 Java 编写应用程序吗?JAXP 使用 DOM、SAX 和 JDOM;如果您用 Java 编写代码,那么您应使用 JAXP 将您的代码与各种解析器实现的细
节隔离。
应用程序将如何部署?如果您的应用程序将要作为 Java applet 部署,那么您会希望使要下载的代码数量最小,别忘了 SAX 解析器比 DOM 解析
器小。还要知道使用 JDOM 时,除了 SAX 或 DOM 解析器之外还要求编写少量的代码。
一旦解析了 XML 文档,还需要多次访问那些数据吗?如果您需要回过头来访问 XML 文件的已解析版本,DOM 可能是正确的选择。而 SAX 事件被
触发时,如果您以后需要它,则由您(开发人员)自己决定以某种方式保存它。如果您需要访问不曾保存的事件,则必须再次解析该文件。而
DOM 自动保存所有的数据。
只需要 XML 源文件的少量内容吗?如果您只需要 XML 源文件的少量内容,那么 SAX 可能是正确的选择。SAX 不会为源文件中的每个东西创建对
象;您要确定什么是重要的。使用 SAX,您要检查每个事件以了解它是否与您的需要有关,然后相应地处理它。更妙的是,一旦找到您正在寻找
的东西,您的代码就会抛出一个异常来完全停止 SAX 解析器。
您正在一台内存很少的机器上工作吗?若是的话,不管您可能考虑到的其它因素是什么,SAX 是您的最佳选择。
要知道还存在用于其它语言的 XML API;尤其是 Perl 和 Python 社区有极佳的 XML 工具。
XML 标准
XML 世界中存在多种标准。除了基本 XML 标准以外,其它标准定义了模式、样式表、链接、Web 服务、安全性和其它重要项目。本章介绍最流行
的 XML 标准,并为您指出了查找其它标准的参考资料。
names/。
XML Schema
XML Schema 语言定义成以下三个部分:
入门位于 w3.org/TR/xmlschema-0,它介绍了 XML 模式文档及其设计用途;
文档结构的标准位于w3.org/TR/xmlschema-1,它说明了如何定义 XML 文档的结构;
数据类型的标准位于w3.org/TR/xmlschema-2,它定义了一些常用数据类型以及创建新类型的规则。
本教程在定义文档内容中简要地介绍了模式;如果您对于用 XML 模式可以做的所有事情,需要了解完整的详细信息,那么最好先阅读“入门”。
XSL、XSLT 和 XPath
可扩展样式表语言(Extensible Stylesheet Language(XSL))定义了一组元素(称为格式化对象),它们描述应该如何格式化数据。为清晰起
见,通常将该标准称为 XSL-FO 以和 XSLT 进行区分。尽管它主要是设计用于生成高质量的可打印文档,但您也可以使用格式化对象从 XML 生成
音频文件。XSL-FO 标准位于 w3.org/TR/xsl/。
用于转换的可扩展样式表语言(Extensible Stylesheet Language for Transformation(XSLT))是一个描述如何将 XML 文档转换成别的东西
的 XML 词汇表。该标准位于w3.org/TR/xslt(结尾没有斜杠符号)。
XPath(XML 路径语言,XML Path Language)是描述 XML 文档中位置的语法。您使用 XSLT 样式表中的 XPath 来描述您希望转换 XML 文档的哪
个部分。XPath 也用在其它 XML 标准中,这就是为什么它是独立于 XSLT 的标准的原因。XPath 在 w3.org/TR/xpath(结尾没有斜杠符号)中定
义。
DOM
文档对象模型定义了如何将 XML 文档转换为驻留内存的树结构。DOM 在 W3C 的许多规范中都有定义:
核心 DOM 定义 DOM 本身、树结构、以及代码遍历树时会发现的各种节点和异常。完整的规范在 w3.org/TR/DOM-Level-2-Core/。
事件定义对于树可以发生的事件,以及如何处理这些事件。该规范试图协调 Netscape 和 Internet Explorer 浏览器的版本 4 之后所支持对象
模型之间的差异。该规范位于 w3.org/TR/DOM-Level-2-Events/。
样式定义程序如何访问 XSLT 样式表和 CSS 样式表。该规范位于 w3.org/TR/DOM-Level-2-Style/。
遍历和范围定义一些允许程序遍历树或定义树中节点范围的接口。可以在 w3.org/TR/DOM-Level-2-Traversal-Range/ 找到完整的规范。
视图为文档本身定义 AbstractView 接口。请参阅 w3.org/TR/DOM-Level-2-Views/ 以获得更多信息。
SAX、JDOM 和 JAXP
用于 XML 的简单 API 定义了一些事件和接口,用于与符合 SAX 的 XML 解析器进行交互。可以在
www.saxproject.org 上找到完整的 SAX 规范
。
Jason Hunter 和 Brett McLaughlin 创建的 JDOM 项目位于 jdom.org/。在 JDOM 站点,您可以找到代码、样本程序和其它能帮助您入门的工具
。(有关在 developerWorks 上介绍 JDOM 的文章,请参阅参考资料)。
有关 SAX 和 JDOM 的重要一点是:二者都来自 XML 开发人员社区,而不是标准组织。它们获得的广泛接受是对全世界 XML 开发人员积极参与的
回报。
您可以在 java.sun.com/xml/jaxp/ 找到所有与 JAXP 有关的内容。
链接和引用
在 XML 世界中有两个用于链接和引用的标准:XLink 和 XPointer:
XLink(XML 链接语言,XML Linking Language)定义将不同资源链接在一起的各种方法。您可以进行正常的点对点链接(就象用 HTML <a> 元素
)或扩展的链接,后者可包括多点链接、通过第三方的链接以及定义转向给定链接的意义的规则。XLink 标准位于
www.w3.org/TR/xlink/。
XPointer(XML 指针语言,XML Pointer Language)使用 XPath 作为引用其它资源的方法。它还包括对 XPath 的一些扩展。可以在
安全性
有两个处理 XML 文档安全性的重要标准。一个是 XML 数字签名(XML Digital Signature)标准(w3.org/TR/xmldsig-core/),它定义了用于
数字签名的 XML 文档结构。您可以为任何类型的数据创建 XML 数字签名,不管它是 XML 文档、HTML 文件、纯文本、二进制数据还是其它东西
。您可以用数字签名来验证一个特定文件自签名后没有被修改过。如果您要签名的数据是 XML 文档,您可以将 XML 文档嵌入签名文件本身,这
会使数据和签名的处理变得非常简单。
另一个标准用于加密 XML 文档。可以将 XML 文档编写得易于人们阅读和理解,尽管这样做很好,但如果文档落入坏人之手就会引起麻烦。XML
加密(XML Encryption)标准(w3.org/TR/xmlenc-core/)定义了如何加密 XML 文档的各部分。
将这些标准一起使用,您就能放心地使用 XML 文档了。我可以对一个重要的 XML 文档进行数字签名,生成一个包含 XML 文档本身的签名。然后
我可以加密该文档(使用我的私钥和您的公钥)然后把它发送给您。当您收到文档时,您可以用您的私钥和我的公钥解密该文档;这可以让您知
道是我发送的文档。(如果需要,您还可以证明我发送了文档)。一旦您解密了文档,您可以使用该数字签名确定文档没有经过任何修改。
Web 服务
Web 服务是一种新的重要的应用程序。Web 服务是一段可以用 XML 发现、描述和访问的代码。在这一领域有许多活动,但有三种主要的用于 Web
服务的 XML 标准:
SOAP:最初是简单对象访问协议(Simple Object Access Protocol),SOAP 定义一个 XML 文档格式,该格式描述如何调用一段远程代码的方法
。我的应用程序创建一个描述我希望调用的方法的 XML 文档,并传递给它所有必需的参数,然后应用程序通过网络将该 XML 文档发送给那段代
码。代码接收 XML 文档、解释它、调用我请求的方法,然后发回一个描述结果的 XML 文档。SOAP 规范版本 1.1 位于 w3.org/TR/SOAP/。请访
问 w3.org/TR/ 以了解 W3C 中 SOAP 相关的所有活动。
WSDL:Web 服务描述语言(Web Services Description Language)是一个描述 Web 服务的 XML 词汇表。编写一段接收 WSDL 文档然后调用其以
前从未用过的 Web 服务的代码,这是可能的。WSDL 文件中的信息定义 Web 服务的名称、它的方法的名称、这些方法的参数和其它详细信息。您
可以在 w3.org/TR/wsdl(结尾没有斜杠符号)找到最新的 WSDL 规范。
UDDI:统一描述、发现和集成(Universal Description, Discovery, and Integration)协议向 Web 服务注册中心定义 SOAP 接口。如果您有
一段代码希望作为 Web 服务部署,UDDI 规范定义如何将您的服务描述添加至注册中心。如果您在寻找一段提供某种功能的代码,UDDI 规范定义
其它标准
还有许多其它的 XML 标准,我没有在这里深入介绍。除了象可伸缩向量图(Scalable Vector Graphic)(
www.w3.org/TR/SVG/)、SMIL(同步
最后,要查找有关 XML 标准的优秀信息来源,请访问 xml.org/xml/registry.jsp 上的 XML 资源库。该站点的特点是有数百个用于各行各业的
标准。
现实世界示例
到目前为止,我希望您相信 XML 具有能使电子商务的运行方式发生革命性变化的极大潜力。尽管潜力是巨大的,但真正重要的是市场中的实际结
果。本章描述了三个案例研究,案例中的组织使用了 XML 来简化其业务过程并改进其结果。
这里讨论的所有案例研究都来自 IBM 的 jStart 计划。jStart 团队的任务是帮助客户使用新技术来解决问题。当客户同意 jStart 约定时,他
会以一定的折扣得到 IBM 咨询和开发服务,客户将被明确告之由此产生的项目将会被作为案例研究使用。如果您想看到更多案例研究,包括涉及
Web 服务和其它新技术的案例研究,请通过 ibm.com/software/jstart 访问 jStart Web 页面。
请注意,jStart 团队不再从事 XML 项目的工作;小组当前的工作重点是从事 Web 服务。Web 服务以专门的方式使用 XML,通常是通过前面Web
服务中提到的 SOAP、WSDL 和 UDDI 标准来使用 XML。
用 XML 生成多个用户界面
除了 HTML 界面以外,还规划了 Java 客户机界面和 B2B 电子界面。针对所有这些界面,将结构化的 XML 数据转换成适当的结构和文档。该服
务首次公开展示时允许一个业务伙伴 — 加拿大证券注册系统(Canadian Securities Registration Systems)使用安全套接字层(SSL)提交
XML 事务数据。然后将该 XML 事务数据转换成用于后端事务的适当格式。
最终结果是马尼托巴省能够创建一个灵活的新应用程序,并且他们的最终用户可以更方便更快捷地访问财产注册中心。因为该省使用 XML 作为数
据格式,所以政府 IT 团队在设计新界面和新访问方法时有极大的灵活性。最棒的是,根本不必更改后端系统。
第一联合银行(First Union)使用 XML
第一联合银行(美国最大的银行之一)正在使用 Java 和 XML 重新设计它的许多应用程序。和大多数大公司一样,它有一个异构环境,有
OS/390、AIX、Solaris、HP/9000 以及 Windows NT 服务器和 Windows NT、Windows 98、Solaris 和 AIX 客户机。在这种环境下,第一联合银
行选择 Java 作为独立于平台的代码,选择 XML 作为独立于平台的数据。
用 Web 服务来帮忙!
为了解决这些问题,Hewitt 和 jStart 团队共同努力构建 Web 服务来满足 Hewitt 客户的需要。Web 服务是一种以许多有趣方式使用 XML 的新
型应用程序:
首先,Web 服务通常使用 SOAP,这是一个用于将 XML 数据从一处移至另一处的 XML 标准。
其次,Web 服务提供的接口(方法名称、参数和数据类型等)是用 XML 描述的。
再次,Web 服务的描述可以存储在 UDDI 注册中心,或从注册中心检索;所有进出该注册中心的信息都格式化为 XML。
最后,Web 服务提供的数据本身就是 XML 数据。
Hewitt 已经开发出两个应用程序,它们都证明了自己以更灵活的方式传递数据的能力:
使用 Secure Participant Mailbox,经授权的用户可以请求包含关于退休和其它员工福利的个性化信息的报告。
使用 Retirement Access B2B Connection,经授权的用户可以获得客户的 401(k) 财务信息的详细情况。
这些应用程序都从现有的旧系统检索数据,使用 XML 格式化数据,然后在 Web 上传递格式化的信息。因为这些应用程序构建于开放标准之上,
所以 Hewitt 可以快速地完成它们的开发。最妙的是,这些应用程序的灵活性使 Hewitt 从其竞争对手中脱颖而出。
“我们把 Web 服务看作一种工具,它通过无所不在的数据网络,对我们参与者的业务服务和数据提供一种开放、非专有的访问。”Hewitt 首席
技术决策专家 Tim Hilgenberg 这样说道。最终结果是:Hewitt 用较低的成本较快地开发出更灵活的应用程序,客户们能够更好地访问他们的数
据,并且不必更改 Hewitt 现有的旧应用程序。
案例研究总结
在所有这些案例研究中,各公司都使用 XML 来创建独立于系统的数据格式。XML 文档可以表示那些可以从一个系统或过程移到另一个的结构化数
据。当前端和后端应用程序更改时,XML 可以在它们之间移动而保持不变。更妙的是,当越来越多的前端和后端应用程序添加进来时,XML 的使
用将现有应用程序与任何更改都隔离起来。当 Web 服务变得越来越普遍时,XML 还将用来传输数据。
建议和参考资料
行动起来!
此时此刻,我希望您已经相信 XML 是移动和操作结构化数据的最佳方法。如果您现在还没有使用 XML,您该如何开始呢?下面是一些建议:
确定您要将什么数据转换成 XML。通常这是需要从一个系统移到另一个系统的数据,或必须转换成不同格式的数据。
了解是否有现有的 XML 标准。如果您正在研究很常见的数据,例如采购订单、医疗记录或股票报价,则很可能已经有人为那些数据定义了 XML
标准。
了解您现有的工具是否支持 XML。如果您正在使用数据库软件包、电子表格或其它数据管理工具的最新版本,则您的现有工具(或其升级版本)
很可能可以使用 XML 作为输入或输出格式。
学习如何构建基于 XML 的应用程序。您需要理解您的数据现在是如何存储的,需要如何转换它,以及如何将您的 XML 开发工作与现有的应用程
wxxmcol/ 找到他所有专栏文章的最新列表。
加入适当的标准组织。考虑加入象万维网协会(W3C)这样的组织,以及象 HR-XML.org 这样特定于业界的组织。成为这些组织的成员将有助于您
跟踪业界中所发生的事件,而且使您有机会塑造 XML 标准的未来。
避免专有产品的诡计。在开发工作中仅使用基于标准的技术很重要;抵制为您提供所谓改进的供应商的诱惑。XML 的优点之一是您对数据有完全
的控制权。一旦它受到某个专有数据格式的限制,您就失去了极大的控制权。
联系 jStart 团队。如果您认为您的企业可以使用 jStart 约定模型,请与该团队联系以了解您可能得到什么服务?
关注 developerWorks。我们的 XML 专区有涉及各种 XML 主题的数千页内容,包括 DTD 和模式开发、XML 编程和创建 XSLT 样式表。
参考资料
下面是一些可以帮助您开始的参考资料:
dW XML 专区是 XML 参考资料的“一站式商店”。请参阅 www-106.ibm.com/developerworks/xml 以获取您一直希望了解的有关 XML 的内容。
XML 工具: developerWorks 有一个系列的“Fill your XML toolbox”文章,它们描述用于各种语言的 XML 编程工具:
C/C++:请在 www-106.ibm.com/developerworks/library/x-ctlbx.html(developerWorks,2001 年 9 月)参阅 Rick Parrish 的文章。
Java:请在 www-106.ibm.com/developerworks/library/java-xml-toolkit/index.html(developerWorks,2000 年 5 月)参阅 Doug Tidwell
的文章。
Perl:请在 www-106.ibm.com/developerworks/library/perl-xml-toolkit/index.html(developerWorks,2001 年 6 月)参阅 Parand Tony
Darugar 的文章。
PHP:请在 www-106.ibm.com/developerworks/library/php-xml-toolkit.html(developerWorks,2000 年 6 月)参阅 Craig Knudsen 的文章
。
除了这些文章以外,请在 www-106.ibm.com/developerworks/library/l-pxml.html 参阅 David Mertz 在其“Charming Python: Revisiting
XML tools for Python”文章中对 Python XML 工具的评论。
veloperworks/education.nsf/dw/xml-onlinecourse-bytitle 以获得最新的列表。
IBM 的 jStart 团队:jStart 团队使用新技术(例如 XML Web 服务)以非常低的成本帮助客户构建解决方案。作为回报,那些客户同意让 IBM
将他们的项目作为案例研究公布。要了解更多信息,请参阅 ibm.com/software/jstart。
XML 标准:下面是本教程中提到的所有 XML 标准的字母顺序列表。
DOM,文档对象模型:
核心规范: w3.org/TR/DOM-Level-2-Core/
事件规范: w3.org/TR/DOM-Level-2-Events/
样式规范: w3.org/TR/DOM-Level-2-Style/
遍历和范围规范: w3.org/TR/DOM-Level-2-Traversal-Range/
视图规范: w3.org/TR/DOM-Level-2-Views/
HR-XML.org,人力资源 XML 协会(Human Resources XML Consortium):hr-xml.org
JAXP,用于 XML 解析的 Java API(Java API for XML Parsing):java.sun.com/xml/jaxp/
JDOM,不代表任何缩写形式:jdom.org/
SAX,用于 XML 的简单 API(Simple API for XML):saxproject.org/
SMIL,同步多媒体集成语言(Synchronized Multimedia Integration Language):
www.w3.org/TR/smil20/SOAP,过去用于代表简单对象访问协议(Simple Object Access Protocol),但现在正式不代表任何缩写形式:w3.org/TR/SOAP/
SVG,可伸缩向量图(Scalable Vector Graphics):
www.w3.org/TR/SVG/UDDI,统一描述、发现和集成协议(Universal Description, Discovery, and Integration Protocol):uddi.org
WSDL,Web 服务描述语言(Web Services Description Language):w3.org/TR/wsdl(结尾没有斜杠符号)
XLink,XML 链接语言(XML Linking Language):w3.org/TR/xlink/
XML,最基础的标准:w3.org/TR/REC-xml
XML 数字签名(XML Digital Signature):w3.org/TR/xmldsig-core/
XML 加密(XML Encryption):w3.org/TR/xmlenc-core/
XML 名称空间(XML Namespaces):w3.org/TR/REC-xml-names/
DTD 和模式的 XML 资源库(XML Repository):xml.org/xml/registry.jsp
XML Schema:
第 0 部分 — 入门:w3.org/TR/xmlschema-0
第 1 部分 — 文档结构:w3.org/TR/xmlschema-1
第 2 部分 — 数据类型:w3.org/TR/xmlschema-2
XPath,XML 路径语言(XML Path Language):w3.org/TR/xpath(结尾没有斜杠符号)
XPointer,XML 指针语言(XML Pointer Language):
www.w3.org/TR/xptr/XSL-FO,用于格式化对象的可扩展样式表语言(Extensible Stylesheet Language for Formatting Objects):w3.org/TR/xsl/
XSLT,可扩展样式表语言(Extensible Stylesheet Language):w3.org/TR/xslt(结尾没有斜杠符号)
有关 JDOM 的更多信息,请参阅以下 developerWorks 文章: