1. 程式人生 > >XML文件型別定義---XML Schema結構

XML文件型別定義---XML Schema結構

5.1 Schema概述

XML Schema是2001年5月正式釋出的W3C的推薦標準,經過數年的大規模討論和開發如今終於塵埃落定,成為全球公認的XML環境下首選的資料建模工具。
使用DTD雖然帶來較大的方便,但是,DTD存在一些缺陷:一是它用不同於XML的語言編寫,需要不同的分析器技術。這增加了工具開發商的負擔,降低了軟體瘦身的可能性,此外開發人員需要多學一門語言及其語法。而XML Schema是按標準XML規則編寫的,更容易掌握。二是DTD不支援名稱空間。隨著大部分的資料處理日益以XML為中心,資訊的相互聯絡變得日益普及與深入,名稱空間作用也將凸現。三是DTD在支援繼承和子類方面的侷限性。由於面向物件技術的出現,對繼承和子類的支援已成為軟體技術領域的主流概念。最後,DTD沒有資料型別的概念,無法對特定元素施加資料型別,對強制性結構化無計可施,例如,如何規定名為Date的資料必須包含有效值。
這些就要依靠XML Schema了。XML Schema不僅可以定義XML文件的結構而且還允許約束文件的內容,這不同於DTD。另外,一個 XML Schema自身就是一個XML文件,其基於標籤的語法比DTD中的特殊字元要清楚多了。XML Schema正是針對這些DTD的缺點而設計的,它完全使用XML作為描述手段,具有很強的描述能力、擴充套件能力和處理維護能力。
XML Schema是用一套預先規定的XML元素和屬性建立的,這些元素和屬性定義了文件的結構和內容模式。
XML Schema也是Web Services技術中需要使用的一個基本工具,然而並不是XML Schema的所有特性都會被廣泛地使用,因此,本書將不對XML Schema規範做系統的介紹。目前主要有兩種重要的模式:Microsoft XML Schema和W3C XML Schema,本章主要討論W3C XML Schema


在下面的例子中,通過使用出現在Schema元素中的名稱空間宣告xmlns:xsd= “http://www.w3.org/2001/XMLSchema”,使得模式文件中的每一個元素都有一個與XML Schema名稱空間相關聯的名稱空間字首xsd。儘管在語法上,可以使用任意的字首形式,但是,名稱空間字首xsd被約定用於表示XML Schema名稱空間。由於使用同樣的字首,所以同樣的關聯就會出現在內建的簡單型別的名字中,例如xsd:string。這種形式關聯的目的是用來表示當前的元素或簡單型別屬於XML Schema語言的內建定義,而不屬於模式文件作者自己的詞彙表。為了在這裡清楚並且簡單地表示,僅提及元素的名字和簡單型別名,而忽略它們的字首xsd。

5.2 Schema的格式和使用

一個XSDL(XML Schema Definition Language)文件由元素、屬性、名稱空間和XML文件中的其他結點構成,並且至少要包含:schema根元素XML模式名稱空間的定義元素定義

5.2.1 簡單例項

【例5.1】 關於書籍資訊的XML文件,程式碼如源程式code5_1.xml所示。

<?xml version="1.0" encoding="gb2312"?>
<book isbn="0-764-58007-8">
    <title>三國演義</title>
    <author
>
羅貫中</author> <price>80.00 </price> <resume>滾滾長江東逝水,浪花淘盡英雄。是非成敗轉頭空。青山依舊在,幾度夕陽紅。白髮漁樵江渚上,慣看秋月春風。一壺濁酒喜相逢。古今多少事,都付笑談中。 </resume> <recommendation>經典好書</recommendation> <publish> <publisher>文藝出版社</publisher> <pubdate>1998.10</pubdate> </publish> </book>

如何寫這個XML文件的Schema呢?可以簡單地依照它的結構來定義它的每個元素。首先加入一個xsd:schema元素。

<?xml version="1.0" encoding=" gb2312"?> 
<xsd:schema xmlns:xsd="http://www.w3.org/2000/10/XMLSchema">

