Latest web development tutorials

XML Schema 實例

本節會為您演示如何編寫一個XML Schema。 您還將學習到編寫schema 的不同方法。


XML 文檔

讓我們看看這個名為"shiporder.xml" 的XML 文檔:

<?xml version="1.0" encoding="ISO-8859-1"?>

<shiporder orderid="889923"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="shiporder.xsd">
<orderperson>John Smith</orderperson>
<shipto>
<name>Ola Nordmann</name>
<address>Langgt 23</address>
<city>4000 Stavanger</city>
<country>Norway</country>
</shipto>
<item>
<title>Empire Burlesque</title>
<note>Special Edition</note>
<quantity>1</quantity>
<price>10.90</price>
</item>
<item>
<title>Hide your heart</title>
<quantity>1</quantity>
<price>9.90</price>
</item>
</shiporder>

上面的XML文檔包括根元素"shiporder",其中包含必須名為"orderid" 的屬性。 "shiporder" 元素包含三個不同的子元素:"orderperson"、"shipto" 以及"item"。 "item" 元素出現了兩次,它含有一個"title"、一個可選"note" 元素、一個"quantity" 以及一個"price" 元素。

上面這一行xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance",告知XML解析器根據某個schema 來驗證此文檔。 這一行:xsi:noNamespaceSchemaLocation="shiporder.xsd" 規定了schema 的位置(在這裡,它與"shiporder.xml" 處於相同的文件夾)。


創建一個XML Schema

現在,我們需要為上面這個XML 文檔創建一個schema。

我們可以通過打開一個新的文件來開始,並把這個文件命名為"shiporder.xsd"。 要創建schema,我們僅僅需要簡單地遵循XML 文檔中的結構,定義我們所發現的每個元素。 首先我們開始定義一個標準的XML 聲明:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
...
</xs:schema>

在上面的schema 中,我們使用了標準的命名空間(xs),與此命名空間相關聯的URI 是Schema 的語言定義(Schema language definition),其標準值是http://www.w3.org/ 2001/XMLSchema。

接下來,我們需要定義"shiporder" 元素。 此元素擁有一個屬性,其中包含其他的元素,因此我們將它認定為複合類型。 "shiporder" 元素的子元素被xs:sequence 元素包圍,定義了子元素的次序:

<xs:element name="shiporder">
<xs:complexType>
<xs:sequence>
...
</xs:sequence>
</xs:complexType>
</xs:element>

然後我們需要把"orderperson" 元素定義為簡易類型(這是因為它不包含任何屬性或者其他的元素)。 類型(xs:string) 的前綴是由命名空間的前綴規定的,此命名空間與指示預定義的schema 數據類型的XML schema 相關聯:

<xs:element name="orderperson" type="xs:string"/>

接下來,我需要把兩個元素定義為複合類型:"shipto" 和"item"。 我們從定義"shipto" 元素開始:

<xs:element name="shipto">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="address" type="xs:string"/>
<xs:element name="city" type="xs:string"/>
<xs:element name="country" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>

通過schema,我們可使用maxOccurs 和minOccurs 屬性來定義某個元素可能出現的次數。 maxOccurs 定義某元素出現次數的最大值,而minOccurs 則定義某元素出現次數的最小值。 maxOccurs 和minOccurs 的默認值都是1!

現在,我們可以定義"item" 元素了。 這個元素可在"shiporder" 元素內部出現多次。 這是通過把"item" 元素的maxOccurs 屬性的值設定為"unbounded" 來實現的,這樣"item" 元素就可出現創作者所希望的任意多次。 請注意,"note" 元素是可選元素。 我們已經把此元素的minOccurs 屬性設定為0 了:

<xs:element name="item" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="title" type="xs:string"/>
<xs:element name="note" type="xs:string" minOccurs="0"/>
<xs:element name="quantity" type="xs:positiveInteger"/>
<xs:element name="price" type="xs:decimal"/>
</xs:sequence>
</xs:complexType>
</xs:element>

現在,我們可以聲明"shiporder" 元素的屬性了。 由於這是一個必選屬性,我們規定use="required"。

注意:此屬性的聲明必須被置於最後:

<xs:attribute name="orderid" type="xs:string" use="required"/>

這是這個名為"shiporder.xsd" 的schema 文件的文檔清單:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="shiporder">
<xs:complexType>
<xs:sequence>
<xs:element name="orderperson" type="xs:string"/>
<xs:element name="shipto">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="address" type="xs:string"/>
<xs:element name="city" type="xs:string"/>
<xs:element name="country" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="item" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="title" type="xs:string"/>
<xs:element name="note" type="xs:string" minOccurs="0"/>
<xs:element name="quantity" type="xs:positiveInteger"/>
<xs:element name="price" type="xs:decimal"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="orderid" type="xs:string" use="required"/>
</xs:complexType>
</xs:element>

