以文本方式查看主题

-  中文XML论坛 - 专业的XML技术讨论区  (http://bbs.xml.org.cn/index.asp)
--  『 DTD/XML Schema 』  (http://bbs.xml.org.cn/list.asp?boardid=23)
----  XML Schema指南 [转帖]  (http://bbs.xml.org.cn/dispbbs.asp?boardid=23&rootid=&id=27149)


--  作者:wFirebird
--  发布时间:2/10/2006 4:05:00 PM

--  XML Schema指南 [转帖]
XML-Data Schema指南


状态: 初稿,Andrew,1999年5月25日, 未经核实和测试

Andrew Layman, Microsoft.

本文描述了微软IE5.0的MSXML解析器已经实现的XML-Data 大纲(Schema)语言的特点.XML-Data是描述XML文荡和部件类的词库,即定义 XML元素类型,属性类型以及将其组合成文档(或部分文档).本文是其特点的指南和向导;在 http://msdn.microsoft.com/xml/XMLGuide/schema-overview.asp 有更详细的资料以及明确规范.

大纲的目的是定义一套XML元素、属性和组合规则集.因此,大纲都包括元素和/或属性的定义,通常还有一些限制,即规定在何种情况下、怎样的元素和属性能以何种方式结合使用.

XML-Data本身只是一套元素和属性.我们将进行说明,并演示如何使用它们.首先从一个XML文档开始.

<PurchaseOrder>
<shipTo>

<name>Alice Smith</name>

<street>123 Maple Street</street>

<city>Mill Valley</city>

<state>CA</state>

<zip>90952</zip>

</shipTo>

<orderDate>1999-05-20</orderDate>

<shipDate>1999-05-25</shipDate>

<comments>Get these things to me in a hurry, my lawn is going wild!</comments>

<Items>

<Item>

<productName>Lawnmower, model BUZZ-1</productName>

<quantity>1</quantity>

<price>148.95</price>

</Item>

<Item>

<productName>Baby Monitor, model SNOOZE-2</productName>

<quantity>1</quantity>

<price>39.98</price>

</Item>

</Items>

</PurchaseOrder>

就这个文档,让我们用它来看看XML-Data大纲中的一些特点.

大纲  

一个XML-Data大纲包括一Schema元素,其中是该特定大纲的具体定义.空的大纲是这样的:

<Schema xmlns="urn:schema-microsoft-com:xml-data" xmlns:dt="urn:schema-microsoft-com:datatypes">
</Schema>
大纲的元素名表明这是一个大纲."xmlns"是一个特殊的信息项,称为"名域声明".它标明大纲元素由称作"urn:schemas-microsoft-com:xml-data"的规范明确定义,因而有别于其它任何类似名称的元素 .(并不可能象"schema"这样的特殊名字都需要该分类,但许多普通的名称需要.以后我们将更详尽地讨论名域声明的作用.)

元素

订购单包括几种元素. ElementType是定义它们的机制.例如,我们能够定义一个简单元素类型:"street" :

<ElementType name="street" />
更复杂的元素不仅仅包括文字;它们可能包括特定形式的文本或者包含其它元素的文本.在本例中,我们想规定"shipDate"元素为日期.我们可以这样写

<ElementType name="orderDate" dt:type="date" />
你在http://msdn.microsoft.com/xml/xmlguide/schema-datatypes.asp可以发现一系列的数据类型,如日期、时间、数字、二进制等格式.

我们在元素的定义中引用了其他的适当的元素类型,使"shipTo"元素包括其他元素.例如,

<ElementType name="shipTo" />
<element type="name" />

<element type="street" />

<element type="city" />

<element type="state" />

<element type="zip" />

</ElementType>

这表示每当"shipTo"元素出现,其中必须有五个子元素,依次是name, street, city, state and zip.当然, 我们需要在此之前就定义他们.我们这样做:

<schema xmlns="urn:schema-microsoft-com:xml-data"
xmlns:dt="urn:schema-microsoft-com:datatypes">

<ElementType name="PurchaseOrder">

<element type="shipTo"/>

<element type="orderDate"/>

<element type="shipDate"/>

<element type="comments" />

<element type="Items"/>

</ElementType>

<ElementType name="shipTo" />

<element type="name" />

<element type="street" />

<element type="city" />

<element type="state" />

<element type="zip" />

</ElementType>

<ElementType name="name" />

<ElementType name="street" />

<ElementType name="city" />

<ElementType name="state" />

<ElementType name="zip" dt:type="number" />

<ElementType name="orderDate" dt:type="date" />

<ElementType name="shipDate" dt:type="date" />

<ElementType name="comments" />

<ElementType name="items">

<element type="Item" />

</ElementType>

<ElementType name="Item">

<element type="product" />

<element type="quantity" />

<element type="price" />

</ElementType>

<ElementType name="product" />

<ElementType name="quantity" dt:type="int" />

<ElementType name="price" dt:type="fixed.14.4" />

</schema>

出现最少和最多次数

如果你仔细看上面的大纲,你会看到在items中只允许出现一个Item .我们要允许顾客一次能订多于一项定单,就要这样标明:

<element type="Item" maxOccurs="*" />
maxOccurs属性是一个限制规则,表示可以出现不止一个但必须是有限个 "Item"元素.maxOccurs的有效值为 "1" 和 "*".同样,你可以用minOccurs规定最少次数.例如,你能设置minOccurs为"0"使得一个子元素是可选择的.minOccurs缺省值为1.maxOccurs也为‘1’,除非当content="mixed"时它为"*".最小和最大值都为1.

这些属性不仅可以用于元素(element)还适用于组声明(group declarations).

内容

一个元素可以包括简单的文字,其它简单的元素,文本和元素的混合或空.我们可以通过使用内容(content)属性来规定.假设我们想表明一个元素仅包括文本而不含子元素.我们可以这样说明

<ElementType name="street" content="textOnly" />
相反的极端情况,我们可以限制一个元素仅包含子元素:

<ElementType name="PurchaseOrder" content="eltOnly" />
content值为"empty"表示不允许有文本或子元素;值为"mixed"允许两者混合.

如果ElementType也有规定的数据类型(比如日期,数字等)那么不必明确说明其内容值暗指"textOnly"(纯文本).

顺序

如果子元素必须以一定顺序出现,或集合中仅能出现一个,可以用顺序属性来表示.要明确地表明在大纲中所列的子元素必须按序出现,使order属性为"seq"值

<ElementType name="PurchaseOrder" order="seq">
如果想要假定一个元素可以是从数个子元素中选出,使用的值为"one".例如,如果一个Item元素可以包括product元素或者backOrderedProduct元素,但不是两者同时,必须这样写

<ElementType name="Item" order="one">
<element type="product" />

<element type="backOrderedProduct" />

</ElementType>

order元素的第三个通常值为"many",表示子元素可以以任意顺序任意数量出现.

如果没有声明一个元素的内容模型的顺序,缺省值为:当content属性值为"eltOnly"时order为"seq",当content属性值为"mixed"时为"many".

分组

有时限制不对元素的所有子元素适用,而只是其中的一些.要标明之,我们使用分组(group)元素.例如, 要标明Item元素有一个product或backOrderedProduct元素,以及quantity和price元素,应该这样写

<ElementType name="Item">
<group order="one">

<element type="product" />

<element type="backOrderedProduct" />

</group>

<element type="quantity"/>

<element type="price"/>

</ElementType>

在一个分组元素中,可以置order, minOccurs和maxOccurs 属性来控制所包含元素出现的顺序和数量.

开放和封闭的内容模型

有些情况下,我们想要设置一个元素包含的最低需求.比如,我们假设一个定单(PurchaseOrder)必须至少有下列的直接子元素: shipTo, orderDate, shipDate, comments和Items. 而且,其他的子元素也可以同时出现. (可能有其他人会发明其他的有用项—当讨论名域空间(namespace)的时候我们将涉及.)设置model的属性值为"open" 时允许有其他子元素

<ElementType name="PurchaseOrder" model="open">
<element type="shipTo"/>

<element type="orderDate"/>

<element type="shipDate"/>

<element type="comments" />

<element type="Items"/>

</ElementType>

缺省情况下,在XML-Data中内容模型是开放的.

当然,相反的情况是"封闭的(closed)".不管元素的内容是"eltOnly"或"mixed",我们都能通过模型属性为"closed"来限制其只能包含列出的属性或子元素.

<ElementType name="PurchaseOrder" model="closed">
<element type="shipTo"/>

<element type="orderDate"/>

<element type="shipDate"/>

<element type="comments" />

<element type="Items"/>

</ElementType>

总结

如果我们采用以上的所有观点并把它们添加到初始的大纲中,能得到

<schema xmlns="urn:schema-microsoft-com:xml-data"

xmlns:dt="urn:schema-microsoft-com:datatypes">

<ElementType name="PurchaseOrder" content="eltOnly" >

<element type="shipTo"/>

<element type="orderDate"/>

<element type="shipDate"/>

<element type="comments" />

<element type="Items"/>

</ElementType>

<ElementType name="shipTo" content="eltOnly" />

<element type="name" />

<element type="street" />

<element type="city" />

<element type="state" />

<element type="zip" />

</ElementType>

<ElementType name="name" content="textOnly" />

<ElementType name="street" content="textOnly" />

<ElementType name="city" content="textOnly" />

<ElementType name="state" content="textOnly" />

<ElementType name="zip" dt:type="number" />

<ElementType name="orderDate" dt:type="date" />

<ElementType name="shipDate" dt:type="date" minOccurs="0" />

<ElementType name="comments" minOccurs="0" content="textOnly" />

<ElementType name="items" model="closed">

<element type="Item" maxOccurs="*"/>

</ElementType>

<ElementType name="Item">

<group order="one">

<element type="product" />

<element type="backOrderedProduct" />

</group>

<element type="quantity" />

<element type="price" />

</ElementType>

<ElementType name="product" content="textOnly" />

<ElementType name="backOrderedProduct" content="textOnly" />

<ElementType name="quantity" dt:type="int" />

<ElementType name="price" dt:type="fixed.14.4" />

</schema>

名域

能从标准部分中建立子定义的大纲,例如我们的定货单,将是件很不错的事.譬如,假设有他人已经定义了一个我们需要用于shipTo元素的Address元素.我们将在PurchaseOrder定单中直接使用,不是只照抄Address元素的定义,而是索引原定义使使用和初始一致."名域"将助我们一臂之力.

要吟咏在另一大纲中定义的元素,我们得做两件事.首先,我们使用名域声明来引出另一大纲.该声明包括一个以"xmlns:"开头的属性,其后是可选择的前缀名,最后是另一大纲的统一资源标识符,Universal Resource Identifier (简称URI).

<ElementType name="PurchaseOrder"
xmlns:abcde="http://electrocommerce.org/stuff.xml" >
这里我们介绍了URI为"http://electrocommerce.org/stuff.xml"的大纲并给出前缀"abcde".URI明确表明另一大纲;前缀是我们在本地引用该名域的局部名称.完成之后,我们就可以在那个大纲中引用该元素,就象是我们自己定义的元素.如果另一个大纲有合适的shipTo元素被定义,我们可以这样写来使用

<ElementType name="shipTo"
xmlns:abcde="http://electrocommerce.org/stuff.xml" >
<element type="abcde:Address"/>
</ElementType>
在第一个子元素的类型(type)属性中,我们发现了值"abcde:Address".前缀"abcde"这里与嵌套名域声明相匹配,这样"abcde:Address"意指"由http://electrocommerce.org/stuff.xml中的大纲定义的Address元素".

而且,这对我们的定货单文档产生了影响: 我们也要引用另一大纲名域.

<PurchaseOrder xmlns:abcde="http://electrocommerce.org/stuff.xml">
<shipTo>

<abcde:Address>

<abcde:name>Alice Smith</abcde:name>

<abcde:street>123 Maple Street</abcde:street>

<abcde:city>Mill Valley</abcde:city>

<abcde:state>CA</abcde:state>

<abcde:zip>90952</abcde:zip>
</abcde:Address>

</shipTo>

<orderDate>1999-05-20</orderDate>

<shipDate>1999-05-25</shipDate>

<comments>
Get these things to me in a hurry, my lawn is going wild!
</comments>

<Items>

<Item>

<productName>Lawnmower, model BUZZ-1</productName>

<quantity>1</quantity>

<price>148.95</price>

</Item>

<Item>

<productName>Baby Monitor, model SNOOZE-2</productName>

<quantity>1</quantity>

<price>39.98</price>

</Item>

</Items>

</PurchaseOrder>

在阅读该文档实例的任何人,甚至是并不理解我们 "定货单"的意思的人都能够判断Address 元素是由"http://electrocommerce.org/stuff.xml"处的大纲定义的. 如果我们能从更被广泛理解、标准部分中(如地址Address元素)中构建专业化大纲(如我们的定货单PurchaseOrder),那么那些专业文档部分可以由标准软件模块来处理.例如, 如果我们已经有了用于"由http://electrocommerce.org/stuff.xml定义的Address元素"的XSL样式表,我们在任何这样的地址元素出现处重用该通用地址样式代码.我们几乎是免费得到定货单地址的格式.

我们在大纲和文档实例中使用同样的前缀.但我们不是非这样不可. 因为前缀是名域URI的唯一局部别名, 我们可以在文档实例中使用任何我们喜欢的前缀.我们所有要做的是:在一个文档中,在声明名域和由该名域使用元素时采用相同的前缀.

<PurchaseOrder xmlns:z="http://electrocommerce.org/stuff.xml">
<shipTo>

<z:Address>

<z:name>Alice Smith</z:name>

<z:street>123 Maple Street</z:street>

<z:city>Mill Valley</z:city>

<z:state>CA</z:state>

<z:zip>90952</z:zip>
</z:Address>

</shipTo>

名域的声明限于其出现的元素.它使得名域前缀有效并与URI相结合.因此声明不必在PurchaseOrder元素中出现,因为我们只用另一名域代表Address元素,它可以在那儿直接出现.

<PurchaseOrder>
<shipTo>

<z:Address xmlns:z="http://electrocommerce.org/stuff.xml">

<z:name>Alice Smith</z:name>

<z:street>123 Maple Street</z:street>

<z:city>Mill Valley</z:city>

<z:state>CA</z:state>

<z:zip>90952</z:zip>
</z:Address>

</shipTo>

我们不仅能N给任何特定名域分配特殊的前缀,还能规定名域缺少前缀.这通常使得文档更易读.这儿,我们通过省略名域声明中的前缀来表示没有前缀的子元素都由指定的名域来定义:

<shipTo>
<Address xmlns="http://electrocommerce.org/stuff.xml" >
<name>Alice Smith</name>
<street>123 Maple Street</street>
<city>Mill Valley</city>
<state>CA</state>
<zip>90952</zip>
</Address>
</shipTo>
名域前缀只是文档内的标记.要紧的是相应的URI,因此以上四个Address元素含义完全相同.

尽管我们在名为"http://electrocommerce.org/stuff.xml"的大纲中定义了Address元素,我们还没有 类似地把PurchaseOrder元素和大纲相联系.我们能这样做.假设名叫"http://fabrikam.com/PO.xml"的大纲定义我们的PurchaseOrder元素,我们可以这么写

<PurchaseOrder xmlns="http://fabrikam.com/PO.xml">
<shipTo>

<Address xmlns="http://electrocommerce.org/stuff.xml" >

<name>Alice Smith</name>

<street>123 Maple Street</street>

<city>Mill Valley</city>

<state>CA</state>

<zip>90952</zip>

</Address>

</shipTo>

<orderDate>1999-05-20</orderDate>

<shipDate>1999-05-25</shipDate>

<comments>
Get these things to me in a hurry, my lawn is going wild!
</comments>

<Items>

<Item>

<productName>Lawnmower, model BUZZ-1</productName>

<quantity>1</quantity>

<price>148.95</price>

</Item>

<Item>

<productName>Baby Monitor, model SNOOZE-2</productName>

<quantity>1</quantity>

<price>39.98</price>

</Item>

</Items>

</PurchaseOrder>

以上声明了PurchaseOrder元素以及它包含的所有元素都在"http://fabrikam.com/PO.xml"大纲中定义, 除了Address元素和其子元素在 xmlns="http://electrocommerce.org/stuff.xml"中定义.两种情况中,明确的前缀都省略了.

你可以在一个文档中声明多个名域,也可以用几个前缀来代表相同的名域.下例显示了这点,但只是表明可以这么做,特别指出的是该文档的意义与前例一致.


<PurchaseOrder xmlns:a="http://fabrikam.com/PO.xml"
xmlns:b="http://electrocommerce.org/stuff.xml"
xmlns:c="http://electrocommerce.org/stuff.xml" >

<a:shipTo>

<b:Address >

<c:name>Alice Smith</c:name>

<b:street>123 Maple Street</b:street>

<c:city>Mill Valley</c:city>

<b:state>CA</b:state>

<c:zip>90952</c:zip>

</b:Address>

</a:shipTo>

<a:orderDate>1999-05-20</a:orderDate>

<a:shipDate>1999-05-25</a:shipDate>

<a:comments>
Get these things to me in a hurry, my lawn is going wild!
</a:comments>

<a:Items>

<a:Item>

<a:productName>Lawnmower, model BUZZ-1</a:productName>

<a:quantity>1</a:quantity>

<a:price>148.95</a:price>

</a:Item>

<a:Item>

<a:productName>Baby Monitor, model SNOOZE-2</a:productName>

<a:quantity>1</a:quantity>

<a:price>39.98</a:price>

</a:Item>

</a:Items>

</a:PurchaseOrder>:PurchaseOrder>

如果一个文档的大纲中有开放内容模式(open content model)的元素,那可以包含最初大纲没有提及的元素,只要这些元素由前缀或者由于在缺省大纲的范围之内指派为特定的名域定义.例如,假设有第三个大纲定义了一个称为"trackingInformation"的有用元素.因为我们定义了PurchaseOrder有开放内容模式,我们可以把这个元素直接加入例中:

<PurchaseOrder xmlns="http://fabrikam.com/PO.xml">
<shipTo>

<Address xmlns="http://electrocommerce.org/stuff.xml" >

<name>Alice Smith</name>

<street>123 Maple Street</street>

<city>Mill Valley</city>

<state>CA</state>

<zip>90952</zip>
</Address>

</shipTo>

<orderDate>1999-05-20</orderDate>

<shipDate>1999-05-25</shipDate>

<comments>
Get these things to me in a hurry, my lawn is going wild!
</comments>

<Items>

<Item>

<productName>Lawnmower, model BUZZ-1</productName>

<quantity>1</quantity>

<price>148.95</price>

</Item>

<Item>

<productName>Baby Monitor, model SNOOZE-2</productName>

<quantity>1</quantity>

<price>39.98</price>

</Item>

</Items>

<trackingInformation xmlns="http://somewhere.com/tracking.xml">

<route>1234-5678</route>

<signature>32143912850-3959159=1395</signature>

</trackingInformation>

</PurchaseOrder>

因为我们要求任何未提及的属性或元素都要有名域限制,trackingInformation元素如果没有xmlns属性将是无效的

属性

XML文档主要由元素和属性组成.目前为止,我们已经看到了信息完全用元素来表达的定货单(Purchase Order).假设我们想要这样的文档:

<PurchaseOrder xmlns="http://fabrikam.com/PO.xml"
orderDate="1999-05-20"

shipDate="1999-05-25"

comments=

"Get these things to me in a hurry, my lawn is going wild!"

shipTo="Address-1"

items="Item-1 Item-2"

>

<Address id="Address-1"

xmlns="http://electrocommerce.org/stuff.xml"

name="Alice Smith"

street="123 Maple Street"

city="Mill Valley"

state="CA"

zip="90952" />

<Item productName="Lawnmower, model BUZZ-1"

quantity="1"

price="148.95" />

<Item productName="Baby Monitor, model SNOOZE-2"

quantity="1"

price="39.98" />

</PurchaseOrder>

这需要一个不同的大纲.(实际上,要求几个大纲间存在差异,因为我们将需要改变"http://fabrikam.com/PO.xml"和"http://electrocommerce.org/stuff.xml".)让我们来看以下修改后的PurchaseOrder大纲.

<schema xmlns="urn:schema-microsoft-com:xml-data"
xmlns:dt="urn:schema-microsoft-com:datatypes">

<ElementType name="PurchaseOrder" content="eltOnly" >

<AttributeType name="shipTo" dt:type="idref"/>

<attribute type="shipTo"/>>

<AttributeType name="shipTo" dt:type="idref"/>

<attribute type="shipTo"/>

<AttributeType name="items" dt:type="idrefs"/>

<attribute type="items" />

<AttributeType name="orderDate" dt:type="date"/>

<attribute type="orderDate"/>

<AttributeType name="shipDate" dt:type="date"/>

<attribute type="shipDate"/>

<AttributeType name="comments" dt:type="string"/>

<attribute type="comments" />

<element type="abcde:Address"

xmlns:abcde="http://electrocommerce.org/stuff.xml" />

<element type="Items" maxOccurs="*"/>

</ElementType>

<ElementType name="Item">

<AttributeType name="id" dt:type="id"/>

<attribute type="id" />

<AttributeType name="product" dt:type="string"/>

<attribute type="product" />

<AttributeType name="quantity" dt:type="int"/>

<attribute type="quantity" />

<AttributeType name="price" dt:type="fixed.14.4"/>

<attribute type="price" />

</ElementType>

</schema>

属性类型用AttributeType元素声明:

<AttributeType name="shipTo" dt:type="idref"/>
然后用attribute元素来引用:

<attribute type="shipTo"/>
属性声明和引用通常成对出现:

<AttributeType name="shipTo" dt:type="idref"/>
<attribute type="shipTo"/>

类似与元素,属性也可能有数据类型.比如,shipTo元素的数据类型是"idref". 我们还没有讨论过该数据类型,以及其他两个相关的数据类型"id"和"idrefs."数据类型是"id"的属性在文档实例中保留有标识值,该值不会在出现在文档中任何其他的id属性中.An attribute of type "idref"类型的属性是用匹配的id值来引用元素."Idrefs"类似"idref",但有一系列用空格分开的id值.例如

shipTo="Address-1"
items="Item-1 Item-2"

在某些方面属性比元素更受限制.属性不能包含子元素.你不能要求属性一特殊的顺序出现,也不能指定两者择一("product"或"backOrderedProduct"). 你可以说明一个属性是必须的还是可选的,但在一个元素中一个属性只能出现一次.

同时,属性也有一些元素不具备的性能:属性值可以被限定一个字符串集,也能指定属性省略时的缺省值. 最重要的是,不同的元素类型可以有同名的属性.而这些属性被认为是独立不相关的.

要指定属性不可选而是必须的,可以这么写:

<AttributeType name="shipTo" dt:type="idref" required="yes"/>

要限制属性值是一短列表中的词,这么写:

<AttributeType name="priority" dt:type="enumeration" dt:values="high medium low" />

要给属性值赋缺省值,则这样写:

<AttributeType name="quantity" dt:type="int" default="1"/>.


--  作者:wscj5218
--  发布时间:5/22/2008 9:32:00 PM

--  
给出空的大纲有误
<Schema xmlns="urn:schema-microsoft-com:xml-data" xmlns:dt="urn:schema-microsoft-com:datatypes">
</Schema>
应在URI中 改为   urn:schemas-microsoft-com:xml-data  后一个同理
--  作者:jingwan
--  发布时间:6/28/2008 7:02:00 PM

--  

W 3 C h i n a ( since 2003 ) 旗 下 站 点
苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
58.594ms