理解XML Schema: XML Schema进阶(I)
转载自:http://www.ibm.com/developerworks/cn/xml/x-schema/part3/index.html
?
模式文档可以被看做一个类型定义和元素声明的集合(词汇表),他们的名字被归属于一个指定的命名空间,这个命名空间称为目标命名空间。目标命名空间使我们能够从不同的词汇表中区分定义以及声明。举例来说,目标命名空间使我们能够区分在XML Schema 语言词汇表中的元素声明和在一个其他是么的假定的化学语言词汇表中的元素声明。前者使目标命名空间"http://www.w3.org/2001/XMLSchema"的一部分,而后者则是另外一个命名空间。
当我们想去检查一个实例文档是否与一个或者多个模式文档相符合(通过一个称为模式校验的处理),我们需要确定在模式定义中声明和定义的哪些元素和属性应该被用来检查在实例文档中的元素和属性。在这个处理流程中,目标命名空间扮演了一个非常重要的角色。
模式文档的作者也有几种可选的方式来影响元素和属性的标识符如何在实例文档中表现。更特别的,通过使用明确的或者默认的命名空间前缀,作者能够决定在实例文档中出现的局部的声明元素和属性是否必须通过一个命名空间的约束验证。模式文档的作者就关于局部元素和属性的约束的选择与模式文档的结构以及针对实例文档的考虑有着很多的牵连,在后面的小节中我们就其中的几个重要方面进行阐述。
为了查看这个模式文档的目标命名空间是如何被填充的,我们应当依次检查每一个类型的定义和元素的声明。在schema元素结束之前,我们首先定义了一个类型USAddress,它由元素name、street等等组成。这种类型定义的一个结果是USAddress类型必须包含在模式文档的目标命名空间中。然后,我们定义类型PurchaseOrderType,这个类型由元素shipTo、billTo、comment等等组成。PurchaseorderType也包括在模式文档的目标命名空间中。注意到在这三个元素声明中的类型引用是有前缀的,po:USAddress。po:USAddress和po:comment,同时这个命名空间前缀是和命名空间”http://www.example.com/PO1”相联系的。这个命名空间与这个模式文档的目标命名空间是同一个命名空间。所以这个模式文档的处理者将知道在本模式文档中查找类型USAddress的定义以及元素comment的声明。当然,我们也可以通过使用不同的目标命名空间引用其他模式中的类型。因此,这样就可以在模式文档中重用外部的定义和声明。
在模式文档po1.xsd的开始,我们声明了元素purchaseOrder和comment,他们包含在模式文档的目标命名空间中。purchaseOrder元素类型是有命名空间前缀的。同样USAddress也是有命名空间前缀的。与之相反,comment元素类型、string没有命名空间前缀。po1.xsd模式文档包括一个默认的命名空间声明,因此没有命名空间前缀的类型诸如string,元素诸如element.和complexType都是与默认的命名空间”http://www.w3.org/2001/XMLSchema”相关联的。实际上,这是XML Schema自身的目标命名空间,所以一个po1.xsd的处理者知道在XML Schema中查找类型string的定义和元素element.的声明。现在,让我们来审阅一下这个模式文档的目标命名空间是如何影响一个实例文档的一致性的:
在这个与上述模式文档相一致的实例文档中,我们明确的限定了所有的元素:
注意到在上面这个模式文档中,对于publicKey属性,我们使用了form属性,来代替attributeFormDefault的值。同样,form属性也能够被用在元素声明中。下面是一个与前述模式文档相一直的实例文档的例子:
这个"全局"版的po1.xsd将正确地校验我们的实例文档po2.xml,如同我们在前面所描述过地,这个文档也能够由前面那个"qualified"版本po1.xsd进行校验。换句话说,两个schema方法都能够正确验证相同的、带有默认命名空间的实例文档。从一方面来看,这两个模式文档的设计方法是相近的,当然从另一方面来看,这两个模式文档的撰写方式又有着非常大的差异。特别是,当所有的元素都被声明为全局元素时,就不能利用到局部命名的优点。举例来说,对于全局元素而言,你只能够声明一个全局元素"title"。然而对于局部元素而言,你能够声明局部元素"title",它有一个string类型,而且它是"book"的子元素。在同样的模式文档中(具有相同的目标命名空间),你能够声明第二个也叫"title"的元素,它可带有枚表值"Mr Mrs Ms"。
未声明的目标命名空间
在前面的XML Schema初步这篇文章中,我们使用没有声明目标命名空间的模式文档和没有声明命名空间的实例文档来阐述了XML Schema的基本知识。那么此时,自然而然地会产生一个问题,在这些模式文档和实例文档的例子里面目标命名空间是什么并且他们引用哪里?
在购买订单模式文档po.xsd中,我们没有为模式文档声明一个目标命名空间,我们也没有声明与模式文档目标命名空间相关联的命名空间前缀(如上面的"po:"),一般来说,如果有命名空间前缀的话,我们就可以在这个命名空间中查阅到模式文档中的类型和元素的定义和声明。如果在模式文档不声明目标命名空间,那么其结果就是在这个模式文档中的定义和声明,如USAddress和purchaseOrder都是没有命名空间修饰限定的引用。换句话说,即没有明确的命名空间前缀应用于引用,同时也没有任何默认的命名空间隐含地应用于引用。对于当前这个例子来说,purchaseOrder元素引用了类型PurchaseOrderType定义来实施声明。与之相对,在po.xsd中使用的所有XML Schema元素和类型都是通过与XML Schema命名空间相关联的命名空间前缀"xsd:"所明确进行限定的。
在模式文档被设计为没有目标命名空间的场合下,我们强烈推荐所有的XML Schema元素和类型通过一个和XML Schema命名空间相关联的命名空间前缀如"xsd:"来明确实施限定(如在po.xsd中)。我们这样推荐的基本原理是因为如果XML Schema元素和类型默认地与XML Schema命名空间相联系,比如不使用命名空间前缀,那么XML Schema类型的引用也许不能和用户自定义类型的引用相区别。
使用一个不带有目标命名空间的模式文档中的元素声明可以去验证在实例文档中没有命名空间前缀限定的元素。也就是说,他们可用于验证未被提供命名空间限定的元素,这些元素即没有明确的命名空间前缀,也没有默认的命名空间前缀。所以,为了验证一个传统的更本未使用命名空间的XML 1.0文档,你必须提供一个没有目标命名空间的模式文档。当然,有很多没有使用命名空间的XML 1.0文档,所以将会有很多没有填写目标命名空间的模式文档。