由于 XML 开发人员需要克服 DTD 作为建模语言的限制,所以 W3C XML Schema 变得越来越流行了。XML Schema 的特别流行是由于它提供了更丰富的数据类型。使用 XML Schema,可以很容易地指定一个元素应该包含文本、数字、布尔值还是其他一些数据类型。
不过,XML Schema 提供了比数据类型更多的功能。它具有组织元素声明的选项,可以改进可读性和易维护性。在本技巧中,我将为您展示XML Schema 中的范围选项。
XML Schema 让您可以直接在
xs:schema 元素下面声明元素,或者作为另一个声明的一部分声明元素。直接出现在
xs:schema 元素下面的声明具有
全局范围,而其他声明具有
局部范围。全局声明并不是新东西
-- DTD 中就已经引入它们了 -- 但是局部声明是 XML Schema 所独有的。
元素的全局声明和局部声明最明显的区别是在其他声明中可以引用全局声明,而局部声明只能存在于它们自己的局部范围内。一个实际的副作用是全局声明必须是唯一的:任何两个全局声明都不能有相同的元素名。另一方面,局部声明如果是在不同的上下文中,则不会产生冲突。甚至可以在局部覆盖一个全局声明。
为什么想要覆盖声明呢?在设计大型模式、特别是设计从现有模式中导入声明的新模式时,这是很有用的。在后一种情况下,导入的模式确实可能具有会引起冲突的声明。
例如 ,一个模式可能定义一个
key 元素为用于密钥的 base64 数据,而另一个模式将
key
定义为一个用于储存数据库标识符的整数。在这里,
key 元素有两个不同的定义,如果要创建所导入的前两者的第三个模式就会产生问题。
清单 1中的 模式 全部使用全局声明。
<xs:element name="..."> construct
定义了一个新元素,它类似于 DTD 中的
<!ELEMENT ...> 语句。这些声明可能会通过
<xs:element
ref="..."/> construct 引用其他声明。
清单 1. 全局声明
<?xml version="1.0"?>
<xs:schema targetNamespace="http://ananas.org/2003/tips/local"
xmlns:tp="http://ananas.org/2003/tips/local"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="list">
<xs:complexType>
<xs:sequence>
<xs:element
ref="tp:movie" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="movie">
<xs:complexType>
<xs:sequence>
<xs:element
ref="tp:title"/>
<xs:element
ref="tp:genre" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="title" type="xs:string"/>
<xs:element name="genre" type="xs:string"/>
</xs:schema>
|
另一方面,清单 2尽可能地使用了局部声明。唯一的全局声明是用于文档的根的(文档的根必须是全局声明,因为根没有父元素)。所有其他声明都嵌入到根声明下面。大量的嵌套使这种方法得到了一个别名“俄罗斯娃娃”。
清单 2. 局部声明
<?xml version="1.0"?>
<xs:schema targetNamespace="http://ananas.org/2003/tips/local"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:element name="list">
<xs:complexType>
<xs:sequence>
<xs:element name="movie" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="title" type="xs:string"/>
<xs:element name="genre" maxOccurs="unbounded"
type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
|
注意
elementFormDefault 属性的使用。在默认情况下,XML 文档中具有局部声明的元素是非限定的(它们没有名称空间前缀)。背后的推论是非限定的元素类似于属性,因为属性在默认情况下是非限定的。
清单3展示了非限定的局部元素。在这里,
movie 、
title 和
genre
元素没有名称空间前缀,假定它们与其父元素在同一个名称空间中。对于非限定的局部元素的使用尚无定论。SOAP 成功地使用了一些,但是大多数用户认为它们是让人困惑的。
一句警告:需要将
清单
2中的
elementFormDefault 从
qualified 改为
unqualified
以验证清单 3。
清单 3. 非限定的局部元素
<?xml version="1.0"?>
<tp:list xmlns:tp="http://ananas.org/2003/tips/local">
<movie>
<title>Johnny English
</title>
<genre>comedy
</genre>
</movie>
<movie>
<title>Finding Nemo
</title>
<genre>family
</genre>
</movie>
</tp:list>
显然,如果要在文档中使用非限定的元素,那么必须使用局部元素。
那么,局部声明和全局声明哪一个更好呢? 唉,就像设计策略的常见情况一样,答案不是这么黑白分明的,大多数模式同时使用两者。局部声明之所以有意义是因为它们隔离了模式的一部分。局部名对于其他上下文是不透明的,这使命名冲突的风险降到了最低。
局部声明的另一项好处是它们明确地标识了文档中可能的根。
局部声明的主要缺点是它们不能重复使用。在
清单
2中(使用局部声明),不能在另一个上下文中重复使用
movie 元素。在
清单
1中(使用全局声明)这是很容易的。
结论是,哪一种选择是最好的取决于元素的本性:一个准备在模式中别的地方重复使用的自包含元素最好使用全局声明,而只在给定上下文中起作用的元素应该在局部声明。
假定
movie 是一个自包含的元素,那么清单 4是一种更好的模式,它很好地结合了局部和全局声明。
清单 4. 混合声明
<?xml version="1.0"?>
<xs:schema targetNamespace="http://ananas.org/2003/tips/local"
xmlns:tp="http://ananas.org/2003/tips/local"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:element name="list">
<xs:complexType>
<xs:sequence>
<xs:element
ref="tp:movie" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="movie">
<xs:complexType>
<xs:sequence>
<xs:element name="title" type="xs:string"/>
<xs:element name="genre" type="xs:string"
maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
尽管在本技巧中没有讨论,但是您还可以在全局和本地声明中使用类型定义以改进模式的可读性。
- 您可以参阅本文在 developerWorks 全球站点上的
英文原文.
- 在
W3C 网站上找到所有关于 XML Schema 的内容。
- 阅读 Kevin Williams 的“
Soapbox:为什么在数据方面,XML
Schema 不费吹灰之力击败了 DTD”。它提供了 XML Schema 优缺点的更多内幕(
developerWorks,2001年6月)。
- 参阅 Ashvin Radiya 和 Vibha Dixitt 合著的 “
使用
XML Schema 定义元素的基础知识”(
developerWorks,
August 2000),其中给出了编写 XML schema 的指导。
- 访问
xFront 的最佳实践页面可以得到有关使用全局和局部元素的指导。
- 想要获得有关 XML Schema 的一些方便的可打印参考卡片吗?请访问
Dan
Vint 的 XML 资源 Web 站点。
- 有关这一主题的最佳参考书之一是 Eric Van Der Vlist 编著的
XML
Schema
(O'Reilly & Associates,2002年)。
- 在
developerWorks 的
XML
专区上能找到更多有关 XML 的资源。可以在
技巧汇总页上找到
XML 技巧的最新完整列表。
- IBM 的
DB2 数据库不仅提供了关系数据库存储机制,而且提供了 XML 相关的工具,比如 DB2 XML Extender,该工具提供了
XML 和关系数据库系统之间的桥梁。请访问
DB2
开发者园地了解 DB2 的更多信息。
- 了解如何才能成为一名
IBM
认证的 XML 及相关技术开发人员。

Benoit Marchal 是一位比利时籍的顾问。他是 XML by Example 和其它几本 XML 图书的作者。Benoit 可以为您的 XML 项目提供帮助。可以通过 bmarchal@pineapplesoft.com 或者他的个人网站 marchal.com 与他联系。