理解XML Schema: XML Schema初步(II)
转载自:http://www.ibm.com/developerworks/cn/xml/x-schema/part2/index.html
?
在item元素中,它被定义为一个复合匿名类型,该复杂类型是由productName、quantity、USPrice、comment、shipDate元素和一个称为partNum的属性组成的。在quantity元素中,他有一个简单匿名类型,从integer类型中引出,他的值范围为1到99。
现在我们如何为这个元素定义添加一个属性呢? 我们以前说过,简单类型不能有属性,而decimal是简单类型。因此,我们必须定义一个复合类型来携带属性声明。然而,同时我们也想具有简单类型decimal的元素内容。所以我们最初的问题转化为:我们如何定义一个基于简单类型decimal的复合类型? 答案是,从简单类型decimal中引出一个新的复合类型(参见下图)。
我们使用complexType 元素来开始定义一个新的(匿名的)类型。为了表示新类型的内容模型只包括字符数据而没有元素,我们使用simpleContent元素来实施定义。最后,我们通过扩展简单的decimal类型引出新的类型。扩展包括使用标准属性声明来添加一个currency属性。
出现在客户信笺中的元素是使用我们先前看到的element 和complexType元素构造来声明的,他们的类型也是用这种方法定义的(参见上图)。
注意到在XML Schema中,混合模型与XML 1.0的混合模型有着根本的区别。在XML Schema下面的混合模型,子元素在一个实例中出现的顺序和数量必须与子元素在模型中说明的顺序和数量一致。与之相对,在XML1.0混合模型下,出现在实例中的子元素的顺序和数量不能被限制。总而言之,XML Schema提供了充分的混合模型的校验而XML1.0只提供了部分的模式校验。
这样的元素根本没有内容,他的内容模型是空。为了定义内容是空的类型,我们可以通过这样的方式:首先我们定义一个元素,它只能包含子元素而不能包含元素内容,然后我们又不定义任何子元素,依靠这样的方式,我们就能够定义出内容模型为空的元素。
在上图这个例子中,我们定义了一个匿名类型,它包含的是complexContent,即只包含子元素。ComplexContent元素表明我们想要限制或者扩展一个复合类型的内容模型,并且类型为anyType的restriction元素声明了两个属性,而没有引入任何元素内容。使用这种方法声明的InternationalPrice元素就得以像上面例子里所显示的那样合理地出现在实例文档中。
前述上图中的关于空内容元素的语法相对有点冗长。我们可以通过更简洁的声明方式来声明internationalPrice元素(参见下图)。
因为一个不带有simpleContent 或者complexContent的复合类型定义,会被解释为带有类型定义为anyType的complexContent,这是一个默认的速记方法,所以这个简洁的语法可以在模式处理器中工作。
用这个方式声明的元素是不受约束的。所以元素的值可以为423.46,也可以为任何其他的字符序列,或者甚至是字符和元素的混合。实际上,anyType是默认类型,所以上面的可以被重写为:?
<xsd:element name="anything"/>
如果需要表示不受约束的元素内容,举例来说在元素包含散文,其中可能需要嵌入标签来支持国际化的表示,那么默认的声明(无约束)或者有些微约束的形式会很合适。
annotation元素也会出现在其他模式构造的开头,如那些通过元素schema、simpleType和attribute来展示的模式构造。
对于choice组元素而言,在实例中仅仅允许出现这个组中的一个子内容。对于上图中的例子而言,第一个子内容是一个内部group元素,引用以shipAndBill命名的元素组,这个元素组由元素序列shipTo、billTo组成。第二个子内容为singleUSAddress。因此,在一个实例文档中,purchaseOrder元素必须,要么包含一个billTo元素和一个shipTo元素,要么包含一个singleUSAddress元素。choice组后面跟着的是comment和items元素声明。元素和组的声明都是sequence 组的子内容。这样定义的效果是comment和items元素必须按顺序跟在地址元素后面。
现在有第三种选择在组中包含元素:通过使用all元素定义的元素组,在组中所有的元素都可以出现一次或者更本不出现,而且他们能够以任何顺序出现。all组被限制放在任何内容模型的顶部,此外,all元素组的子内容必须都为独立元素(不能有组元素),在all元素定义的内容模型中的元素都不可以出现超过一次,也就是说minOccurs 和maxOccurs允许的值为"0"和"1"。举例来说,为了允许purchaseOrder的子元素以任意的顺序出现,我们能够用下面的形式重新定义purchaseOrderType(参见下图):
通过使用这个定义,一个comment元素可以选择出现在purchaseOrder中的不同位置,可以在shipTo、billTo和items元素之前或者之后出现,但他只能够出现一次。而且all组的约束不允许我们在组外面声明一个元素,因为这样可以允许它出现超过一次。XML Schema限制所有的all组必须作为内容顶部的唯一子元素出现,换句话说,下面的形式是不合法的(参见下图):
最后,在内容模型中被命名或未被命名的元素组(分别由group、choice、sequence、all所表现)可以带有minOccurs 和maxOccurs属性。通过使用这些特性,XML Schema可以完全表现DTD所能表现的功能。而且,all组也提供了额外的表达能力。
或者,我们可以建立一个被命名的属性组来包含所有item元素所期望的属性,并且在item元素声明中通过名字来引用这个属性组(参见下图):
通过这种方法来使用属性组,可以提高模式文档的可读性,同时也便于更新模式文档。这是因为一个属性组能够在一个地方定义和编辑,同时能够在多个定义和声明中被引用。注意到一个属性组可以包含其他属性组,同时还要注意到属性组的声明和引用必须在复合类型定义的最后。
为了在实例文档中明确的表示shipDate有一个空值,我们可以设置nil属性为真: <shipDate xsi:nil="true"></shipDate>
nil属性是作为XML Schema命名空间的一部分来定义的,即"http://www.w3.org/2001/XMLSchema-instance",并且在实例文档中必须带有与命名空间相对应的前缀(一般定义为xsi:)出现。需要注意的是,空值机制仅仅适用于元素值,而不适用于属性值,一个元素有xsi:nil="true"可以没有任何元素内容但仍旧可以带有其他属性。