每個Schema文件都是從schema元素開始,並且只能有一個,用以控制Schema所使用的名稱空間和另外幾個選項,現在的Schema標準有好幾種,這裡決定它所採用的標準,因此是非常重要的。
對應著XML文件的book元素,同樣也定義一個名為book的元素(element)。因為這個元素有屬性(attributes)和非文字的子元素(non-text children),所以認為它是一個複雜型別(complexType)。而對於簡單型別,只能有值,不能有子元素或者屬性。同時還注意到book元素下的子元素,都按照一定的順序排列,因此使用順序元素(sequence element)來描述。

<xsd:element name="book">
<xsd:complexType>
<xsd:sequence>

順序元素(sequence element)是一個定義子元素排列順序的元素,在下面的章節,還將介紹其他類似的元素,如選擇(choice)和全選(all)。
接著定義title和author,都是xsd:string型別的簡單元素,因為沒有屬性(attributes)或者子元素。xsd:string是一個已經在名域中預定義了的XML Schema型別中的一個。

<xsd:element name="title" type="xsd:string"/>
<xsd:element name="author" type="xsd:string"/>
<xsd:element name="price" type="xsd:integer" />
<xsd:element name="resume" type="xsd:string" />
<xsd:element name="recommendation" type="xs:string" />

接著,來處理publish元素,它也是一個複雜型別,注意它的基數的定義。

<xsd:element name="publish" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>

同其他Schema定義語言不一樣,W3C XML Schema允許定義一個元素的使用基數,能指定元素的minOccurs(最小數)maxOccurs(最大數)。這裡設定maxOccurs為unbounded,這意味著能有任意多的publish元素。這兩個屬性的預設值都是1。下面,用同樣的方法定義其他的子元素。

<xsd:element name="publisher" type="xsd:string" />
<xsd:element name="pubdate" type="xsd:date" />

下面封閉complexType和element等元素。

</xsd:sequence>
</xsd:complexType>
</xsd:element>

這樣publish元素就完成了,然後封閉book的sequence元素。

</xsd:sequence>

現在,宣告book元素的屬性,通常是在最後這麼做。這樣做沒有什麼特別的原因,只不過W3C XML Schema工作組認為在元素後定義屬性感覺更加自然。

<xsd:attribute name="isbn" type="xsd:string"/>

最後,封閉所有剩下的元素。

</xsd:complexType>
</xsd:element>
</xsd:schema>

至此,一個Schema已經完成了。其中,最關鍵的在於根據文件的上下關係來定義每一個元素和屬性,並且允許有多個同名元素帶有不同的內容。為了這個目的,W3C XML Schema被設計成一種有作用域的語言,它的每一個定義只能被它定義的子元素所看見。
【例5.2】 關於books.xml模式定義的完整例子,程式碼如源程式code5_2.xsd所示。

<?xml version="1.0" encoding=gb2312" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="book">
    <xsd:complexType>
    <xsd:sequence>
        <xsd:element name="title" type="xs:string" />
        <xsd:element name="author" type="xs:string"/>
        <xsd:element name="price" type="xs:integer" />
        <xsd:element name="resume" type="xs:string" />
        <xsd:element name="recommendation" type="xs:string" />
        <xsd:element name="publish" minOccurs="0" maxOccurs="unbounded">
            <xsd:complexType>
            <xsd:sequence>
                    <xsd:element name="publisher" type="xs:string" />
                    <xsd:element name="pubdate" type="xs:date" />
            </xsd:sequence>
            </xsd:complexType>
        </xsd:element>
    </xsd:sequence>
    <xsd:attribute name="isbn" type="xs:string" />
    </xsd:complexType>
</xsd:element>
</xsd:schema>

5.2.2 Schema的使用

