您的位置:首页 > 其它

使用 XML Schema 定义元素的基本知识

2005-09-25 01:11 656 查看
学习使用 XML Schema 代替 DTD 定义 XML 文档结构
级别: 中级
Ashvin Radiya, 总裁兼首席技术官, AvantSoft, Inc.
Vibha Dixit, 首席执行官, AvantSoft, Inc.

2003 年 12 月

的 XML Schema 系统即将成为 W3C 推荐标准,目的是为了克服 DTD 的局限性(请参阅侧栏, DTD 的局限性 ),为 XML
文档提供丰富的语法结构。本文展示了模式的灵活性,说明如何使用 XML Schema 系统来定义最基本的 XML 文档构造块——元素。


XML Schema 比 DTD 更强大。为了说明 XML Schema 机制的强大功能,下面三个程序清单简要比较了表示元素的不同方式。

清单 1给出了一个 XML 文档片段,

清单 2用 DTD 语法声明了这两个元素,

清单 3则是相应的 XML Schema 语法形式。要注意,

清单 3中所用的是相同的 XML 语法。通过模式,验证解析器可以检查元素

InvoiceNo
是否是正整数,元素

ProductID
的首字符是否为 A 到 Z 之间的字母,后面为六个阿拉伯数字。相反,引用 DTD 的验证解析器只能检查这些元素是否用字符串表示。




清单 1:XML 文档片段


[code]

<InvoiceNo>123456789</InvoiceNo>
<ProductID>J123456</ProductID>
清单 2:描述清单 1 中元素的 DTD 片段


