XML介绍
经常会出现这种情况,新思想产生之后,人们回过头来往往觉得其非常简单并且理所应当,以至于每个人都希奇竟然以前不是这样。这种情况往往表明所谓的新思想究竟不是真正的全新的思想。Java这一革新性的语言就是吸取之前的所有程序语言的思想才得以出现的。就象Java源于之前的程序语言一样,现在出现了XML——可扩展标记语言(the Extensible Markup Language)。XML是一种方便人们描述数据的轻量语言。
XML为标记结构性信息如文本提供了一种简单而通用的格式。XML承继了Html这一通用文本表示格式并将之推广,从而可处理任何类型的数据。在此过程中,XML不仅重铸了HTML并且正影响着商业业务关于其自身信息的考虑。在世界越来越被文档和数据交换驱策的情况下,XML时代来临了。
一点背景知识
XML和HTML之所以被称为标记语言(markup languages)是因为XML用象征结构和意义的标签来包裹文本部分,从而为纯文本文档添加结构信息,这一点和人们用钢笔来标识句子、添加注释很相似。然而HTML定义了一系列的标签和标签结构,而XML没有预先定义这些,XML的创建者可以定义标签、规则以及它们的含义。
XML和HTML都源自标准通用标记语言SGML。SGML(Standard Generalized Markup Language)是所有标记语言的始祖,在出版业(包括O'Reilly)广泛应用多年。但是直到Web通行,它才通过HTML流传开来。HTML起自SGML的一个小小应用,假如HTML无所不能的话,这说明简单胜过一切。
然而尽管HTML曾经颇为风行,但最终结果表明它还大有局限。使用HTML的文档把结构信息(如<head>和 <body>)和描述信息(举个尤其过分的例子:<blink>)不恰当地混在一起。这种把模型和用户界面搅在一块儿的方式对HTML作为数据交互格式带来了限制,因为计算机难以理解这种方式。XML文档完全由结构组成,应用含义取决于文档读者。本章我们将看到,有几种相关语言用于解释和转换XML以利于其显示和后续处理。
文本还是二进制
Tim Berners-Lee二十世纪八十年代后期在欧洲粒子物理研究所(CERN)开始试运行Web时,他想用超文本组织规划信息。由于Web需要一种协议,HTTP——一种基于文本的简单客户端-服务器协议创建出来。纯文本方式到底有什么过人之处呢?比如说,Tim为什么不采用微软的Word格式做为Web文档的基础呢?基于二进制的、人类不易阅读的格式和协议难道不是效率更高吗?既然从Web诞生到现在有数以百万亿计的HTTP事务,让它们用英文单词“GET”和“POST”,这真的个好主意吗?
答案是“是”,如我们现在看到的一样。开发人员显然更轻易和人类可读的东西打交道。尽管可以在时间和空间上对其进行高度优化,但由于它已被普遍接受并且可轻易跨越多个平台,简单和透明显得更为重要。这是XML的首要基本原则。
通用解析器
使用文本交换数据不仅仅是一种新思想;从历史上看,必须为每个新文档格式写一个新的解析器。解析器是读取文档并能理解格式规则的应用程序,它常要求文档内容符合某些规则。例如,Java中的Properties类是专门处理标准属性文件格式的解析器。在简单电子制表程序中,我们构造了一个能理解基本数学表达式的解析器。我们将看到,随着复杂度的增加,解析可能变得非常棘手。
XML状态
本文中我们要讨论的API非常强大而且已经很好地测试过,如今它们已被广泛应用于企业级系统。遗憾的是,现在和Java绑定的XML工具只能部分解除开发者的负担。
尽管我们已经从低级的字符串处理跨越到公共的结构化文档格式,但标准工具通常仍然要求开发人员编写低级代码来遍历文本内容,手工解析字符串数据。这样的程序难免有点不太稳定,而且其中的大部分工作单调乏味。下一步我们将使用生成工具读取XML文档描述(XML DTD或XML Schema)并生成相应的Java类,或者将已经存在的类自动绑定到XML数据上。
XML API
Java1.4自带所有和XML协同工作的基本API,包括javax.xml标准扩展包,该包处理用于XML的简单API(Simple API for XML,SAX)和文档对象模型(document.nbspObject Model,DOM)以及扩展的风格表单语言(eXtensible Stylesheet Language,XSL)转换。假如您使用的是Java1.4之前的版本,您仍然可以使用所有这些工具,但您必须从http://java.sun.com/xml/.上下载各个相应程序包。
XML和Web浏览器
微软公司的IE网页浏览器是第一个显式支持XML的浏览器。假如您在IE5.0或以上版本中载入XML文件,文件将使用非凡的样式菜单显示为一棵树的形式。通过使用动态HTML,该样式菜单答应查看文档的时候收缩和展开树节点。IE也支持在浏览器中直接进行基本的XSL转换。
Netscape 6.x 和 最新的 Mozilla也能理解XML内容并支持通过XSL显示文档。然而到本章写作的时候为止,它们缺省状况仍不能提供友好的阅读工具。您可以通过使用“查看源文件”选项来使XML以较好形式显示。但一般而言,假如您通过以上这些浏览器或其它不显式转换XML的浏览器加载XML文档,这些浏览器只是简单地显示剥除所有标签(结构信息)之后的文档文本。这是它们作用于XML的预定方式。
XML基础
XML的基本语法相当简单。假如您有HTML的相关经验,那您实际上对XML也有所了解。象HTML一样,XML将信息表示为使用标签添加结构的文本。标签以夹在小于号(<)和大于号(>)之间的名字开始。和HTML不同的是,XML的标签必须匹配。换言之,开始标签之后必须有相应的结束标签。结束标签很象开始标签,但它以小于号和斜杠(</)打头。开始标签、结束标签以及开始标签和结束标签之间的所有内容合起来被称为XML文档的元素(element)。元素中可以包含其它元素,但它们必须正确嵌套,所有元素内的开始标签必须在元素本身结束前用结束标签结束。元素可以包含纯文本和文本和元素的混合物。注释放置于标记“<!—”和“ -->”之间。下面是几个例子。
<!-- Simple -->
<Sentence>This is text.</Sentence>
<!-- Element -->
<Paragraph><Sentence>This is text.</Sentence></Paragraph>
<!-- Mixed -->
<Paragraph>
<Sentence>This <verb>is</verb> text.</Sentence>
</Paragraph>
<!-- Empty -->
<PageBreak></PageBreak>
空白标签可以用一个以斜杠和大于号结束的单个标签更紧凑的表示(/>),如下所示:
<PageBreak/>
属性
XML元素可以包含属性,也就是开始标签中提供的名-值对。如:
<document.nbsptype="LEGAL" ID="42">...</document>
<Image name="truffle.jpg"/>
属性值必须包含在引号中,使用双引号(”)或单引号(’)都可以。单引号在值本身含有双引号时尤其有用。
属性用于和元素数据相关的简单、非结构性的性质或标识。总是可以把属性组织为子元素,所以没有必须使用属性的真正要求。但使用属性通常使XML文档更赋逻辑,更易阅读。在上面的小例子片断中,document.素的属性type和 ID代表文档的元数据。我们可能期望代表document.Java类拥有文档类型(如LEGAL)的静态标识。对Image元素而言,属性是只包含文件名的更为简洁的形式。通常属性没有重要的内部结构,是不可再分的;而子元素却可以任意复杂。
XML文档
XML文档以下列文档头开头并且有一个根元素。
<?xml version="1.0" encoding="UTF-8"?>
<Mydocument>
</Mydocument>
文件头指明了XML的版本和文件的编码特征。可以把元素层次理解为一棵树的形式,根元素也就是元素层次的顶层元素。假如您漏掉这样的文件头或者XML文本中没有单个根元素,那样的东西只能称为XML片断。
编码
XML文档的默认编码方式是UTF-8,一种ASCII使用者易于使用的8位Unicode编码方式。但XML文档可以通过指定XML文件头的encoding属性来指定文档编码。
XML文档中有些字符是需要保留使用的,比如表示元素标签的字符“<”和“>”。假如您需要在XML文档内容中包含这些字符,则必须对它们进行转码。XML提供了称为“实体(entities)”的转义机制以对非凡结构进行转码。XML中有五种预定义的实体。如表23-1所示。
表23-1 XML实体
Entity
Encodes
&
& (ampersand)
<
< (less than)
>
> (greater than)
"
" (quotation mark)
'
' (apostrophe)
也可以使用被称作字符数据(CDATA)的非凡的不解析文本段来进行编码。一个CDATA块以<![CDATA[开始,以]]>结束,如下所示:
[code]<![CDATA[ Learning Java, O'Reilly & Associates ]]>[/code]
CDATA块看起来有点象注释,但CDATA块中的数据确实是XML文档的一部分,只不过对解析器来说是不透明的。
命名空间
您可能看到了HTML具有用来构造网页的<body>标签,试想一下我们要为殡仪馆编写XML,而殡仪馆因为某些令人恐怖的原因也使用<body>标签。假如要将HTML和尸体信息混在一块儿可能会带来些问题。
在这种情况下,假如您把HTML标签和殡仪馆标签当做一种语言,文档使用的元素(标签名称)就是这些语言的词汇。XML命名空间指明对于给定元素您使用的是哪种字典,从而让我们可以把它们随意混合在一起。(稍后我们将讨论XML Schema,它要求语言必须遵守语法和词法检查)。
命名空间使用xmlns属性指定,xmlns的值是定义该命名空间标签集合(常包括标签含义)的统一资源标识符(Universal Resource Identifier,URI):
<element xmlns="namespaceURI">
URI不必是URL,URI的范围比URL更为宽泛。URI实际上常被简单视作独特的字符串。对描述命名空间的文档来说,URI实际上通常也是URL,但这只是就一般情况而言。
xmlns命名空间属性可以应用到元素和其所有子元素上,这称作该元素的默认命名空间。
<body xmlns="http://funeral-procedures.org/";>
但通常在一个一个的标签上指定命名空间更让人满足。要做到这点,我们可以使用xmlns属性为命名空间定义一个非凡的标识符,并且将这个标识符做为要使用的标签前缀。比如:
<funeral xmlns:fun="http://funeral-procedures.org/";>
<html><head></head><body>
<fun:body>Corpse #42</fun:body>
</funeral>
在以上的XML代码片中,我们用在<funeral>标签中定义的前缀“fun:”限制body标签。在这种情况下,我们还可以反过来用它限制根标签。如:
<fun:funeral xmlns:fun="http://funeral-procedures.org/";>
在XML的历史上,对命名空间的支持相对而言时间不长,并非所有解析器都支持命名空间。要想支持命名空间,我们随后讨论的XML解析器工厂有一个转换开关以指明您是否需要能理解命名空间的解析器。
factory.setNamespaceAware(true);
我们将在以后的SAX和DOM部分进一步讨论XML解析。
验证
符合XML基本规则,具有正确的编码以及匹配的标签的文档称为形式良好的XML文档。但文档只是在句法上符合规范并不意味它就是有意义的文档。文档类型定义(document.nbspType Definitions,DTD)和XML Schema这两个相关规范为XML元素提供了语法规范的方式,它们答应您自己创建语法规则,比如在Address元素中City元素只能出现一次。XML Schema是进一步提供了描述标签数据内容验证的灵活语言,包括简单的数据类型和由数字及字符串组成的复杂类型。尽管XML Schema包含数据验证和定义元素规则以外的东西,是最终的解决方案,但到目前为止XML Schema还是理论多于实际——至少就其和Java的集成而言是如此,我们希望这种情况能迅速改变。
通过DTD或XML Schema描述检查并符合规则的文档称为有效的文档。文档可能是形式良好的但并不是有效的,反之却不可能。
从HTML到XHTML
不严格的说来,现在应用最多的XML的形式是HTML。之所以说不严格,是因为HTML还算不上是形式良好的XML。HTML标签违反了XML不答应空元素的规则,一个典型的例子是HTML常用的没有结束标签的<p>