hema學習筆記(二)
張小根
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>