[code]
<!ELEMENT InvoiceNo (#PCDATA)>
<!ELEMENT ProductID (#PCDATA)>
清单 3:描述清单 1 中元素的 XML Schema


[code]
<element name='InvoiceNo' type='positive-integer'/>
<element name='ProductID' type='ProductCode'/>
<simpleType name='ProductCode' base='string'>
<pattern value='[A-Z]{1}d{6}'/>
</simpleType>
在 XML Schema 中使用名称空间

在这个协作的世界中,一个人可能处理来自多个其他团体的文档,而不同的团体可能希望以不同的方式表示他们的数据元素。此外,他们还可能在一个文档中引用不同团体创建的同名元素。如何区分相同名字的不同定义呢?XML
Schema 使用名称空间区分这些定义。





DTD 的局限性

尽管作为描述结构化信息的一种机制,DTD 成功地为 SGML 和 HTML 开发人员服务了 20 年,但与 XML Schema 相比,它存在着严重的局限性。





DTD 要求元素由以下三种成分组成:


文本字符串
文本字符串与其他子元素的混合
一组子元素



DTD 不使用 XML 语法,对类型和名称空间仅提供有限的支持。


一个给定的 XML Schema 定义了一组新名字,如元素名、类型名、属性名、属性组名,这些名字的定义和声明都写在模式中。

清单 3定义的名字包括

InvoiceNo


ProductID


ProductCode





我们说模式中定义的名字属于它的

目标名称空间[/i]。名称空间本身有一个固定但没有限制的名字,必须符合 URL 语法。比如,对于

清单 3中模式片段,您可以把名称空间的名字设为:

http://www.SampleStore.com/Account





名称空间的名字语法容易让人混淆,尽管以

http://
开始,那个 URL 并不指向一个包含模式定义的文件。事实上,这个 URL

http://www.SampleStore.com/Account
根本没有指向任何文件,只是一个分配的名字。




模式中的定义和声明可能引用属于其他名称空间的名字。在本文中,我们称这些名称空间为

源名称空间[/i]。每个模式都有一个目标名称空间,但可能有多个源名称空间。名称空间的名字可能相当长,但在 XML 文档中通过

xmlns
声明可使用简写形式。为了说明这些概念,我们可以向前述

清单 4中的示例模式中添加更多的内容。




清单 4:目标名称空间和源名称空间


[code]
<!--XML Schema fragment in file schema1.xsd-->
[code]
<xsd:schema targetNamespace='http://www.SampleStore.com/Account'
xmlns:xsd='http://www.w3.org/1999/XMLSchema'
xmlns:ACC= 'http://www.SampleStore.com/Account'>
<xsd:element name='InvoiceNo' type='xsd:positive-integer'/>
<xsd:element name='ProductID' type='ACC:ProductCode'/>
<xsd:simpleType name='ProductCode' base='xsd:string'>
<xsd:pattern value='[A-Z]{1}d{6}'/>
</xsd:simpleType>


清单 4的 XML Schema 中,

targetNamespace
的名字是

http://www.SampleStore.com/Account
,其中包含的名字有

InvoiceNo


ProductID


ProductCode


schema


element


simpleType


pattern


string


positive-integer
这些名字属于源名称空间

http://www.w3.org/1999/XMLSchema
,通过

xmlns
声明缩写为

xsd
。别名

xsd
没有任何特殊的地方,我们可以选择任何其他的名字。在本文后面的部分为了方便和简化起见,我们使用

xsd
代表名称空间

http://www.w3.org/1999/XMLSchema
,在一些代码片段中省略了限定符

xsd
。在这个例子中,

targetNamespace
偶尔也作为一个源名称空间,因为要使用名字

ProductCode
定义其他的名字。







图 1:清单 4 中的名称空间











清单 4中的模式片段不需要指定源模式文件的位置。对于整个“模式的模式”,

http://www.w3.org/1999/XMLSchema
,不需要指定位置,因为它的位置是人所共知的。对于源名称空间

http://www.SampleStore.com/Account
,也不需要指定位置,因为它恰好是该文件中定义的目标名称空间。为了更好地理解如何指定模式的位置和使用默认名称空间,看一看

清单 5中扩展的例子。




清单 5:多个源名称空间,导入一个名称空间


[code]

<!--XML Schema fragment in file schema1.xsd-->
<schema targetNamespace='http://www.SampleStore.com/Account'
xmlns='http://www.w3.org/1999/XMLSchema'
xmlns:ACC= 'http://www.SampleStore.com/Account'
xmlns:PART= 'http://www.PartnerStore.com/PartsCatalog'>
<import namespace='http://www.PartnerStore.com/PartsCatalog'
schemaLocation='http://www.ProductStandards.org/repository/alpha.xsd'/>
<element name='InvoiceNo' type='positive-integer'/>
<element name='ProductID' type='ACC:ProductCode'/>
<simpleType name='ProductCode' base='string'>
<pattern value='[A-Z]{1}d{6}'/>
</simpleType>
<element name='stickyGlue' type='PART:SuperGlueType'/>
清单 5中多了一个名称空间引用:

http://www.PartnerStore.com/PartsCatalog
。这个名称空间不同于

targetNamespace
和标准名称空间。因此必须使用

import
声明元素引入,该元素的

schemaLocation
属性指明包含模式的文件位置。默认的名称空间是

http://www.w3.org/1999/XMLSchema
,它的

xmlns
声明没有名字。每个非限定的名字如

schema


element
,都属于默认名称空间

http://www.w3.org/1999/XMLSchema
。如果模式从一个名称空间中引用了多个名字,将其指定为默认名字空间更方便。




一个 XML 实例文档可能引用多个名称空间的元素名,这些名称空间定义在不同模式中。为了引用和简化名称空间的名字,同样要使用

xmlns
声明。我们使用 XML Schema 实例名称空间的

schemaLocation
属性指定文件的位置。要注意,该属性不同于上一个例子中

xsd
名称空间的同名属性

schemaLocation





清单 6:使用来自多个模式的多个名称空间的名字


[code]

<?xml version="1.0"?>
<ACC:rootElement xmlns:ACC='http://www.SampleStore.com/Account'
xmlns:PART='http://www.PartnerStore.com/PartsCatalog'
xmlns:xsi='http://www.w3.org/1999/XMLSchema-instance'
xsi:schemaLocation='http://www.PartnerStore.com/PartsCatalog http://www.ProductStandards.org/repository/alpha.xsd http://www.SampleStore.com/Account http://www.SampleStore.com/repository/schema1.xsd'> <ACC:InvoiceNo>123456789</ACC:InvoiceNo>
图 2:清单 5 和清单 6 的名称空间









定义元素

定义元素就是定义元素的名字和内容模型。在 XML Schema 中,元素的内容模型由其类型定义,因此 XML 文档中实例元素的值必须符合模式中定义的类型。





简单类型
XML Schema 规范定义了一些值的简单类型,如

表 2:“预定义的值简单类型”所示。







类型包括简单类型和复杂类型。简单类型的值不能包含元素或属性。复杂类型可以产生在其他元素中嵌套元素的效果,或者为元素增加属性。(到目前为止本文中的例子都是用户定义的简单类型,比如

ProductCode
)。XML Schema 规范也包括预定义的简单类型(请参阅侧栏

简单类型)。

派生的简单类型[/i]约束了基类型的值。比如,派生简单类型

ProductCode
的值是基类型

string
值的子集。




简单的、非嵌套的元素是简单类型

不含属性或其他元素的元素可以定义为简单类型,无论是预定义的简单类型还是用户定义的简单类型,如

string


integer


decimal


time


ProductCode
等等。







清单 7:一些元素的简单类型


[code]

<element name='age' type='integer'/>
<element name='price' type='decimal'/>
带有属性的元素必须是复杂类型

现在,试着向

清单 7中的简单元素

price
增加属性

currency
。您不能这样做,因为简单类型的元素不能有属性。如果希望增加属性,您必须把

price
元素定义成复杂类型。在

清单 8的例子中,我们定义了一个

匿名类型[/i],没有明确地命名这个复杂类型。换句话说,没有定义复杂类型

complexType


name
属性。







清单 8:一个复杂元素类型


[code]

<element name='price'>
<complexType base='decimal' derivedBy='extension'>
<attribute name='currency' type='string'/>
</complexType>
</element>
<!-- In XML instance document, we can write: <price currency='US'>45.50</price> -->
嵌入其他元素的元素必须是复杂类型

在 XML 文档中,一个元素可能嵌入其他的元素。这种要求可以在 DTD 中直接表示。但 XML Schema 定义一个元素,这个元素有一个类型,而这个类型可以包含其他元素和属性的声明。

表 1给出了一个简单的例子。










表 1:DTD 和 XML Schema 中复杂数据类型的比较


XML 文档


[code]

<Book>
<Title>Cool XML<Title>
<Author>Cool Guy</Author>
</Book>
DTD


[code]

<Book>
<Title>Cool XML<Title>
<Author>Cool Guy</Author>
</Book>
XML Schema


[code]

<Book>
<Title>Cool XML<Title>
<Author>Cool Guy</Author>
</Book>
[code]
<!ELEMENT Book (Title, Author)>
<!ELEMENT Title (#PCDATA)>
<!ELEMENT Author (#PCDATA)>
[code]

<element name='Book' type='BookType'/>
<complexType name='BookType'>
<element name='Title' type='string'/>
<element name='Author' type='string'/>
</complexType>
尽管

表 1中的 XML 代码同时满足 DTD 与 XML Schema 片段,但两者之间有一个很大的区别。在 DTD 中所有的元素都是全局性的,而表中的 XML Schema 允许把

Title


Author
定义成局部的——只出现在元素

Book
中。为了在 XML Schema 中实现与 DTD 声明完全相同的效果,元素

Title


Author
必须是全局范围的,如

清单 9中所示。元素

element


ref
属性使您能够引用前面声明的元素。




清单 9:用全局简单类型定义的复杂类型


[code]

<element name='Title' type='string'/>
<element name='Author' type='string'/>
<element name='Book' type='BookType'/>
<complexType name='BookType'>
<element ref='Title'/>
<element ref='Author'/>
</complexType>


表 1

清单 9所示的例子中,

BookType
是全局性的,可用于声明其他元素。相反,

清单 10将该类型局部地定义到元素

Book
中,而且定义成匿名元素。要注意,

表 1中的 XML 文档片段与表 1、

清单 9

清单 10中三个模式片段都匹配。




清单 10:隐藏 BookType 作为本地类型


[code]

<element name='Title' type='string'/>
<element name='Author' type='string'/>
<element name='Book'>
<complexType>
<element ref='Title'/>
<element ref='Author'/>
</complexType>
</element>
表示元素的复杂约束

对于表示元素内容模型的约束,XML Schema 比 DTD 提供了更大的灵活性。在最简单的层次上,像在 DTD
中那样,您可以把属性和元素声明关联起来,指明能够出现的给定元素集合序列:只能出现 1 次(1)、出现 0 次或多次(*)或者出现 1
次或多次(+)。您还可以表示 XML Schema 中的其他约束,比方说使用
element
元素的

minOccurs


maxOccurs
属性,以及

choice


group


all
元素。







清单 11:表示元素类型的约束


[code]

<element name='Title' type='string'/>
<element name='Author' type='string'/>
<element name='Book'>
<complexType>
<element ref='Title' minOccurs='0'/>
<element ref='Author' maxOccurs='2'/>
</complexType>
</element>


清单 11中,

Book


Title
的出现是可选的(类似 DTD 的 '?')。但是,

清单 11也说明

Book
元素中至少要有一个但不能超过两个作者。

element


minOccurs


maxOccurs
属性的默认值是 1。元素

choice
只允许它的一个子女出现在实例中。另外一个元素

all
,表示这样的约束:组中的所有子元素可以同时出现一次,或者都不出现,它们可以按任意的顺序出现。

清单 12表示

Title


Author
两者必须同时出现(顺序任意)在

Book
中,或者都不出现。这种约束很难在 DTD 中表示。




清单 12:指出必须为元素定义所有的类型


[code]

<xsd:element name='Title' type='string'/>
<xsd:element name='Author' type='string'/>
<xsd:element name='Book'>
<xsd:complexType>
<xsd:all>
<xsd:element ref='Tile'/>
<xsd:element ref='Author'/>
</xsd:all>
</xsd:complexType>
</xsd:element>
更上层楼

我们已经讨论了在 XML Schema 中定义元素所需的最基本的概念,通过一些简单的例子使您领略到它的强大功能。还有一些更强大的机制:





XML Schema 对类型继承提供了广泛的支持,允许重用以前定义的结构。使用所谓的

facets,您可以派生新的类型,表示其他某个类型值的更小子集,比如通过枚举、范围或模式匹配来定义子集。在本文的例子中,

ProductCode
类型就是使用模式面(

pattern
facet)定义的。子类型也可以向基类型增加更多的元素和属性声明。


有几种机制控制能否定义子类型,或者能否在具体的文档中替换为子类型。比如,有可能表示

InvoiceType
( Invoice 编号的类型)不允许子类型化,任何人都不能定义新版本的

InvoiceType
。通过规定在特定的上下文中不能用

ProductCode
类型的子类型替换,也能表达这种约束。


除了子类型外,还可以定义等价的类型,这样,一个类型的值可以用另一个类型代替。
通过声明抽象的元素或者类型,XML Schema 提供了一种强制替换机制。
为了方便起见,可以定义并命名属性组和元素组,从而能够在后面引用这些组达到重用的目的。
XML Schema 提供了三个元素——

appInfo


documentation


annotation
——为模式作注解,以方便读者(

documentation
)和应用程序(

appInfo
)。


基于子元素的某些属性可以表示惟一性约束。


可以通过 W3C 站点(请参阅

参考资料)的文档进一步研究 XML Schema,或者访问 dW XML 专区了解更多的内容。目前,XML Schema 规范已经被批准,并成为候选推荐标准(Candidate Recommendation),毫无疑问您将越来越多地用到它。




参考资料



您可以参阅本文在 developerWorks 全球站点上的

英文原文.



通过填写

Web 表单,可以免费获得爱丁堡大学/W3C 的 XSV(alpha 版),这是一个 XML Schema Validator。







免费下载 Apache 项目的

XML Schema validator







Extensibility 的商业软件

XML Schema aware editor/validator的评估版。









http://www.ibm.com/alphaworks下载免费工具。







最新 XML Schema 规范的背景资料:



XML Schema Part 0: Primer

[/i]。







目前的 W3C XML Schema 规范文档由两部组成:



XML Schema Part 1: Structures

[/i]和



XML Schema Part 2: Datatypes

[/i]。








作者简介
Ashvin Radiya 是

AvantSoft, Inc.
创始人和总裁。作为首席技术官,他领导开发并推出了最新 Java 编程及相关技术的 AvantSoft 培训课程。他还建立和管理与财富 100
强的战略伙伴关系。Ashvin 有丰富的企业、学院和专业人员经历。他曾在奥斯汀的 IBM 工作,研究基于 CORBA
的高级分布式面向对象产品。在移动商务、XML、Java、Enterprise JavaBeans 组件、InfoBus、安全、CORBA
和分布式面向对象编程方面,他拥有丰富的知识和经验。Ashvin 从锡拉丘兹大学获得了计算机科学博士学位。可以通过 ashvin@avantsoft.com与 Ashvin Radiya 联系。










Vibha Dixit 在

AvantSoftInc.
的 Business Development Manager and Technologist
中担任重要职务。她负责业务规划、管理战略伙伴、开发新的客户、营销和市场。她还积极参与 AvantSoft 技术目标的制定,确定移动商务、XML
和 Java 技术领域的发展方向。Vibha 在商业管理方面有独到的经验,在计算机技术方面也有丰富的行业经验。在加入 AvantSoft
之前,她曾在 IBM Santa Teresa
实验室工作,从事分布式交互对象中间件的研究。在俄亥俄超级计算机中心,她参与了一个微型计算机操作系统的设计与开发。Vibha
从俄亥俄州立大学获得了计算机科学博士学位。她还从 Southern Methodist University 修完了 MBA
高级管理人员课程。可以通过 vibha@avantsoft.com与 Vibha Dixit 联系。











内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: