名??? 域[china_zhao整理]

名域(Namespace,也称为名称空间)在XML中是一个非常重要的概念,如果没有名域这个概念,XML的应用范围将受到很大的限制。如果您熟悉Perl或Java,那么您可能在不知不觉中使用了名域。名域的规定并没有收录在XML 1.0的标准中,而是通过后来的一份单独的标准来增补的,这份标准是“Namespaces in XML”。
在本章中,将详细叙述名域的必要性、名域的声明及应用、名域的范畴以及预设的名域等内容。

8.1? 名域的概述

XML能够使开发者为工程创建自己的标记语言。这些语言可以和工作于世界各地的类似工程的工作者们共享。使用这种方式工作的典型实例之一就是XSL。XSL本身就是用于XML样式文档的一个XML应用程序。XSL变换语言必须输出任意的、结构整洁的XML,或许还包括XSL本身。因此,需要有明确的手段来区分何为XSL转换指令的XML元素、何为输出的XML元素,即便它们有相同的名称也得要区分开!
在本节中,将首先通过一个具体的实例来阐述为什么在XML中需要使用名域,然后介绍名域的结构、声明和范畴等内容。

8.1.1? 为什么要使用名域

这里假设某一出版社原先设计了一个XML通讯录,其中包含了其近几年来出版的书的信息,发布到网上,以供书商联系。其XML文档的框架代码如下所示。
<图书信息>
<书? 出版日期="2001">
<书名>...??? </书名>
<作者>
<姓名>...??? </姓名>
<电话>
<公司电话>...</公司电话>
<住宅电话>...</住宅电话>
<手机>...</手机>
</电话>
<EMail>...</EMail>
<Fax>...</Fax>
</作者>
<定价>...??? </定价>
<摘要>...??? </摘要>
</书>

<书? 出版日期="2001">
<书名>...??? </书名>
<作者>
<姓名>...??? </姓名>
<电话>
<公司电话>...</公司电话>
<住宅电话>...</住宅电话>
<手机>...</手机>
</电话>
<EMail>...</EMail>
<Fax>...</Fax>
</作者>
<定价>...??? </定价>
<摘要>...? ??</摘要>
</书>
...
</图书信息>
为了书商的联系方便,想在“图书信息中”添加一项负责此书的“责任编辑”的联系方式。而责任编辑的信息,例如联系电话、E-mail地址等,都记录在出版社的另一份有关职员信息的XML文档中。文档基本框架的代码如下所示。
<职员名单>
<职员>
<姓名>...??? </姓名>
<部门>...??? </部门>?
<职位>...??? </职位>
<电话>
<公司电话>...</公司电话>
<住宅电话>...</住宅电话>
<手机>...</手机>
</电话>
<EMail>...</EMail>
<Fax>...</Fax>
</职员>

<职员>
<姓名>...??? </姓名>
<部门>...??? </部门>?
<职位>...??? </职位>
<电话>
<公司电话>...</公司电话>
<住宅电话>...</住宅电话>
<手机>...</手机>
</电话>
<EMail>...</EMail>
<Fax>...</Fax>
</职员>
...
</职员名单>
因此需要把“职员名单”中的部分数据和“图书信息”结合起来,修改后的“图书信息”文档基本框架如下所示。
<图书信息>
<书? 出版日期="2001">
<书名>...??? </书名>
<作者>
<姓名>...??? </姓名>
<电话>
<公司电话>...</公司电话>
<住宅电话>...</住宅电话>
<手机>...</手机>
</电话>
<EMail>...</EMail>
<Fax>...</Fax>
</作者>
<定价>...??? </定价>
<摘要>...??? </摘要>
<责任编辑>
<姓名>...??? </姓名>
<部门>...??? </部门>?
<职位>...??? </职位>
<电话>
<公司电话>...</公司电话>
<住宅电话>...</住宅电话>
<手机>...</手机>
</电话>
<EMail>...</EMail>
<Fax>...</Fax>
</责任编辑>
</书>

<书? 出版日期="2001">
<书名>...??? </书名>
<作者>
<姓名>...??? </姓名>
<电话>
<公司电话>...</公司电话>
<住宅电话>...</住宅电话>
<手机>...</手机>
</电话>
<EMail>...</EMail>
<Fax>...</Fax>
</作者>
<定价>...??? </定价>
<摘要>...??? </摘要>
<责任编辑>
<姓名>...??? </姓名>
<部门>...??? </部门>?
<职位>...??? </职位>
<电话>
<公司电话>...</公司电话>
<住宅电话>...</住宅电话>
<手机>...</手机>
</电话>
<EMail>...</EMail>
<Fax>...</Fax>
</责任编辑>
</书>
...
</图书信息>
由于“职员名单”和“图书信息”这两套XML语汇中同时包含了如“电话”、“E-Mail”元素,造成了混乱。虽然对于人来说,通过分析上下文,可以很容易地将来自两个XML文档的相同元素区别开,但是对于计算机程序来说,就是一件很不轻松的事情。因此,在这种情况下,就必须设计一种简单明了的方法,使计算机很容易处理这来自两个XML文档中的相同元素。即使没有任何名称上的冲突,仍然有必要设计一个简单明了的方法,使计算机知道哪些元素来自哪个语汇,以便使用该语汇的DTD来确认文件结构的正确性。
一个可行的方法是在“书”元素下,把一些过于笼统的子元素名(例如“姓名”、“电话”等元素)前面加上“作者”两字,也就是把它们分别改为“作者姓名”、“作者电话”等,此外对“职员名单”也作相同的处理,在“职员”的子元素前加上“职员”两字,例如“姓名”、“电话”变为“职员姓名”、“职员电话”等。这诚然是一个可行的办法,但是这么做必须要改动DTD里面的定义,但是由于不是所有的DTD都是自己设计的,有些是无法改变的,即使改了,仍然无法保证以后不会再遇到类似的同名元素。因此对于XML来说,这不是一个可行的方法。
名域概念正是在这种背景下提出来的。它的概念非常直接,如果每套XML语汇,都有各自一个独一无二的标志来代表,并且在使用的时候,它这个标志和语汇中的元素、属性名连在一起,那么就不会和其他语汇中的元素造成混乱了。因为每个语汇中的元素、属性,都已经事先被该语汇的独特标识码给限定了。其实这个解决办法和前面提出的方法有共同之处,那就是在含糊的元素或属性前加一个限定,使这个语汇中的元素或属性名独一无二,避免和其他语汇相冲突。只不过名域的做法使让编写XML文件的人替文件中所用到的语汇,自行指定标识码。
一个独特的标识码,代表一套语汇,各语汇中的名称,因而能各得其所,有它们自己的活动领域,这就是名域这个名称的由来。
8.1.2? 名域的声明
XML采用了一个非常聪明、简单的方法来指定名域,那就是利用网络域名地址来标识名域。这是由于域名地址是独特的,而且由于各机关对于放在自己网域下的域名有完全的控制权。
在一般情况下,我们所说的“网址”是指URL,但是在名域中规定必须使用URI。URI是Uniform Resouce Identifier(同一资源标示码)的缩写,它是一个Internet标准,记载于RFC 2396。URI与URL,URN的区别主要是:URI泛指所有以字符串进行标示的网络资源,范围涵盖了URL和URN;而URL是指标有通信协议(如:HTTP、FTP)的字符串;URN(Uniform Resouce Name)主要是指用来标示持久、而且有专责机构负责的资源。
下面来看XML到底是如何声明名域的。现看下面的例子,这个例子是用于解决本节开始提出的名称冲突的问题。代码如下所示:
<?xml version="1.0" encoding="gb2312" ?>
<book:图书信息 xmlns:book="http://www.bar.com/book.dtd"
xmlns:职员="http://www.bar.com/employe.dtd">
<book:书>
<book:书名>...??? </book:书名>
<book:作者>
<book:姓名>...??? </book:姓名>
<book:电话>
<book:公司电话>...</book:公司电话>
<book:住宅电话>...</book:住宅电话>
<book:手机>...</book:手机>
</book:电话>
<book:EMail>...</book:EMail>
<book:Fax>...</book:Fax>
</book:作者>
<book:定价>...? ??</book:定价>
<book:摘要>...??? </book:摘要>
<book:责任编辑>
<职员:姓名>...??? </职员:姓名>
<职员:部门>...??? </职员:部门>?
<职员:职位>...??? </职员:职位>
<职员:电话>
<职员:公司电话>...</职员:公司电话>
<职员:住宅电话>...</职员:住宅电话>
<职员:手机>...</职员:手机>
</职员:电话>
<职员:EMail>...</职员:EMail>
<职员:Fax>...</职员:Fax>
</book:责任编辑>
</book:书>

