XML Schema學(xué)習(xí)筆記
發(fā)表時(shí)間:2024-02-05 來(lái)源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]1、復(fù)雜類型和簡(jiǎn)單類型之間最根本的區(qū)別就是:復(fù)雜類型的內(nèi)容中可以包含其他元素,也可以帶有屬性(Attribute),但簡(jiǎn)單類型既不能包含子元素,也不能帶有任何屬性。 <xsd:complexType name="CNAddress" > <xsd:sequen...
1、復(fù)雜類型和簡(jiǎn)單類型之間最根本的區(qū)別就是:復(fù)雜類型的內(nèi)容中可以包含其他元素,也可以帶有屬性(Attribute),但簡(jiǎn)單類型既不能包含子元素,也不能帶有任何屬性。
<xsd:complexType name="CNAddress" >
<xsd:sequence>
<xsd:element name="name"type="xsd:string"/>
<xsd:element name="street" type="xsd:string"/>
<xsd:element name="city"type="xsd:string"/>
<xsd:element name="zip"type="xsd:decimal"/>
</xsd:sequence>
<xsd:attribute name="country" type="xsd:NMTOKEN" fixed="US"/>
</xsd:complexType>
2、element存在約束:element可以通過(guò)其minOccurs和maxOccurs兩個(gè)屬性來(lái)約束元素實(shí)例存在的個(gè)數(shù),這兩個(gè)屬性的缺省值都是1,表示默認(rèn)情況下此元素在XML實(shí)例文檔中必須出現(xiàn)一次。
3、attribute存在約束:元素屬性也可以通過(guò)attribute的use屬性來(lái)約束出現(xiàn)一次或根本不出現(xiàn);use屬性的取值可以是required,optional,prohibited三個(gè)值,缺。J(rèn))值是optional.
4、element和attribute都有一個(gè)default和fixed屬性,針對(duì)element來(lái)書(shū),只有當(dāng)element實(shí)例為空時(shí)才采用此default值,而attribute是當(dāng)實(shí)例不提供此attribute時(shí)才采用此default值,因此對(duì)attribute而言,只有其use值是optional時(shí)default值才有意義,而且對(duì)element和attribute來(lái)說(shuō)fixed和default兩個(gè)屬性不能同時(shí)存在,否則會(huì)出現(xiàn)錯(cuò)誤。
5、直接定義在schema元素下,即schema元素的頂級(jí)子元素的element和attribute都是全局的,稱之為全局元素和全局屬性,你在其他類型定義中可以直接引用。
6、派生新類型有兩種方式:第一種就是直接從其他類型中擴(kuò)展(繼承)而來(lái),另外一種就是通過(guò)對(duì)已有類型進(jìn)行限定性約束而來(lái)。
如:以下有三種通過(guò)限定性約束定義的新類型:
通過(guò)值范圍限定:
<xsd:simpleType name="myInteger">
<xsd:restriction base="xsd:integer">
<xsd:minInclusive value="10000"/>
<xsd:maxInclusive value="99999"/>
</xsd:restriction>
</xsd:simpleType>
使用模式匹配限定:
<xsd:simpleType name="SKU">
<xsd:restriction base="xsd:string">
<xsd:pattern value="\d{3}-[A-Z]{2}"/>
</xsd:restriction>
</xsd:simpleType>
使用枚舉方式限定:
<xsd:simpleType name="CNCity">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="BeiJing"/>
<xsd:enumeration value="NanChang"/>
<xsd:enumeration value="ShangHai"/>
</xsd:restriction>
</xsd:simpleType>
7、原子類型(不可分割的類型,象string,integer等系統(tǒng)內(nèi)建的類型)、列表類型、聯(lián)合類型合起來(lái)統(tǒng)一稱為簡(jiǎn)單類型。在Schema中有NMTOKENS、IDREFS、ENTITIES三種內(nèi)建的列表類型,你也可以從已有的簡(jiǎn)單類型來(lái)創(chuàng)建list(列表)類型,但你不能從已有的list類型和復(fù)雜類型來(lái)創(chuàng)建列表(list)類型。
如:
<xsd:simpleType name="listOfMyIntType">
<xsd:list itemType="myInteger"/>
</xsd:simpleType>
在XML實(shí)例文檔中列表類型的值是通過(guò)空格來(lái)進(jìn)行分隔的,如果聲明了一個(gè)listOfMyIntType元素,其值可能是:
<listOfMyInt>20003 15037 95977 95945</listOfMyInt>
8、有幾個(gè)方面的元素可以應(yīng)用于list類型來(lái)進(jìn)行約束,它們是:length、minLength、maxLength和enumeration,如:
<xsd:simpleType name="USStateList">
<xsd:list itemType="USState"/>
</xsd:simpleType>
<xsd:simpleType name="SixUSStates">
<xsd:restriction base="USStateList">
<xsd:length value="6"/>
</xsd:restriction>
</xsd:simpleType>
注:針對(duì)列表類型要千萬(wàn)注意成員是string類型的,因?yàn)閟tring類型中的空格和列表類型的分割符空格會(huì)造成部分混淆。
[page_break]9、對(duì)元素的定義可以采用通過(guò)指定其type屬性為已定義的屬性的方式,也可一采用匿名定義類型的方式,如:
采用類型定義:
<xsd:element name=”comment” type=”xsd:string”>
采用匿名定義:
<xsd:element name=”quantity”>
<xsd:simpleType>
<xsd:restriction base=”xsd:positiveInteger”>
<xsd:maxExclusive value=”100” />
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
10、union(聯(lián)合)類型表示在XML實(shí)例文檔中的元素實(shí)例符合union類型定義的成員類型中的一種就可以了(合法),這一點(diǎn)和C++中的聯(lián)合類型有類似的概念,如:
<xsd:simpleType name="addrUnion">
<xsd:union memberTypes="xsd:string integer"/>
</xsd:simpleType>
11、復(fù)雜類型一般可以分為三類:第一類是包含字符內(nèi)容和屬性但不包含子元素;第二類是包含屬性和子元素但不包含字符數(shù)據(jù)(字符數(shù)據(jù)包含在子元素中);第三類是即包含屬性和字符內(nèi)容又包含子元素的;那么如何來(lái)定義這三類類型呢?針對(duì)第一類可以通過(guò)simpleContent來(lái)實(shí)現(xiàn),第二類可以通過(guò)complexContent來(lái)做到,第三類只需要將complexType的屬性mixed設(shè)為true就可以了。具體的例子如下:
第一種類型(從一個(gè)簡(jiǎn)單類型擴(kuò)展而來(lái),增加了屬性):
<xsd:element name="internationalPrice">
<xsd:complexType>
<xsd:simpleContent>
<xsd:extension base="xsd:decimal">
<xsd:attribute name="currency" type="xsd:string"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>
第二種類型(有一個(gè)element和兩個(gè)attribute構(gòu)成):
<xsd:element name="internationalPrice">
<xsd:complexType>
<xsd:complexContent>
<xsd:element name=”Country” ?type=”xsd:string” />
<xsd:attribute name="currency" type="xsd:string"/>
<xsd:attribute name="value"?type="xsd:decimal"/>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
注意:在這里由于默認(rèn)情況下缺省是complexContent,所以在這里簡(jiǎn)略的寫法是:
<xsd:element name="internationalPrice">
<xsd:complexType>
<xsd:element name=”Country”type=”xsd:string” />
<xsd:attribute name="currency" type="xsd:string"/>
<xsd:attribute name="value"?type="xsd:decimal"/>
</xsd:complexContent>
</xsd:element>
第三種類型:
<xsd:element name="letterBody">
<xsd:complexType mixed="true">
<xsd:sequence>
<xsd:element name="salutation">
<xsd:complexType mixed="true">
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="quantity"type="xsd:positiveInteger"/>
<xsd:element name="productName" type="xsd:string"/>
<xsd:element name="shipDate"type="xsd:date" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
第三種類型的實(shí)例可能如下:
<letterBody>
<salutation>Dear Mr.<name>Robert Smith</name>.</salutation>
Your order of <quantity>1</quantity> <productName>Baby
Monitor</productName> shipped from our warehouse on
<shipDate>1999-05-21</shipDate>
</letterBody>
12、根據(jù)11的描述那么要定義一個(gè)空內(nèi)容的元素,也就是說(shuō)定義一個(gè)只包含屬性的元素,只要在complexContent中不包含任何子元素,就可以了,如:
<xsd:element name="internationalPrice">
<xsd:complexType>
<xsd:attribute name="currency" type="xsd:string"/>
<xsd:attribute name="value"type="xsd:decimal"/>
</xsd:complexType>
</xsd:element>
13、anyType是所有Schema類型的基類型,和Java中的Object類似。因此,以下定義:
<xsd:element name="anything" type="xsd:anyType"/>
可以寫成:
<xsd:element name="anything"/>
14、Schema中用annotation、document、appInfo三個(gè)元素來(lái)進(jìn)行注釋,其中appI和document都是作為annotation的子元素來(lái)處理的。并且annotation一般是作為schema的頂層子元素、element的構(gòu)造、類型定義的頂層子元素的。
如:
<xsd:element name="internationalPrice">
<xsd:annotation>
<xsd:documentation xml:lang="en">
element declared with anonymous type
</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:annotation>
<xsd:documentation xml:lang="en">
empty anonymous type with 2 attributes
</xsd:documentation>
</xsd:annotation>
<xsd:complexContent>
<xsd:restriction base="xsd:anyType">
<xsd:attribute name="currency" type="xsd:string"/>
<xsd:attribute name="value"type="xsd:decimal"/>
</xsd:restriction>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
15、choice僅允許在實(shí)例文檔中使用其中一個(gè)子元素;在all中的所有元素都可以出現(xiàn)一次或一次都不出現(xiàn),并且其中元素實(shí)例是沒(méi)有順序約束的,而且all必須放在任何內(nèi)容模型的最頂層,為了說(shuō)明這個(gè)問(wèn)題,下面先列出一個(gè)合法的,然后列出一個(gè)不合法的以供對(duì)照說(shuō)明:
<xsd:complexType name="PurchaseOrderType">
<xsd:all>
<xsd:element name="shipTo" type="USAddress"/>
<xsd:element name="billTo" type="USAddress"/>
<xsd:element ref="comment" minOccurs="0"/>
<xsd:element name="items"type="Items"/>
</xsd:all>
<xsd:attribute name="orderDate" type="xsd:date"/>
</xsd:complexType>
下面是一個(gè)不合法的:
<xsd:complexType name="PurchaseOrderType">
<xsd:sequence>
<xsd:all>
<xsd:element name="shipTo" type="USAddress"/>
<xsd:element name="billTo" type="USAddress"/>
<xsd:element name="items"type="Items"/>
</xsd:all>
<xsd:sequence>
<xsd:element ref="comment" />
</xsd:sequence>
</xsd:sequence>
<xsd:attribute name="orderDate" type="xsd:date"/>
</xsd:complexType>
[page_break]16、在存在很多類型中都有幾個(gè)相同的類型的情況,可以采用屬性組的方式來(lái)進(jìn)行重用,屬性組定義的格式是:
<xsd:attributeGroup name=”attrGroupName”>
<xsd:attribute name=”attrName1” type=”xsd:string” />
<xsd:attribute name=”attrName2” type=”xsd:string” />
…
</xsd:attributeGroup>
使用可以采用以下方式:
<xsd:element name=”testAttrGroup”>
<xsd:comlexType>
<xsd:element name=”element1”type=”xsd:string” />
<xsd:attributeGroup ref=”attrGroupName” />
</xsd:complexType>
</xsd:element>
1、關(guān)于include的用法
include元素可以將外部的定義和聲明引入到文檔中,并且作為新Schema文檔的一部分,但必須注意的一點(diǎn)是,被包含成員的目標(biāo)命名空間必須和包含的目標(biāo)命名空間一樣。具體寫法例子是:
<include schemaLocation=“http://www.example.com/schemas/address.xsd” />
2、如果一個(gè)類型是從另一個(gè)類型擴(kuò)展而來(lái)的,那么定義為父類型的element,在實(shí)例文檔中,可以通過(guò)符合子類型的element實(shí)例來(lái)代替,但必須通過(guò)xsi:type指明此元素的具體類型。例如:
<xsd:complexType name=”Person”>
<xsd:sequence>
<xsd:element name=”FirstName” type=”xsd:string” />
<xsd:element name=”LastName” type=”xsd:string” />
</xsd:sequence>
</xsd:complexType>
<!-- 擴(kuò)展類型定義 -->
<xsd:complexType name=”Father”>
<complexContent>
<xsd:extension base=”Person”>
<xsd:sequence>
<xsd:element name=”gender”>
<xsd:restriction base=”string”>
<xsd:enumeration value=”male” />
</xsd:restriction>
</xsd:element>
</xsd:sequence>
</xsd:extension>
</complexContent>
</xsd:complexType>
<!-- 類型的聲明 -->
<xsd:element name=”human” type=”Person” />
在XML實(shí)例文檔中針對(duì)human可以是這樣的(和面向?qū)ο笥蓄愃频母拍?:
<human xsi:type=”Father”>
<name>xiaogen</name>
<gender>male</gender>
</human>
3、關(guān)于置換組
XML Schema提供了一種機(jī)制叫置換組,允許原先定義好的元素被其他元素所替換。更明確的,這個(gè)置換組包含了一系列的元素,這個(gè)置換組中的每一個(gè)元素都被定義為可以替換一個(gè)指定的元素,這個(gè)指定的元素稱為頭元素(Head Element),需要注意的是頭元素必須作為全局元素聲明,注意,當(dāng)一個(gè)實(shí)例文檔包含置換元素時(shí)替換元素的類型時(shí)從它們的頭元素那里派生的,此時(shí)并不需要使用我們前面所說(shuō)的xsi:type來(lái)識(shí)別這些被派生的類型,當(dāng)定義了置換組之后,并非意味著不能使用頭元素,而只能使用這個(gè)置換組中的元素,它只是提供了一個(gè)允許元素可替換使用的機(jī)制。例如:
<xsd:schema>
<xsd:element name=”comment” type=”xsd:string”/>
<xsd:element name=”shipComment” type=”xsd:string”
?substitutionGroup=”comment” />
<xsd:element name=”customerComment type=”xsd:string”
substituionGroup=”comment” />
<xsd:element name=”order”>
<xsd:complexType>
<xsd:element name=”productName” type=”xsd:string” />
<xsd:element name=”price” type=”xsd:decimal” />
<xsd:element ref=”comment” />
<xsd:element name=”shipDate” type=”xsd:date” />
</xsd:complexType>
</xsd:element>
</xsd:schema>
下面是實(shí)例文檔的一個(gè)例子:
<order>
<productName>Lapis necklace</productName>
<price>999</price>
<shipComment>Use gold wrap if possible</shipComment>
<customerComment>Want this for the holidays!</customerComment>
<shipDate>2004-08-15</shipDate>
</order>
4、抽象元素和抽象類型
當(dāng)一個(gè)元素或者類型被聲明為“abstract”時(shí),那么它就不能在實(shí)例文檔中使用。當(dāng)一個(gè)元素被聲明為”abstract”的時(shí)候,元素的置換組的成員必須出現(xiàn)在實(shí)例文檔中。當(dāng)一個(gè)元素相應(yīng)的類型被定義聲明為"abstract"時(shí),所有關(guān)聯(lián)該元素的實(shí)例必須使用"xsi:type"來(lái)指明一個(gè)類型,這個(gè)類型必須是非抽象的,同時(shí)是在定義中聲明的抽象類型的派生類型。
一、如將上面的comment元素的聲明更改成:
<xsd:element name=”comment” type=”xsd:string” abstract=”true” />
那么上面的order實(shí)例中就只能包含customerComment和shipComment才是有效的。
二、如果有下面的類型定義:
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://cars.example.com/schema"
xmlns:target="http://cars.example.com/schema">
<complexType name="Vehicle" abstract="true"/>
<complexType name="Car">
<complexContent>
<extension base="target:Vehicle"/>
</complexContent>
</complexType>
<complexType name="Plane">
<complexContent>
<extension base="target:Vehicle"/>
</complexContent>
</complexType>
<element name="transport" type="target:Vehicle"/>
</schema>
根據(jù)以上的定義和聲明,下面的實(shí)例片斷就是不能通過(guò)驗(yàn)證的:
<transport xmlns="http://cars.example.com/schema" />
下面經(jīng)過(guò)修改的就可以通過(guò)驗(yàn)證了。
<transport xmlns=“http://cars.example.com/schema”
?xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Car"/>
5、為了阻止類型被派生(包括通過(guò)限制派生和通過(guò)擴(kuò)展派生),可以使用final來(lái)設(shè)置(有點(diǎn)和java中的final的概念類似),其值有三個(gè):restriction,extension,#all。在模式文件的根元素schema元素中有一個(gè)可選的finalDefault屬性,它的值能夠取為final屬性所允許的幾個(gè)值之一。指定finalDefault屬性的值的效果等于在模式文檔中每個(gè)類型定義和元素聲明中指定final屬性,同時(shí)其值為finalDefault屬性的值。如果想阻止前面的Person被限制派生,我們需要修改定義為如下:
<xsd:complexType name=”Person” final=”restriction”>
<xsd:sequence>
<xsd:element name=”FirstName” type=”xsd:string” />
<xsd:element name=”LastName” type=”xsd:string” />
</xsd:sequence>
</xsd:complexType>
6、因?yàn)樵趯?shí)例文檔中與父類型關(guān)聯(lián)的元素(也就是聲明為父類型的元素)可以通過(guò)派生的子類型來(lái)替代,這在2中已經(jīng)有詳細(xì)的說(shuō)明和例子。同時(shí),XML Schema也提供了一種機(jī)制來(lái)控制派生類型以及置換組在實(shí)例文檔中使用的機(jī)制。這種機(jī)制是通過(guò)類型的block屬性來(lái)控制的,該屬性可以取值為:restriction,extension,#all。和final屬性一樣,在模式文檔的根元素schema元素里有一個(gè)可選的屬性blockDefault,它的值為block屬性所允許的值中的一個(gè)。指定blockDefault屬性的作用等價(jià)于在模式文檔中為每個(gè)類型定義和元素聲明指定block屬性。如在前面例子中我們想阻止在使用Father來(lái)替代Person的話我們需要修改Person的定義如下:
<xsd:complexType name=”Person” block=”extension”>
<xsd:sequence>
<xsd:element name=”FirstName” type=”xsd:string” />
<xsd:element name=”LastName” type=”xsd:string” />
</xsd:sequence>
</xsd:complexType>
取值為“extension”的block屬性將阻止在實(shí)例文檔中使用通過(guò)擴(kuò)展的派生類型來(lái)替換Person(即可以阻止Father來(lái)替換Person),然而它不會(huì)阻止通過(guò)約束的派生來(lái)替換Person。
7、另外一種派生類型的控制機(jī)制是應(yīng)用于簡(jiǎn)單類型方面的派生。當(dāng)定義一個(gè)簡(jiǎn)單類型的時(shí)候,我們可以使用fixed屬性對(duì)它的所有定義的參數(shù)進(jìn)行修飾,以阻止這些參數(shù)在類型派生中被修改,例如:
<xsd:simpleType name=”Postcode”>
<xsd:restriction base=”xsd:string”>
< xsd:length value=”7” fixed=”true” />
</xsd:restriction>
</xsd:simpleType>
當(dāng)這個(gè)簡(jiǎn)單類型被定義之后,我們能夠派生出一個(gè)新的郵編類型,在其中我們使用了一個(gè)沒(méi)有在基本類型中固定的參數(shù):
<xsd:simpleType name="UKPostcode">
<xsd:restriction base=" Postcode">
<xsd:pattern value="[A-Z]{2}\d\s\d[A-Z]{2}"/>
</xsd:restriction>
</xsd:simpleType>
然而,我們不能購(gòu)派生出一個(gè)這樣的新的郵編類型:在其中我們重新定義了任何在基類型中已經(jīng)被固定(fixed)的參數(shù):
<xsd:simpleType name="UKPostcode">
<xsd:restriction base="ipo:Postcode">
<xsd:pattern value="[A-Z]{2}\d\d[A-Z]{2}"/>
<!-- illegal attempt to modify facet fixed in base type -->
<xsd:length value="6" fixed="true"/>
</xsd:restriction>
</xsd:simpleType>