本章将介绍可扩展标记语言(Extensible Markup Language,XML)及其相关规范。
本节将介绍XML的基础知识。目的让你知道XML入门所需的足够信息,理解XML牵涉到哪些方面。(在本教程的后面几节中,你将具体学习XML)。首先我们介绍XML得以在信息存储和交换领域取得成功的几个特性,然后让你大致了解一下如何使用XML。
XML是一种基于文本的标记语言,它很快就将成为Web上数据交换的标准。像HTML一样,你可以使用标签(括在尖括号中的标识符)来标识数据。统一地,这些标签都叫做“标记(markup)”。
但是与HTML不同的是,XML标签用于标识 数据,而不是规定数据的显示格式。对于那些HTML标签中形如“用粗体显示数据”(<b> …</b>)的地方,XML标签则表现为程序中的一个字段名。它为一个数据定义一个标记(label)来表示该数据。(例如:<message>...</message>
)
注意:由于标识数据可以让你看出其中的意义(如何解释它,应该如何处理它),XML有时也被描述为一种能够指明数据语义(意义)的机制。
与定义某个数据结构的字段名时所使用方法一样,你可以随心所欲地使用任何对一个给定的应用有用的XML标签。不过,对于要使用同样XML数据的多个应用来说,它们理所当然地要承认它们要用到的标签名。
下面的例子展示了在一个消息发送应用中要用到的一些XML数据:
<message>
<to>[email protected]</to>
<from>[email protected]</from>
<subject>XML Is Really Cool</subject>
<text>
How many ways is XML cool? Let me count the ways...
</text>
注意:本教程的所有部分,我们都使用黑体文本来突出显示要引起你注意的地方。实际上,XML本身没有要求任何部分使用黑体!
在这个例子中,标签指明了整个message(消息)、消息的目的地和发送方地址、主题,以及消息的文本。像HTML一样,<to>标签有一个配对的介绍标签</to>。在这个标签和该及其配对结束标签之间的数据定义了XML数据的一个元素。注意,<to>标签中的内容完全包含在<message>…</message>标签所辖范围之内。由于在XML中一个标签可以包含其他的标签,所以XML便可以表
示层次性的数据结构。
有一个与HTML类似的地方就是,空白是不计的。因此,为了提高可读性,你可以用它来调整数据格式,而不必担心会增加处理数据时的复杂度。不过,与HTML不同的是,在XML中你可以轻松地搜索那些在主题中包含了“cool”字样的消息的数据集合,因为XML标签指明了数据的内容,而不是指定数据的显示格式。
标签还可以包含属性——包含在标签中作为标签的一部分的附加信息,放在标签的尖括号中。下面的例子展示了一个email message结构,并且为“to”、“from”和“subject”字段使用了属性:
<message to="[email protected]" from="[email protected]"
subject="XML Is Really Cool">
<text>
How many ways is XML cool? Let me count the ways...
</text>
和在HTML中一样,属性名的后面跟一个等号,等号的后面是属性值,多个属性之间用空格隔开。不过,与HTML不同的是,在XML中各属性之间的逗号不会被忽略——如果有这样的逗号,将产生错误。
既然用属性和用标签都可以设计一个像<message>这样的数据结构,那么就很有必要指出哪种设计方案最能适合目的。在“设计XML数据结构”一节向你介绍的内容有助于帮你理解何时使用属性,何时使用标签。
XML和HTML之间的一个很大的差别就是XML文档都要求有良好的格式。判断一个XML文档是否格式良好有几条规则,但最重要的一条是每个标签都应该有一个对应的结束标签。所以,在XML中,</to>标签并非可选的,而是必需的。<to>元素只有在碰到</to>标签时才算结束。
注意:一个well-formed的XML文档的另一个重要方面是所有标签都是完全嵌套的。所以你可以有这样的格式:<message>..<to>..</to>..</message>,但是不可以用这样的格式:<message>..<to>..</message>..</to>。对于良好格式的XML文档的要求的完整列表包含在XML常见问题问答(FAQ)列表中,网址为http://www.ucc.ie/xml/#FAQ-VALIDWF。(这个FAQ在w3c的“Recommended Reading”列表中,网址:http://www.w3.org/XML/)
Sometimes, though, it makes sense to have a tag that stands by itself. For example, you might want to add a "flag"
tag that marks message as important. A tag like that doesn't enclose any content, so it's known as an "empty tag". You can create an empty tag by ending it with />
instead of >
. For example, the following message contains such a tag:
不过,有时候使用一个独立的标签也是可取的。例如,你可能想使用一个“flag”标签来标明某个message是重要的。由于这种标签没有包括进任何内容,因此被称为“空标签”。你可以创建一个空标签,以/>结束,而不是以>结束。例如,下面的message中就包含了那样的一个标签:
<message to="[email protected]" from="[email protected]"
subject="XML Is Really Cool">
<flag/>
<text>
How many ways is XML cool? Let me count the ways...
</text>
注意:通过使用空标签,你就可以不必为保持文档的良好格式而麻烦地使用<flag></flag>了。通过创建一个文档类型定义(Document Type Definition),即DTD,你就可以决定哪些标签可以是空标签。随后不久我们就会讨论这个问题。如果没有DTD,那么文档中就可以包含你喜欢的任何类型的标签,只要保证文档是well-formed的就行了。
<message to="[email protected]" from="[email protected]"
subject="XML Is Really Cool">
<!-- This is a comment -->
<text>
How many ways is XML cool? Let me count the ways...
</text>
XML Prolog(序言)
最后要注意的是XML文件总是以一个prolog开头的。最简单的prolog包含一个声明,该声明指定了本文档为XML文档,如下所示:
XML声明实质上与HTML的头部是一致的,不同之处就在于它使用了<?...?>,它可能包含如下属性:
表明用于数据编码的字符集。“ISO-8859-1”即“Latin-1”,西欧和英国语言字符集。(缺省为压缩的Unicode:UTF-8)
该属性表明文档是否引用了外部实体或者外部数据类型规范(参见下面的介绍)。如果没有,那么该属性的值就设为“yes”。
prolog还可以包含对一些实体(在文档范围内要引用时插入的项)的定义,以及一些规范,这些规范规定了文档中哪些标签是合法的,上述定义和规范都是在一个文档类型定义(DTD)中声明的,DTD可以直接在prolog中定义,也可以使用外部规范文
件的指示器来定义。不过这些都是以后的教程要讲到的主题。要了解XML这些方面的更详细的信息以及其他方面的信息,参见w3c XML网页上的推荐读物列表,网址:http://www.w3.org/XML/。
注意:声明不是必需的。但是,每次创建一个XML文件时都包含声明是个好习惯。声明一般包括版本号,这是最基本的,最好还应该包含encoding类型。如果XML标准在将来还会扩展,如果还需要因为地理位置的不同而将数据本地化,那么,那些标准就可以起到简化的作用。
XML文件还可以包含处理指令(processing instruction),这些指令可以将命令或信息传给正在处理XML数据的应用。处理指令有如下格式:
其中target是进行XML数据处理的应用的名称,instructions是一个字符串,包含了传给应用的信息和命令。
由于这些指令都是应用专属(application specific)的,因此XML文件可以有多条处理指令,用来告诉不同的应用去做类似的事情,但是可能做事的方式各不相同。例如,在为一个幻灯片显示而设计的XML文件中,可以有这样的指令,这些指令让说话者指定他所表达的内容的技术性的或者执行级的表示。如果使用了多个表示程序,那么这些程序就需要不同版本的处理指令(当然,如果应用能识别标准指令的话,事情会更好办一些。)
注意:目标名“xml”(不分大小写)在XML标准中是保留字。从某种意义上说,声明也是一种符合那种标准的处理指令。(然而,如果以后要用到解析器的话,你就会发现在使用解析器时声明对于那些接受处理指令的方法是不可见的。)
XML之所以被广泛接受,是有很多原因的。下面就列出了最突出的几点。
由于XML不是二进制格式,因此从标准的文本编辑器到可视化开发环境,你可以在任何环境下创建和编辑XML文件。这样大大地方便了你调试程序,并且用XML来存储少量数据也十分可取。另一方面,通过一个相对于数据库的XML前端,高效存储大量XML数据同样也是可能的。所以,XML可以提供适合广泛要求的规模,小到配置文件,大到公司级的数据仓库。
XML可以描述出数据的类型,但并不描述数据的显示格式。由于XML使用标签来标识信息,并将数据拆分几个部分,所以email程序可以处理XML文件,搜索程序也可以从中查找发送给某个人的消息,而且地址簿还可以从消息的其他部分提取出地址信息。简言之,由于信息的不同部分在XML中都被标识了,所以不同的应用可以通过不同的方式使用信息的这些不同部分。
如果对显示有特殊要求,样式表标准XSL可以告诉你如何描绘数据。例如,对下面语句的样式表:
<to>[email protected]</to>
2. 用粗体显示“To”,后面加上空格
3. 显示目标数据
当然,这样的事情你可以在HTML中也可以做到,但是你不可以用搜索程序和地址提取程序或其他类似的程序来处理数据。更重要的是,由于XML天生就是样式自由(style-free)的,你可以使用完全不同的样式表来产生postscript格式的输出,这些postscript格式有TEX、PDF或其他还没有发明的新格式。这种灵活性可以达到一位作者所描述的那样的程度:“先验(future-proof)”你的信息。你现在创建的XML文档可以用在将来的文档传送(document-delivery)系统中,虽然这样的系统还纯属乌有。
XML文档另一个良好的方面就是它们可以由一些各自独立的实体组成。虽然你也可以用HTML做到这一点,但是只有通过链接到其他的文档的方式才行。与HTML不同,XML实体可以“内联”在一个文档中。包含进来的那些区段看上去就是文档中很一般的某
个部分——你可以一次搜索整个文档,或者可以将它下载到一个块中。这样一来,你就可以将文档模块化,而不需要使用链接。你可以将某个区单源化(single-source),这样一来,只需作一次修改,就可以在所有用到该区的地方生效。
正因为HTML,现在大家都认为定义文档之间的链接是必不可少的。本教程的下一节,XML and Related Specs: Digesting the Alphabet Soup(URL:http://java.sun.com/webservices/docs/1.1/tutorial/doc/IntroXML3.html#wp64046),将讨论链接规范计划。该建议使你可以定义双程链接、多目标链接、“展开”链接(单击这样的链接时,目标信息将在页面内显示出来,而不会新开一个页面),以及由第三方页面定义的两个页面之间的链接。
正如前面提到的那样,由于XML使用了正规的、一致的符号,因此要创建一个处理XML数据的程序就更加简单。例如,在HTML中,一个<dt>标签可以由</dt>作为结束,也可以由<dt>、 <dd>或 </dl>作为结束。这样一来,编写处理程序就有些困难了。而在XML中,<dt>标签必须以</dt>结束,除非将它定义成<dt/>标签。这种约束机制只是所有约束机制中严格意义上的一部分,这些约束机制使得XML具有良好的格式。(如果不这样的话,XML解析器就不能读取数据了。) 并且,由于XML是一种厂商无关(vendor-neutral)标准,因而你可以从几个XML解析器中选择其中的任何一个,只要可以处理XML数据。
最后,XML文档得益于它的层次结构。通常来说,层次文档结构访问起来会更快些,因为你可以由表及里地找到你需要的那一部分,就像访问内容的表(table)一样。而且,这样的结构也更加便于重排,因为每一块都是界定的。例如,在一个文档中,你可以将一个标题移到一个新的位置,标题下的所有内容都将随标题一起移动到那个位置,而无需选择内容、键切并将所选内容粘贴到新的位置。
绑定,使用DTD或模式(定义了XML数据的结构)来自动生成一个在应用中具有重要意义的部分,这一部分最终将用于数据处理
XML正快速成为Web用来表示数据的当然选择。当XML与用ava 编程语言写成的网络中心程序(负责发送和接收信息)一起使用时,效果是惊人的。例如,一个客户端/服务器应用可以在客户端和服务器之间来回传送XML-编码的数据。
在将来,XML有潜力成为解决在各种类型的事务中进行数据交换的金钥匙,只要双方同意使用相同的标签。(例如,一个e-mail程序可以识别名为<FIRST> 和 <LAST>,或 <FIRSTNAME> 和<LASTNAME>这样的标签)。人们对于共同标准的需求将促使大量工业化标准在几年内产生。同时,可以用来“翻译”XML文档中的标签的机制也是十分重要的。这种机制包括的主题有RDF的初始化,在这里定义“meat tag”;以及XSL规范,通过这种规范就可以将XML某些标签翻译成其他的XML标签。
XML最新的一种用途就是用它来构成一种可用于描述应用的页面的显示方式的文档。这种文档,并不仅仅是用于显示,它由用户接口组件的引用和业务逻辑组件的引用组成,将这两种组件联结在一起,从而一边创建了一个应用。
当然,利用Java平台来作为那些组件的平台是很有用的。用于设计界面的JavaBeans 组件和用于设计业务逻辑的EJB组件可以一道构成那样的一个应用。尽管目前这种方案还没有应用到商业中,但很多初步的工作已经完成。
注意:用Java编程语言来编写XML-处理工具也是很好的,这种用Java编写出来的工具可以拥有XML那样的便携性。目前已经有了一些为Java平台编写的可视化XML编辑器。如果想看到编辑器、处理工具和其他XML资源的列表,请访问Robin Cover的SGML/XML网页http://www.oasis-open.org/cover/中的“Software”部分。
一旦定义了XML数据的结构(通过一个DTD或者某种模式标准),你所需要进行的大部分处理就有了定义。例如,如果模式规定了<data>元素中的文本数据必须遵从某种公认的数据格式,那么这样也就定义了数据确认标准的一个方面—— 。尽管DTD规范不能详细到这种程度,但是DTD(和模式一样)也提供了一套语法,用于指定可以出现的数据结构,以及它们出现的顺序。这些规范可以告诉你如何编写可以处理数据元素的高级代码。
但是,如果完全指定了数据结构(也可能是格式),那么你需要用于处理它们的代码就可以自动生成。这种过程就叫做绑定-创建类,即通过处理了定义数据元素的规范说明来处理这些不同的数据元素。慢慢的,你就会发现你正在使用这样的数据规范说明来创建很大一部分的代码,这样你就可以将注意力放在编写那些专用于你的应用的代码。
编程中的Holy Grail是一种可重用的、模块化的组件结构。在理想情况下,你可以轻易地得到这些组件、定制它们,然后将它们放在一起构成一个应用,在这个过程中只需添加少量的代码,并稍作编译。
保存信息的基本机制就叫做归档(archiving)。要将组件归档,你可以将组件以一种可重用的格式写入到一个输出流中。你可以从组件中读取信息,使用保存的参数创建组件的实例。(例如,如果你保存了一个table表组件,该组件的参数可能是要显示的行和列的数量。)归档的组件可以在Web的各处使用,而且用法不一。
然而,如果组件是以二进制格式归档的,并且你希望保持与前面保存的版本兼容,那么你对底层类的更改就要受到一些限制。如果你可以通过修改归档版本来反映更改,则这个问题就可以得到解决了。但是,对于二进制对象,这样做是很困难的。基于这样的考虑,人们纷纷对通过使用XML来进行归档的可行性产生了怀疑。但是,如果使用XML来将对象的状态以文本格式进行归档,那么对对象中的任何东西的修改就都可以简单到如你所说的“查找和替换”的程度。
XML的基于文本的格式还使得在用不同语言编写的应用之间转移对象变得更加简单。由于所有的这些原因,基于XML的归档很可能会在不久的将来成为一支重要的力量。
XML相当简单,而且也非常的灵活。它还有很多的用途有待于我们去发现——我们也正在开始试图描绘出它的潜能到底有多大。作为大量将要到了的标准的基础,首先要提供一种通用的语言,使得不同的计算机可以使用这种语言来相互交换数据。随着每个工业组织都为自己的需要提出了新的标准,计算机正以一种以前无法想象的方式相互连接在一起。
要了解更多背景知识以及使用XML的动机,参见Scientific American网站上的文章,网页地址:
http://www.sciam.com/1999/0599issue/0599bosak.html.