符合某個模式的文件稱為例項。例項可以根據特定的模式進行驗證。需要宣告XML文件的Schema例項名稱空間(xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”),並把名稱空間對映到字首xsi。例項與模式之間有多對多的關係。一個模式可以描述多個有效的例項(通過使用不同的根元素型別來實現),同樣,一個例項也可以被多個模式描述。例如一個例項可能擁有多個模式,它們有不同的驗證級別。其中一個模式可能只驗證結構,而另一個模式則根據資料型別來檢查每一個數據項。
1. Schema的作用
Schema文件用來驗證XML文件的正確性,用來判斷例項是否符合模式中所描述的所有約束,涉及到檢查例項中所有的元素和屬性。
Schema主要檢驗如下內容:
(1) 驗證資料的顯示格式是否正確及是否超出值的範圍;
(2) 驗證所有必需的資訊都存在;
(3) 確保不同使用者對文件理解的方式相同。
除了對XML文件的驗證外,Schema文件還在一定程度上擴充例項:
(1) 為元素和屬性新增預設值和固定值;
(2) 使具有簡單型別的元素和屬性值中的空白符規範化。

2. Schema的引用
一個模式可能由多個模式文件構成。多個模式文件通過包含或匯入機制來形成模式,當其他模式文件與主模式文件具有相同的目標名稱空間時,需要使用包含;當模式文件之間各自擁有不同的目標名稱空間時,需要使用匯入。下面的例子建立一個單獨用來驗證例項的模式文件。
【例5.3】 關於多個模式文件通過包含實現定義的例子,程式碼如源程式code5_3.xsd所示。

<?xml version="1.0" encoding="gb2312" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://example.org/ord"
targetNamespace="http://example.org/ord">
    <xsd:include schemaLocation="moreBookInfo.xsd"/>
    <xsd:import namespace="http://example.org/ord" schemaLocation="publish.xsd" />
    <!--…-->
</xsd:schema>

要驗證XML文件,必須指定Schema文件的位置。模式的位置可以利用帶有名稱空間模式的xsi:schemaLocation屬性以及不帶名稱空間XML模式的xsi:noNamespace SchemaLocation 屬性來指定,它們位於根/頂級元素中或XML文件的任何其他元素中。
當Schema文件不包括targetNamespace屬性時,應當通過XML文件根元素的noNamespace SchemaLocation屬性及W3C的Schema例項名稱空間(xmlns:xsi=“http://www.w3.org /2001/XML Scheam-instance”)來引用XML Schema檔案。針對上面的例項修改如下:

<?xml version="1.0" encoding="gb2312" ?>
<book  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="books.xsd"
isbn="0-764-58007-8">
    <!--…-->
</book>

然而,如果Schema文件包含了一個targetNamespace 屬性,在XML文件中就將通過schemaLocation屬性而不是noNamespaceSchemaLocation屬性來引用Schema文件。而且,這個屬性所指定的值必須是完整的。它需要包含以空格分開的兩部分,前一部分是URI,這個URI與Schema文件的targetNamespace屬性內部引用的URI是一致的;後一部分是Schema檔案的完整路徑及名稱。另外,XML文件的根元素也必須宣告Schema例項名稱空間(xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”)。Schema文件如下所示:

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
targetNamespace="http://tempuri.org/book">
    <!--…-->
</xsd:schema>

則修改上面的例項為

<?xml version="1.0" encoding="gb2312" ?>
<book  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://tempuri.org/book book.xsd"
xmlns="http://tempuri.org/book"
isbn="0-764-58007-8">
    <!--…-->
</book>

5.3 Schema元素的宣告

元素是建立XML文件的主要構建材料。在W3C XML Schema中,元素通過使用element元素實現。元素宣告用於給元素指定元素型別名稱、內容和資料型別等屬性。在XSDL中,元素宣告可以是全域性的,也可以是區域性的。

5.3.1 schema根元素

在schema文件中必須定義一個且只能定義一個schema根元素。根元素不但表明了文件型別,而且還包括模式的約束、XML模式名稱空間的定義,其他名稱空間的定義、版本資訊、語言資訊和其他一些屬性。定義如下:

<?xml version="1.0" encoding="gb2312" ?>
<xsd: schema name="mySchema" xmlns:xsd="http://www.w3.org/2001/XMLSchema"></xsd: schema>

其中name屬性指定Schema名稱,也可以不需要。xmlns指定所屬名稱空間,緊跟在後面的xsd則是該名稱空間的名稱,名稱空間http://www.w3.org/2001/XMLSchema被對映到xsd字首,在後面將詳細說明名稱空間。

5.3.2 element元素

XSD中的元素是利用element來宣告的。其中name屬性是元素的名字,type屬性是元素值的型別,在這裡可以是XML Schema中內建的資料型別或其他型別。具體定義格式如下:

<xsd:element name=“author” type=“xsd:string” />

name是元素型別的名稱,必須是以字母或下劃線開頭,而且只能夠包含字母、數字、下劃線、連線符及句號。type屬性是必要的,說明元素的資料型別。
下面的例子定義全域性元素宣告author,為簡單字串型別。

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="author" type="xsd:string"/>
</xsd:schema>

與以上文件對應的有效XML文件如下:

<?xml version="1.0"encoding="gb2312"?>
<author>羅貫中</author>

在元素的定義中還有兩個屬性:minOccurs和maxOccurs。其中minOccurs定義了該元素在父元素中出現的最少次數(預設為1,值為大於等於0的整數),maxOccurs定義了該元素在父元素中出現的最多次數(預設為1,值為大於等於0的整數)。在maxOccurs中可以把值設定為unbounded,表示對元素出現的最多次數沒有限制。

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="author" type="xsd:string"minOccurs="0" maxOccurs="unbounded"/>
</xsd:schema>

表示元素author的型別為string,出現的次數最少為0(就是可選),最多不限制。
一般來說,如果元素宣告出現在Schema文件的頂級結構中,也就是說,它的父元素是schema,那麼這些元素為全域性元素。
相反,區域性元素宣告只出現在複雜型別定義的內部,區域性元素宣告只在該型別定義中使用,而不被其他複雜型別引用或在替換組中使用。不同的複雜型別,可以有相同元素型別名稱的區域性元素。
【例5.4】 顯示title、author和price三種區域性元素宣告的模式文件,程式碼如源程式code5_4.xsd所示。

<?xml version="1.0" encoding="gb2312"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2000/10/XMLSchema">
    <xsd:complexType name="book">
        <xsd:sequence>
            <xsd:element name="title" type="xsd:string"/>
            <xsd:element name="author" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>
            <xsd:element name="price" type="xsd:integer"/>
        </xsd:sequence>
    </xsd:complexType>
</xsd:schema>

5.3.3 設定預設值和固定值

預設值和固定值通過給空元素增加值的方式來擴充套件例項。如果文件中存在空的元素,模式處理器根據模式文件的定義,會插入預設值或固定值。在XSDL中,預設值和固定值分別通過default和fixed屬性設定。兩個屬性只能出現其中之一,因為它們是互斥的。
如果元素為空,就填入預設值。下例中,聲明瞭city元素,並指定了預設值為“佚名”。

<xsd:element name="author" type="xsd:string" default="佚名"/>

必須注意的是,元素宣告中“空”的定義根據資料型別不同而有所不同。某些資料型別允許空值,包括string等。任何允許空字串值的型別,元素都不會認為是空的,從而對於字串型別元素,預設值不會被填充。相反,integer資料型別的空元素通常會被認為是空的,從而將填入預設值。此外,如果元素的xsi:nil屬性被設定為true,那麼就不會插入它的預設值。

<?xml version="1.0" encoding="gb2312"?> 
<xsd:schema xmlns:xsd="http://www.w3.org/2000/10/XMLSchema">
<xsd:element name="title" type="xsd:string"/>
<xsd:element name="author" type="xsd:string" default="N/A" />
<xsd:element name="price" type="xsd:integer" default="30" />
</xsd:schema>

元素的預設值行為見表5-1。
元素預設值行為

固定值與預設值在相同的情況下新增,它們的差別僅在於如果元素擁有一個值,則該值必須和固定值相等。當模式解析器確定元素值和固定值實際上是否相等時,會考慮到元素的資料型別。price元素的資料型別為integer,所以整數1的所有形式在例項中都會被接受,包括01、+1和周圍包含空白符的1。相反,對於author元素具有資料型別為string,字串“01”是無效的,因為與字串“1”並不相等。

<xsd:element name="author" type="xsd:string" fixed="1"/>
<xsd:element name="price" type="xsd:integer" fixed="1"/>

按照以上定義,元素的固定值行為見表5-2。
元素的固定值行為

5.3.4 引用元素和替代

引用是利用element元素的ref屬性實現的。主要適用於避免在文件中多次定義同一個元素,應當將經常使用的元素定義為根元素的子元素,即為全域性元素,這樣方便在文件的任何地方引用它。如每本書籍都有作者,其他產品也會有作者,因此可以把author屬性宣告為全域性元素,供文件中多處引用。
【例5.5】 引用元素定義的模式文件,程式碼如源程式code5_5.xsd所示。

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:element name="author" type="xsd:string"/>
   <xsd:element name="book">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element ref="author" />
              </xsd:sequence>
        </xsd:complexType>
   </xsd:element>
</xsd:schema>

在這裡還可以為某個定義的元素起一個別名,主要是利用element元素中的substitutionGroup屬性實現的。
方法如下:

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:element name="writer" type=xsd:string" substitutionGroup="author" />
    <xsd:element name="author" type="xsd:string"/>
    <xsd:element name="book">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element ref="author" />
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
</xsd:schema>

以上文件對應的有效XML文件如下:

 <?xml version="1.0"?>
<book>
    <author>羅貫中</author>
</book>

或者:

<?xml version="1.0"?>
<book>
    <writer>string</writer>
</book> 

5.4 Schema的屬性宣告

屬性宣告用於命名屬性並使之與某個特定的簡單型別相關聯。在XSDL中,實現的方法是使用attribute元素。在XML Schema文件中可以按照定義元素的方法定義屬性,但受限制的程度較高。它們只能是簡單型別,只能包含文字,且沒有子屬性。屬性是沒有順序的,而元素是有順序的。
使用屬性十分簡練,元素的功能比屬性強大,但在某些場合屬性是非常有用的。通常,對於元資料使用屬性,而對於資料則使用元素。如用屬性描述單位、語言或元素值的時間相依性。

5.4.1 建立屬性

定義屬性的方法如下:

<xsd:attribute name="isbn" type="xsd:string"/>

該語句定義了一個名為isbn的屬性,它的值必須是一個字元型別。
屬性也分全域性和區域性屬性。全域性宣告的屬性是schema元素的子元素,在模式文件中必須是唯一的。複雜型別的元素,使用ref屬性通過名稱來引用屬性。區域性屬性宣告只出現在複雜型別定義中,它們僅能在型別定義中使用,而不能被其他型別重用。下面的例子顯示了兩個屬性——isbn和amount 的全域性宣告,然後定義了一個複雜型別,使用ref屬性通過名稱來引用這兩個屬性。

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:attribute name="isbn" type="xsd:string"/>
<xsd:attribute name="amount" type="xsd:integer"/>
<xsd:complexType name="book">
<xsd:attribute ref="isbn" use="required"/>
<xsd:attribute ref="amount">
</xsd:complexType>
</xsd:schema>

use屬性用於指示屬性是必需的還是可選的,它出現在屬性引用而不是屬性宣告中,因為它關係到屬性在複雜型別中的出現,而不是屬性本身。上面的例子定義的是全域性的屬性定義方式,如果要在複雜型別裡宣告屬性,可以參照下面的例子:

 <xml ID="xmldata" SRC="code7_1.xml"></xml>
   <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <xsd:complexType name="book">
   <xsd:attribute name="isbn" type="xsd:string" use="required"/>
   <xsd:attribute name="amount" type="xsd:integer"/>
   </xsd:complexType>
   </xsd:schema>rbut

上面的例子描述了isbn和amount兩個屬性的區域性宣告,它們完全出現在複雜型別的定義中。區域性宣告的屬性名稱,作用範圍僅限於複雜型別內,在同一個複雜型別定義中,兩個屬性使用相同的限定名稱是非法的。只有當屬性會被多個名稱空間的多個元素宣告使用到時,才提倡將該屬性宣告為全域性屬性。

5.4.2 為屬性指派型別

所有的屬性宣告都把屬性指定為某種簡單型別。所有的屬性都具有簡單型別而不是複雜型別,因為它們本身不能有子元素和屬性。
屬性宣告有3種方式:
(1) 在屬性宣告中通過用type屬性指定命名簡單型別。它可以是內建型別,也可以是使用者自定義型別。
(2) 通過指定simpleType子屬性來指定匿名型別。
(3) 既沒有type屬性,又沒有simpleType子屬性,從而不指定特定型別。在這種情況下,屬性的型別為anySimpleType,它可以擁有任何值,只有它是結構合理的XML文件。
下例顯示4個屬性的宣告,採用了不同的型別指定方法。定義了grade屬性並賦予gradeType型別,amount屬性指定了內建型別integer,同時使用內嵌的匿名簡單型別來宣告bookcategory屬性,anything屬性沒有指定特定的型別。

<xsd:attribute name="amount" type="xsd:integer"/>
<xsd:attribute name="grade" type="gradeType"/>
<xsd:attribute name="bookcategory">
<xsd:simpleType>
    <xsd:restriction base="xsd:string">
      <xsd:enumeration value="文藝"/>
    <xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="anything"/>

5.4.3 屬性的預設值和固定值

對於屬性來說,也可以通過預設值和固定值的方式增加未出現的屬性來擴充例項。定義和擴充的方式與元素一致。在XSDL中,預設值和固定值分別通過default和fixed屬性設定。兩個屬性只能出現其中之一,因為它們是互斥的。
如果屬性在元素中預設,它的預設值將會被填入。如果屬性出現,且包含任意值,它將保持該值不變。下面的例子顯示了book元素的宣告,它包含一個amount屬性,該屬性被指定了預設值。

<xsd:element name="book">
    <xsd:complexType>
        <xsd:attribute name="amount" type="xsd:integer" default="100"/>
    </xsd:complexType>
</xsd:element>

固定值與預設值在基本一樣的情況下被插入,區別在於,其值應和固定值相等。同時也會考慮屬性的型別。

<xsd:element name="book">
    <xsd:complexType>
        <xsd:attribute name="isbn" type="xsd:string" fixed="100"/>
        <xsd:attribute name="amount" type="xsd:integer" fixed="100"/>
    </xsd:complexType>
</xsd:element>

5.5 Schema的資料型別

W3C XML Schema可以把XML文件中的元素宣告為特定的型別,准許解析器檢查文件的內容及其結構。XML Schema定義了兩種主要的資料型別:預定義簡單型別和複雜型別。這兩種資料型別之間的主要區別是複雜型別可以像資料一樣包含其他元素而簡單型別則只能包含資料。簡單型別給予了XML Schema低階型別檢查能力。

5.5.1 簡單型別

元素和屬性宣告都可以使用簡單型別來描述資料型別。
1. 簡單型別的種類
原子型別(不可分割的型別,如string、integer等系統內建的型別)、列表型別、聯合型別合起來統一稱為簡單型別。XML Schema具有低階型別檢查能力,允許把元素定義為表5-3中的任何型別之一。賦予簡單型別的元素具有字元型別內容,但沒有子元素或屬性。
(1) 原子型別具有不可分割的值,如10和large。
(2) 列表型別的值為用空格符隔開的原子值列表,如<availableSizes>10 large 2</available Sizes>
(3) 聯合型別的值可以是原子值,也可以是列表值。它們的區別在於該型別的有效值集是兩個或多個其他簡單型別值空間的聯合。如要對學生的成績評定等級,可以定義一個聯合型別,它允許的值既可以是0~100的整數,也可以是優、良、合格或不合格。
XML Schema支援的部分簡單型別

在前面一些例子中,有幾個元素和屬性被宣告為簡單型別。其中一些簡單型別如 string 和integer是XML Schema中內建的型別,其他的一些則是源於(如果使用物件技術的語言就是繼承)內建的型別。
除此之外,新的簡單型別可以通過從現有的簡單型別(內建的簡單型別以及源於內建簡單型別的簡單型別)引出定義。通常,通過重新約束一個現有的簡單型別來引出一個新的簡單型別。換句話說,新型別的合法值範圍是現有型別的值範圍的子集。使用simpleType元素來定義和命名新的簡單型別,使用restriction元素來指出現有的基型別,並且用它來標識約束值範圍的細節。
假設希望建立一個新的整數型別稱為myInteger,它的值範圍為10000~99999。那麼定義應當基於簡單型別integer,然後定義它的值範圍為10000~99999。為了定義myInteger,這樣來約束integer的範圍,示例如下:

<xsd:simpleType name="myInteger"> 
    <xsd:restriction base="xsd:integer">
        <xsd:minInclusive value="10000"/> 
        <xsd:maxInclusive value="99999"/>
    </xsd:restriction>
</xsd:simpleType> 

這個例子顯示了由一個基本型別定義和兩個值域區間方面描述的組合,通過這3個要素對myInteger實施定義。
2. 簡單型別的命名定義
簡單型別既可以為命名簡單型別又可以為匿名簡單型別。命名簡單型別總是在全域性定義的,而且要求在模式的資料型別中具有唯一名稱。型別的名稱必須為XML無冒號名稱,即必須以字母或下劃線開始,只能包含字、數字母、下劃線、連字元和句點。如上面的例子,簡單型別名為myInteger。
這種型別的模式構造非常直截了當,但有些不實用。特別是如果定義了許多隻應用一次而且包含非常少約束的型別,在這種情況下,一個型別應該能夠被更簡單的定義。這樣的簡單定義通常的形式是一個省略了名稱和外部引用開銷的匿名型別。
在下面的示例中,publish元素宣告使用了匿名型別定義。一般來說,通過元素中是否包含“type=”這個屬性可以判斷匿名屬性定義(或者是匿名元素定義)。如果出現無名稱的型別定義,也可以認為是匿名屬性(元素)定義。

<xsd:element name="publish">
    <xsd:simpleType>
        <xsd:restriction base="xsd:string"> 
            <xsd:maxLength value="40"/> 
        </xsd:restriction> 
    </xsd:simpleType>
</xsd:element> 
  1. 簡單型別的限制
    每個簡單型別都是從另一個簡單型別派生而來的,則另一個簡單型別稱為基型別。可以從原子型別,也可以從使用者定義的簡單型別派生。上面的例子都從內建的原子型別派生成新的簡單型別。所有新的簡單型別都以某種方式限制其基型別的值空間。下面的例子從簡單型別種類例子中定義的myInteger型別進一步限制。
<xsd:simpleType name="bookInteger"> 
    <xsd:restriction base="xsd:myInteger">
        <xsd:minInclusive value="23"/> 
    <xsd:maxInclusive value="2046"/>
  </xsd:restriction>
</xsd:simpleType> 

簡單型別定義時,都是通過restriction元素來定義限制,通過base屬性來規定一種基型別。在restriction內,可以任何順序指定任何面(facet),來對型別取值進一步限制。根據面的不同,這個元素或屬性具有不同的有效值。XML Schema面的定義見表5-4。
XML Schema面的定義
對每個內建的原子型別來說,都有一套定義時可用的面。如果某個面適用於某種原子型別,那麼也適用於由該型別派生的簡單型別。這裡有必要舉例說明列舉的簡單型別定義,下面的例子定義了一個簡單型別category,用於說明書籍的類別。

<xsd:simpleType name="category"> 
    <xsd:restriction base="xsd:token">
        <xsd:enumeration value="小說"/> 
        <xsd: enumeration value="散文"/>
        <xsd: enumeration value="傳記"/>
        <xsd: enumeration value="詩歌"/>
        <xsd: enumeration value="武俠"/>
            <xsd: enumeration value="紀實"/>
    </xsd:restriction>
</xsd:simpleType>
  1. 列表型別
    除了使用簡單型別中描述的原子型別,XML Schema還定義了其他兩種簡單型別:列表型別和聯合型別。
    列表型別由一組原子型別組成,因此它的每一個部分(原子)本身都是有意義的,定義時以空格隔開原子值的列表。舉例來說category是個列表型別。這個型別的元素將是NMTOKEN的列表,不同的NMTOKEN值使用空格分隔,如“小說 散文 傳記”。XML Schema有3個內建的列表型別,它們是NMTOKENS、IDREFS和ENTITIES。
    除了使用內建的列表型別之外,還可以通過引用現有的原子型別建立新的列表型別(不可以使用現有的列表型別來建立新的列表型別,也不能使用聯合型別來建立新的列表型別)。舉例來說,可以建立一個名為myInteger的列表型別,並在例項文件中使用它。其中示例的後半部分即為例項文件中與列表型別listOfMyIntType相一致的例項元素myInt。
<!-- Schema Fragment -->
<xsd:simpleType name="listOfMyIntType"> 
    <xsd:list itemType="myInteger"/>
</xsd:simpleType> 
<xsd:element name="myInt" type="listOfMyIntType"/>
<!-- Instance Fragment --> 
<myInt>20003 15037 95977 95945</myInt> 

一些用於描述的引數能夠被應用到列表型別的定義中,它們是length、minLength、maxLength和enumeration。舉例來說,如果想定義一個列表型別,這個列表型別正好包含了6個分類項名。首先從category型別定義一個新的列表型別,稱為cateList,然後通過限制cateList匯出只有3個項的threeBookCate型別。具體的定義如下:

<!-- Schema Fragment --> 
<xsd:simpleType name="cateList"> 
<xsd:list itemType="category"/>
</xsd:simpleType>
<xsd:simpleType name="threeBookCate">
  <xsd:restriction base="cateList"> 
    <xsd:length value="3"/>
  </xsd:restriction> 
</xsd:simpleType> 
<xsd:element name="threeBookCategory" type="threeBookCate"/>
<!-- Instance Fragment --> 
<threeBookCategory> 小說 散文 傳記</threeBookCategory> 

型別為threeBookCate的元素必須有3個項,它們中的每一個項必須是一個列舉型別category的原子型別(列舉型別將在後面的章節中介紹),在示例後半部分的例項文件中就是一個具體的應用例子。
需要注意的是,從原子型別string可以匯出一個列表型別,然而,在一個string中也許會帶有空格,而空格在一個列表型別例項中是作為分隔符使用的,因此當在使用基型別為string的列表型別時,應當格外小心。舉例來說,假設定義了一個length取值為3的列表型別,同時這個列表型別基於型別string。下面由3個元素這樣組成的列表是合法的Asia Europe Africa;而由3個元素這樣組成的列表是不合法的Asia Europe Latin America。即使Latin America在列表外可以作為單獨的一個字串存在,但當它包含在列表中時,在Latin和America之間的空格使得第4個項被有效地生成了,因此後面的例子不符合只有3個項的列表型別定義。
5. 聯合型別
應用原子型別和列表型別,一個元素或者屬性的值可以為一個或者多個原子型別(列表型別)的例項。與之相比較,一個聯合型別(Union Type)包含了多個原子型別或者列表型別,而應用了聯合型別的元素或屬性,它們的值可以是聯合型別中所包含的這些原子型別或列表型別中的任何一個型別例項。為了說明這一點,建立一個用於表示學生成績的由評定等級或者數字列表的聯合型別。gradeUnion聯合型別由一個原子型別和一個列表型別構成。

<!-- Schema Fragment -->
<xsd:simpleType name="gradeUnion">
<xsd:union>
    <xsd:simpleType name="scoreInteger">
        <xsd:restriction base="xsd:integer"> 
            <xsd:minInclusive value="0"/>
            <xsd:maxInclusive value="100"/>
        </xsd:restriction> 
    </xsd:simpleType>
    <xsd:simpleType name=<