</xs:schema>


分割Schema

前面的設計方法非常容易,但當文檔很複雜時卻難以閱讀和維護。

接下來介紹的設計方法基於首先對所有元素和屬性的定義,然後再使用ref 屬性來引用它們。

這是用新方法設計的schema 文件("shiporder.xsd"):

<?xml version="1.0" encoding="ISO-8859-1" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<!-- definition of simple elements -->
<xs:element name="orderperson" type="xs:string"/>
<xs:element name="name" type="xs:string"/>
<xs:element name="address" type="xs:string"/>
<xs:element name="city" type="xs:string"/>
<xs:element name="country" type="xs:string"/>
<xs:element name="title" type="xs:string"/>
<xs:element name="note" type="xs:string"/>
<xs:element name="quantity" type="xs:positiveInteger"/>
<xs:element name="price" type="xs:decimal"/>

<!-- definition of attributes -->
<xs:attribute name="orderid" type="xs:string"/>

<!-- definition of complex elements -->
<xs:element name="shipto">
<xs:complexType>
<xs:sequence>
<xs:element ref="name"/>
<xs:element ref="address"/>
<xs:element ref="city"/>
<xs:element ref="country"/>
</xs:sequence>
</xs:complexType>
</xs:element>

<xs:element name="item">
<xs:complexType>
<xs:sequence>
<xs:element ref="title"/>
<xs:element ref="note" minOccurs="0"/>
<xs:element ref="quantity"/>
<xs:element ref="price"/>
</xs:sequence>
</xs:complexType>
</xs:element>

<xs:element name="shiporder">
<xs:complexType>
<xs:sequence>
<xs:element ref="orderperson"/>
<xs:element ref="shipto"/>
<xs:element ref="item" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute ref="orderid" use="required"/>
</xs:complexType>
</xs:element>

</xs:schema>


使用指定的類型(Named Types)

第三種設計方法定義了類或者類型,這樣使我們有能力重複使用元素的定義。 具體的方式是:首先對簡易元素和復合元素進行命名,然後通過元素的type 屬性來指向它們

這是利用第三種方法設計的schema 文件("shiporder.xsd"):

<?xml version="1.0" encoding="ISO-8859-1" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:simpleType name="stringtype">
<xs:restriction base="xs:string"/>
</xs:simpleType>

<xs:simpleType name="inttype">
<xs:restriction base="xs:positiveInteger"/>
</xs:simpleType>

<xs:simpleType name="dectype">
<xs:restriction base="xs:decimal"/>
</xs:simpleType>

<xs:simpleType name="orderidtype">
<xs:restriction base="xs:string">
<xs:pattern value="[0-9]{6}"/>
</xs:restriction>
</xs:simpleType>

<xs:complexType name="shiptotype">
<xs:sequence>
<xs:element name="name" type="stringtype"/>
<xs:element name="address" type="stringtype"/>
<xs:element name="city" type="stringtype"/>
<xs:element name="country" type="stringtype"/>
</xs:sequence>
</xs:complexType>

<xs:complexType name="itemtype">
<xs:sequence>
<xs:element name="title" type="stringtype"/>
<xs:element name="note" type="stringtype" minOccurs="0"/>
<xs:element name="quantity" type="inttype"/>
<xs:element name="price" type="dectype"/>
</xs:sequence>
</xs:complexType>

<xs:complexType name="shipordertype">
<xs:sequence>
<xs:element name="orderperson" type="stringtype"/>
<xs:element name="shipto" type="shiptotype"/>
<xs:element name="item" maxOccurs="unbounded" type="itemtype"/>
</xs:sequence>
<xs:attribute name="orderid" type="orderidtype" use="required"/>
</xs:complexType>

<xs:element name="shiporder" type="shipordertype"/>

</xs:schema>

restriction 元素顯示出數據類型源自於W3C XML Schema 命名空間的數據類型。 因此,下面的片段也就意味著元素或屬性的值必須是字符串類型的值:

<xs:restriction base="xs:string">

restriction 元素常被用於向元素施加限制。 請看下面這些來自以上schema 的片段:

<xs:simpleType name="orderidtype">
<xs:restriction base="xs:string">
<xs:pattern value="[0-9]{6}"/>
</xs:restriction>
</xs:simpleType>

這段代碼指示出,元素或屬性的值必須為字符串,並且必須是連續的六個字符,同時這些字符必須是0-9 的數字。