1、復雜類型和簡單類型之間最根本的區別就是:復雜類型的內容中可以包含其他元素,也可以帶有屬性(Attribute),但簡單類型既不能包含子元素,也不能帶有任何屬性。 <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可以通過其minOccurs和maxOccurs兩個屬性來約束元素實例存在的個數,這兩個屬性的缺省值都是1,表示默認情況下此元素在XML實例文檔中必須出現一次。
3、attribute存在約束:元素屬性也可以通過attribute的use屬性來約束出現一次或根本不出現;use屬性的取值可以是required,optional,prohibited三個值,缺省(默認)值是optional.
4、element和attribute都有一個default和fixed屬性,針對element來書,只有當element實例為空時才采用此default值,而attribute是當實例不提供此attribute時才采用此default值,因此對attribute而言,只有其use值是optional時default值才有意義,而且對element和attribute來說fixed和default兩個屬性不能同時存在,否則會出現錯誤。
5、直接定義在schema元素下,即schema元素的頂級子元素的element和attribute都是全局的,稱之為全局元素和全局屬性,你在其他類型定義中可以直接引用。
6、派生新類型有兩種方式:第一種就是直接從其他類型中擴展(繼承)而來,另外一種就是通過對已有類型進行限定性約束而來。 如:以下有三種通過限定性約束定義的新類型: 通過值范圍限定: <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等系統內建的類型)、列表類型、聯合類型合起來統一稱為簡單類型。在Schema中有NMTOKENS、IDREFS、ENTITIES三種內建的列表類型,你也可以從已有的簡單類型來創建list(列表)類型,但你不能從已有的list類型和復雜類型來創建列表(list)類型。 如: <xsd:simpleType name="listOfMyIntType"> <xsd:list itemType="myInteger"/> </xsd:simpleType> 在XML實例文檔中列表類型的值是通過空格來進行分隔的,如果聲明了一個listOfMyIntType元素,其值可能是: <listOfMyInt>20003 15037 95977 95945</listOfMyInt>
8、有幾個方面的元素可以應用于list類型來進行約束,它們是: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> 注:針對列表類型要千萬注意成員是string類型的,因為string類型中的空格和列表類型的分割符空格會造成部分混淆。 [page_break]9、對元素的定義可以采用通過指定其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(聯合)類型表示在XML實例文檔中的元素實例符合union類型定義的成員類型中的一種就可以了(合法),這一點和C++中的聯合類型有類似的概念,如: <xsd:simpleType name="addrUnion"> <xsd:union memberTypes="xsd:string integer"/> </xsd:simpleType>
11、復雜類型一般可以分為三類:第一類是包含字符內容和屬性但不包含子元素;第二類是包含屬性和子元素但不包含字符數據(字符數據包含在子元素中);第三類是即包含屬性和字符內容又包含子元素的;那么如何來定義這三類類型呢?針對第一類可以通過simpleContent來實現,第二類可以通過complexContent來做到,第三類只需要將complexType的屬性mixed設為true就可以了。具體的例子如下:
第一種類型(從一個簡單類型擴展而來,增加了屬性): <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>
第二種類型(有一個element和兩個attribute構成): <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> 注意:在這里由于默認情況下缺省是complexContent,所以在這里簡略的寫法是: <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> 第三種類型的實例可能如下: <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、根據11的描述那么要定義一個空內容的元素,也就是說定義一個只包含屬性的元素,只要在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三個元素來進行注釋,其中appI和document都是作為annotation的子元素來處理的。并且annotation一般是作為schema的頂層子元素、element的構造、類型定義的頂層子元素的。 如: <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僅允許在實例文檔中使用其中一個子元素;在all中的所有元素都可以出現一次或一次都不出現,并且其中元素實例是沒有順序約束的,而且all必須放在任何內容模型的最頂層,為了說明這個問題,下面先列出一個合法的,然后列出一個不合法的以供對照說明: <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> 下面是一個不合法的: <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、在存在很多類型中都有幾個相同的類型的情況,可以采用屬性組的方式來進行重用,屬性組定義的格式是: <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、關于include的用法 include元素可以將外部的定義和聲明引入到文檔中,并且作為新Schema文檔的一部分,但必須注意的一點是,被包含成員的目標命名空間必須和包含的目標命名空間一樣。具體寫法例子是: <include schemaLocation=“http://www.example.com/schemas/address.xsd” />
2、如果一個類型是從另一個類型擴展而來的,那么定義為父類型的element,在實例文檔中,可以通過符合子類型的element實例來代替,但必須通過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> <!-- 擴展類型定義 --> <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實例文檔中針對human可以是這樣的(和面向對象有類似的概念): <human xsi:type=”Father”> <name>xiaogen</name> <gender>male</gender> </human>
3、關于置換組 XML Schema提供了一種機制叫置換組,允許原先定義好的元素被其他元素所替換。更明確的,這個置換組包含了一系列的元素,這個置換組中的每一個元素都被定義為可以替換一個指定的元素,這個指定的元素稱為頭元素(Head Element),需要注意的是頭元素必須作為全局元素聲明,注意,當一個實例文檔包含置換元素時替換元素的類型時從它們的頭元素那里派生的,此時并不需要使用我們前面所說的xsi:type來識別這些被派生的類型,當定義了置換組之后,并非意味著不能使用頭元素,而只能使用這個置換組中的元素,它只是提供了一個允許元素可替換使用的機制。例如: <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> 下面是實例文檔的一個例子: <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、抽象元素和抽象類型 當一個元素或者類型被聲明為“abstract”時,那么它就不能在實例文檔中使用。當一個元素被聲明為”abstract”的時候,元素的置換組的成員必須出現在實例文檔中。當一個元素相應的類型被定義聲明為"abstract"時,所有關聯該元素的實例必須使用"xsi:type"來指明一個類型,這個類型必須是非抽象的,同時是在定義中聲明的抽象類型的派生類型。 一、如將上面的comment元素的聲明更改成: <xsd:element name=”comment” type=”xsd:string” abstract=”true” /> 那么上面的order實例中就只能包含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> 根據以上的定義和聲明,下面的實例片斷就是不能通過驗證的: <transport xmlns="http://cars.example.com/schema" /> 下面經過修改的就可以通過驗證了。 <transport xmlns=“http://cars.example.com/schema” ?xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Car"/>
5、為了阻止類型被派生(包括通過限制派生和通過擴展派生),可以使用final來設置(有點和java中的final的概念類似),其值有三個:restriction,extension,#all。在模式文件的根元素schema元素中有一個可選的finalDefault屬性,它的值能夠取為final屬性所允許的幾個值之一。指定finalDefault屬性的值的效果等于在模式文檔中每個類型定義和元素聲明中指定final屬性,同時其值為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、因為在實例文檔中與父類型關聯的元素(也就是聲明為父類型的元素)可以通過派生的子類型來替代,這在2中已經有詳細的說明和例子。同時,XML Schema也提供了一種機制來控制派生類型以及置換組在實例文檔中使用的機制。這種機制是通過類型的block屬性來控制的,該屬性可以取值為:restriction,extension,#all。和final屬性一樣,在模式文檔的根元素schema元素里有一個可選的屬性blockDefault,它的值為block屬性所允許的值中的一個。指定blockDefault屬性的作用等價于在模式文檔中為每個類型定義和元素聲明指定block屬性。如在前面例子中我們想阻止在使用Father來替代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屬性將阻止在實例文檔中使用通過擴展的派生類型來替換Person(即可以阻止Father來替換Person),然而它不會阻止通過約束的派生來替換Person。
7、另外一種派生類型的控制機制是應用于簡單類型方面的派生。當定義一個簡單類型的時候,我們可以使用fixed屬性對它的所有定義的參數進行修飾,以阻止這些參數在類型派生中被修改,例如: <xsd:simpleType name=”Postcode”> <xsd:restriction base=”xsd:string”> < xsd:length value=”7” fixed=”true” /> </xsd:restriction> </xsd:simpleType> 當這個簡單類型被定義之后,我們能夠派生出一個新的郵編類型,在其中我們使用了一個沒有在基本類型中固定的參數: <xsd:simpleType name="UKPostcode"> <xsd:restriction base=" Postcode"> <xsd:pattern value="[A-Z]{2}\d\s\d[A-Z]{2}"/> </xsd:restriction> </xsd:simpleType> 然而,我們不能購派生出一個這樣的新的郵編類型:在其中我們重新定義了任何在基類型中已經被固定(fixed)的參數: <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>
|