我們現在已經討論了如何定義新的復合類型(比如PurchaseOrderType)、聲明元素(比如purchaSEOrder)和聲明屬性(如orderDate)。在這些定義行為中,一般都包含著命名,如果我們給兩個對象賦予同樣的名稱會有何種結果? 答案取決於問題中的兩個對象,一般來說這兩個對象越相近,它們越有可能引起沖突。
下面,我們給出一些例子來說明什麼時候同樣的名稱會導致問題。如果兩個對象都是類型,而且定義了一個復合類型為USStates,同時又定義了一個簡單類型為USStates,此時就出現了沖突。如果兩個對象是類型和元素或者是類型和屬性,當定義了一個復合類型叫USAddress時,同時又定義了一個元素稱為USAddress,此時是沒有沖突發生的。如果兩個對象是不同類型的元素(一般地、並非是全局元素),當我們聲明了一個元素名字作為USAddress類型的一部分,並且第二個元素名字作為item類型的一部分,此時就沒有沖突(類似的元素有時候稱為局部元素聲明)。最後,如果兩個對象都是類型,你自己定義了其中的一個,而XML Schema規范內置定義了另外的一個,比如定義了一個簡單類型稱為decimal,那麼此時沒有沖突發生。這裡之所以沒有命名沖突發生的,因為它們屬於不同的命名空間。
使用簡單類型
在購買訂單模式文檔po.xsd中,有幾個元素和屬性被聲明為簡單類型。其中一些簡單類型如 string 和decimal是XML Schema中內置的,其它的一些則是源於(如果使用對象技術的語言就是繼承)內置的類型。舉例來說,partNum屬性的類型稱為SKU(Stock Keeping Unit),它是源於string的。內置的簡單類型和它們的後繼版本都能夠用在所有的元素和屬性聲明中。
新的簡單類型通過從現有的簡單類型(內置的簡單類型以及源於內置簡單類型的簡單類型)引出定義。通常,我們通過重新約束一個現存的簡單類型來引出一個新的簡單類型。換句話說,新類型的合法值范圍是現有類型的值范圍的子集。我們使用simpleType元素來定義和命名新的簡單類型,使用restriction元素來指出現有的基類型,並且用它來標識約束值范圍的細節。
假設希望建立一個新的整數類型稱為myInteger,它的值范圍為10000到99999。那麼定義應當基於簡單類型integer,然後定義它的值范圍為10000到99999。為了定義myInteger,這樣來約束integer的范圍,參見代碼6:
<!--代碼 6 使用基類型來定義新的簡單類型-->
<xsd:simpleType name="myInteger">
<xsd:restriction base="xsd:integer">
<xsd:minInclusive value="10000"/>
<xsd:maxInclusive value="99999"/>
</xsd:restriction>
</xsd:simpleType>
代碼6的例子顯示了由一個基本類型定義和兩個值域區間方面描述的組合,通過這三個要素對myInteger實施定義。
先前的購買訂單模式文檔包含了其它更詳細的定義簡單類型的例子。一個叫SKU的新簡單類型(參見代碼7)是從(通過約束)簡單類型string引出的。此外,我們使用一個稱為pattern的描述,以及pattern的正則表達式值“\d{3}-[A-Z]{2}”來約束SKU的值。其中,該正則表達式值的語義為3個數字後面跟著一個連字號,接著跟著兩個大寫的英文字母。
<!--代碼7 SKU簡單類型定義-->
<xsd:simpleType name="SKU">
<xsd:restriction base="xsd:string">
<xsd:pattern value="\d{3}-[A-Z]{2}"/>
</xsd:restriction>
</xsd:simpleType>
<!--代碼8 USState簡單類型定義-->
<xsd:simpleType name="USState">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="AK"/>
<xsd:enumeration value="AL"/>
<xsd:enumeration value="AR"/>
<!-- and so on ... -->
</xsd:restriction>
</xsd:simpleType>
USState將會在現用的state元素聲明中成為string類型的一個非常好的替換品。通過使用這個替換品可以使state元素具有合法值的校驗能力。舉例來說,billTo和shipTo元素的子元素state,將會被限制在AK、AL和AR等中。注意對於特定類型的列舉值必須是惟一的。
匿名類型定義
使用XML Schema,我們能夠通過定義一系列具有名稱的類型,如PurchaseOrderType類型。然後聲明一個元素,比如purchaSEOrder,通過使用“type=”這樣的構造方法來應用類型。這種類型的模式構造非常直截了當,但有些不實用。特別是如果定義了許多只應用一次而且包含非常少約束的類型,在這種情況下,一個類型應該能夠被更簡單的定義。這樣的簡單定義通常的形式是一個節省了名稱和外部引用開銷的匿名類型。
在po.xsd(參見代碼9)中類型Items的定義中,有兩個元素聲明使用了匿名類型定義,它們是item和quantity。一般的來說,你通過元素中是否包含“type=”這個屬性可以判斷匿名元素定義(或者是匿名屬性定義)。如果出現無名稱的類型定義,也可以認為是匿名元素(屬性)定義。
<!--代碼 0-9 po.xsd模式定義-->
<xsd:complexType name="Items">
<xsd:sequence>
<xsd:element name="item" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="prodUCtName" type="xsd:string"/>
<xsd:element name="quantity">
<xsd:simpleType>
<xsd:restriction base="xsd:positiveInteger">
<xsd:maxExclusive value="100"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="USPrice" type="xsd:decimal"/>
<xsd:element ref="comment" minOccurs="0"/>
<xsd:element name="shipDate" type="xsd:date" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="partNum" type="SKU" use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
在item元素中,它被定義為一個復合匿名類型。該復雜類型是由productName、quantity、USPrice、comment、shipDate元素和一個稱為partNum的屬性組成的。在quantity元素中,它有一個簡單匿名類型從integer類型中引出,它的值范圍為1到99。