XML Schema幫你建模(3)
發(fā)布時(shí)間:2008-09-07 閱讀數(shù): 次 來源:網(wǎng)樂原科技
命名沖突
我們現(xiàn)在已經(jīng)討論了如何定義新的復(fù)合類型(比如PurchaseOrderType)、聲明元素(比如purchaseOrder)和聲明屬性(如orderDate)。在這些定義行為中,一般都包含著命名,如果我們給兩個(gè)對象賦予同樣的名稱會(huì)有何種結(jié)果? 答案取決于問題中的兩個(gè)對象,一般來說這兩個(gè)對象越相近,它們越有可能引起沖突。
下面,我們給出一些例子來說明什么時(shí)候同樣的名稱會(huì)導(dǎo)致問題。如果兩個(gè)對象都是類型,而且定義了一個(gè)復(fù)合類型為USStates,同時(shí)又定義了一個(gè)簡單類型為USStates,此時(shí)就出現(xiàn)了沖突。如果兩個(gè)對象是類型和元素或者是類型和屬性,當(dāng)定義了一個(gè)復(fù)合類型叫USAddress時(shí),同時(shí)又定義了一個(gè)元素稱為USAddress,此時(shí)是沒有沖突發(fā)生的。如果兩個(gè)對象是不同類型的元素(一般地、并非是全局元素),當(dāng)我們聲明了一個(gè)元素名字作為USAddress類型的一部分,并且第二個(gè)元素名字作為item類型的一部分,此時(shí)就沒有沖突(類似的元素有時(shí)候稱為局部元素聲明)。最后,如果兩個(gè)對象都是類型,你自己定義了其中的一個(gè),而XML Schema規(guī)范內(nèi)置定義了另外的一個(gè),比如定義了一個(gè)簡單類型稱為decimal,那么此時(shí)沒有沖突發(fā)生。這里之所以沒有命名沖突發(fā)生的,因?yàn)樗鼈儗儆诓煌拿臻g。
使用簡單類型
在購買訂單模式文檔po.xsd中,有幾個(gè)元素和屬性被聲明為簡單類型。其中一些簡單類型如 string 和decimal是XML Schema中內(nèi)置的,其它的一些則是源于(如果使用對象技術(shù)的語言就是繼承)內(nèi)置的類型。舉例來說,partNum屬性的類型稱為SKU(Stock Keeping Unit),它是源于string的。內(nèi)置的簡單類型和它們的后繼版本都能夠用在所有的元素和屬性聲明中。
新的簡單類型通過從現(xiàn)有的簡單類型(內(nèi)置的簡單類型以及源于內(nèi)置簡單類型的簡單類型)引出定義。通常,我們通過重新約束一個(gè)現(xiàn)存的簡單類型來引出一個(gè)新的簡單類型。換句話說,新類型的合法值范圍是現(xiàn)有類型的值范圍的子集。我們使用simpleType元素來定義和命名新的簡單類型,使用restriction元素來指出現(xiàn)有的基類型,并且用它來標(biāo)識(shí)約束值范圍的細(xì)節(jié)。
假設(shè)希望建立一個(gè)新的整數(shù)類型稱為myInteger,它的值范圍為10000到99999。那么定義應(yīng)當(dāng)基于簡單類型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的例子顯示了由一個(gè)基本類型定義和兩個(gè)值域區(qū)間方面描述的組合,通過這三個(gè)要素對myInteger實(shí)施定義。
先前的購買訂單模式文檔包含了其它更詳細(xì)的定義簡單類型的例子。一個(gè)叫SKU的新簡單類型(參見代碼7)是從(通過約束)簡單類型string引出的。此外,我們使用一個(gè)稱為pattern的描述,以及pattern的正則表達(dá)式值“\d{3}-[A-Z]{2}”來約束SKU的值。其中,該正則表達(dá)式值的語義為3個(gè)數(shù)字后面跟著一個(gè)連字號(hào),接著跟著兩個(gè)大寫的英文字母。
<!--代碼7 SKU簡單類型定義-->
<xsd:simpleType name="SKU">
<xsd:restriction base="xsd:string">
<xsd:pattern value="\d{3}-[A-Z]{2}"/>
</xsd:restriction>
</xsd:simpleType>
XML Schema定義了15個(gè)用于簡單類型定義描述的元素。在這些元素中,enumeration特別有用,它能夠被用于約束除boolean類型之外的幾乎每一個(gè)簡單類型。enumeration限制簡單類型的值為一系列不同的枚舉值。舉例來說,我們可以使用enumeration來定義一個(gè)新類型稱為USState(參見代碼8),USState是從string類型引出的,同時(shí)它的值必須為美國州名的縮寫。
<!--代碼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將會(huì)在現(xiàn)用的state元素聲明中成為string類型的一個(gè)非常好的替換品。通過使用這個(gè)替換品可以使state元素具有合法值的校驗(yàn)?zāi)芰?。舉例來說,billTo和shipTo元素的子元素state,將會(huì)被限制在AK、AL和AR等中。注意對于特定類型的列舉值必須是惟一的。
匿名類型定義
使用XML Schema,我們能夠通過定義一系列具有名稱的類型,如PurchaseOrderType類型。然后聲明一個(gè)元素,比如purchaseOrder,通過使用“type=”這樣的構(gòu)造方法來應(yīng)用類型。這種類型的模式構(gòu)造非常直截了當(dāng),但有些不實(shí)用。特別是如果定義了許多只應(yīng)用一次而且包含非常少約束的類型,在這種情況下,一個(gè)類型應(yīng)該能夠被更簡單的定義。這樣的簡單定義通常的形式是一個(gè)節(jié)省了名稱和外部引用開銷的匿名類型。
在po.xsd(參見代碼9)中類型Items的定義中,有兩個(gè)元素聲明使用了匿名類型定義,它們是item和quantity。一般的來說,你通過元素中是否包含“type=”這個(gè)屬性可以判斷匿名元素定義(或者是匿名屬性定義)。如果出現(xiàn)無名稱的類型定義,也可以認(rèn)為是匿名元素(屬性)定義。
<!--代碼 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元素中,它被定義為一個(gè)復(fù)合匿名類型。該復(fù)雜類型是由productName、quantity、USPrice、comment、shipDate元素和一個(gè)稱為partNum的屬性組成的。在quantity元素中,它有一個(gè)簡單匿名類型從integer類型中引出,它的值范圍為1到99。