<book:书> <!-- 书2-->
<book:书名>...??? </book:书名>
<book:作者>
<book:姓名>...??? </book:姓名>
<book:电话>
<book:公司电话>...</book:公司电话>
<book:住宅电话>...</book:住宅电话>
<book:手机>...</book:手机>
</book:电话>
<book:EMail>...</book:EMail>
<book:Fax>...</book:Fax>
</book:作者>
<book:定价>...??? </book:定价>
<book:摘要>...??? </book:摘要>
<book:责任编辑>
<职员:姓名>...??? </职员:姓名>
<职员:部门>...??? </职员:部门>?
<职员:职位>...??? </职员:职位>
<职员:电话>
<职员:公司电话>...</职员:公司电话>
<职员:住宅电话>...</职员:住宅电话>
<职员:手机>...</职员:手机>
</职员:电话>
<职员:EMail>...</职员:EMail>
<职员:Fax>...</职员:Fax>
</book:责任编辑>
</book:书>

</book:图书信息>
从上面的例子,可以看出名域是通过“独特标识码+名称”的方式,让每个XML语汇中的元素、属性名都能有它们自己的领域,而不会和其他语汇中的名称发生冲突。也就是说在名称前面加上独特的标识码,这个名称就变成独一无而的了。
虽然XML选用URI来做独特的标识码,但是一般的URI都很长,如果直接拿来放在元素和属性名称前,不但书写不便,而且阅读也不方便。因此通常使用一个简短的代号来替代URI。这个简短的代号,在名域的标准中称为“前置字串”(Namespace prefix)。它是由编辑XML文档的人自由决定的,例如上例中的book、职员。前置字串只能包含XML标准中允许作元素和属性名的字,这包括了英文字母和所有收录在Unicode中的汉字。但是在XML标准中,把所有以“xml”这三各字母开头的前置字串保留作特殊的用途,所以使用者不能使用这三个字母来起头,不管是“xml”、“XML”、“XMl”等什么样的大小写组合都不允许。
那么应该通过什么样的方式才能将前置字串和它所代表的名域关联起来呢?由上面的例子,可以看出形式是:“xmlns:前置字串=URI”。
使用名域的目的是在一个XML文件中使用多种语汇,要实现这个目的必须先将各个语汇的名域和前置字串定义好,然后根据具体的需要在各个元素或属性名前加上适当的前置字串,并将两者以冒号分隔开。在前面的例子中,“http://www.bar.com/book.dtd”是给“图书信息”这个XML语汇指定的名域标识码,“http://www.bar.com/employe.dtd”是“职员名单”的标识码。为了书写方便和阅读的方便,用“book”这个前置字串代替“图书信息”的标识网址(xmlns:book="http://www.bar.com/book.dtd"),用“职员”来代替“职员名单的标识网址(xmlns:职员="http://www.bar.com/employe.dtd")。一个元素里面可以放置多个xmlns的属性声明,一旦声明完成以后,只要将各个元素名都加上这个前置字串,就不会产生冲突了。

8.1.3? 名域的范畴

范畴(Scope)是一个非常重要的概念,对于程序设计来说特别重要,如果将前面一个实例的代码该成如下:
<?xml version="1.0" encoding="gb2312" ?>
<book:图书信息>
<book:书 >
<book:书名>...??? </book:书名>
<book:作者>
<book:姓名>...??? </book:姓名>
<book:电话>
<book:公司电话>...</book:公司电话>
<book:住宅电话>...</book:住宅电话>
<book:手机>...</book:手机>
</book:电话>
<book:EMail>...</book:EMail>
<book:Fax>...</book:Fax>
</book:作者>
<book:定价>...??? </book:定价>
<book:摘要>...??? </book:摘要>
<book:责任编辑 xmlns:book="http://www.bar.com/book.dtd"
xmlns:职员="http://www.bar.com/employe.dtd">
<职员:姓名>...? ??</职员:姓名>
<职员:部门>...??? </职员:部门>?
<职员:职位>...??? </职员:职位>
<职员:电话>
<职员:公司电话>...</职员:公司电话>
<职员:住宅电话>...</职员:住宅电话>
<职员:手机>...</职员:手机>
</职员:电话>
<职员:EMail>...</职员:EMail>
<职员:Fax>...</职员:Fax>
</book:责任编辑>
</book:书>


[下一页]