XML Schema幫你建模(2)
發(fā)布時(shí)間:2008-09-07 閱讀數(shù): 次 來源:網(wǎng)樂原科技
復(fù)合類型定義、元素和屬性聲明
在XML Schema中,對(duì)于那些允許元素有自己的內(nèi)容,以及可以攜帶自身屬性的復(fù)合類型與那些不能夠有元素內(nèi)容和屬性的簡(jiǎn)單類型,它們的表示形式有著本質(zhì)的不同。在實(shí)例文檔中,對(duì)于能建立新的類型(無論簡(jiǎn)單和復(fù)雜)的定義和允許元素和屬性有特定的名字和類型(無論是簡(jiǎn)單還是復(fù)雜)的聲明,它們之間也有著顯著的差別。在這一節(jié)中,將針對(duì)如何定義復(fù)合類型,以及如何聲明使用復(fù)合類型的元素及其屬性做較詳細(xì)的描述。
在一個(gè)模式文檔中,當(dāng)需要定義新的復(fù)合類型的時(shí)候,應(yīng)當(dāng)使用complexType元素來定義,這樣的典型定義包括元素聲明、元素引用和屬性聲明。這些元素聲明與其說是它們自身的類型,不如說是一由相關(guān)模式控制的元素名與控制這些元素名在實(shí)例文檔中的表現(xiàn)形式的型約束之間的關(guān)聯(lián)。元素是通過使用element元素來聲明的,屬性則是通過使用attribute元素來聲明的。舉例來說,USAddress被定義為一個(gè)復(fù)合類型,所以在USAddress類型定義中看到它包含了五個(gè)元素的聲明和一個(gè)屬性的聲明(參見代碼3)。
<!--代碼3 復(fù)合類型定義示例: USAddress-->
<xsd:complexType name="USAddress" >
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/>
<xsd:element name="street" type="xsd:string"/>
<xsd:element name="city" type="xsd:string"/>
<xsd:element name="state" type="xsd:string"/>
<xsd:element name="zip" type="xsd:decimal"/>
</xsd:sequence>
<xsd:attribute name="country" type="xsd:NMTOKEN" fixed="US"/>
</xsd:complexType>
這個(gè)定義的含義是,在實(shí)例文檔中出現(xiàn)任何類型聲明為USAddress的元素(比如在po.xml中的shiptTo)必須包含五個(gè)元素和一個(gè)屬性,而且這些元素必須被命名為name、street、city、state和zip,這些名稱應(yīng)該與在模式定義中element元素的name屬性的值相一致。并且這些元素必須按照模式聲明中的相同順序出現(xiàn),前四個(gè)元素必須包含一個(gè)字符串元素內(nèi)容,第五個(gè)必須包含一個(gè)十進(jìn)制數(shù)字類型的元素內(nèi)容。聲明為USAddress類型的元素可以帶有一個(gè)country屬性,該屬性必須包含字符串“US”。
USAddress類型定義僅僅包含了引用簡(jiǎn)單類型的元素聲明,這些簡(jiǎn)單類型包括string、decimal 和NMTOKEN。與之對(duì)比,PurchaseOrderType類型定義(參閱代碼4)則包含了引用復(fù)合類型的元素聲明,如USAddress。這兩個(gè)類型聲明都使用同樣的type屬性來標(biāo)識(shí)類型,而無需去區(qū)分類型是簡(jiǎn)單的還是復(fù)合的。
<!--代碼4 復(fù)合類型定義示例: Purchase OrderType-->
<xsd:complexType name="PurchaseOrderType">
<xsd:sequence>
<xsd:element name="shipTo" type="USAddress"/>
<xsd:element name="billTo" type="USAddress"/>
<xsd:element ref="comment" minOccurs="0"/>
<xsd:element name="items" type="Items"/>
</xsd:sequence>
<xsd:attribute name="orderDate" type="xsd:date"/>
</xsd:complexType>
在PurchaseOrderType的類型定義中,對(duì)于shipTo 和 billTo這兩個(gè)子元素的聲明將不同的元素名與相同的復(fù)合類型相關(guān)聯(lián),這個(gè)復(fù)合類型是USAddress。這個(gè)定義的結(jié)果是,如果在實(shí)例文檔中出現(xiàn)的任何元素(如po.xml中),當(dāng)元素類型被聲明為PurchaseOrderType時(shí),那么這個(gè)元素必須包含兩個(gè)名為shipTo 和billTo的元素,這兩個(gè)元素都要包含五個(gè)子元素(name、street、city、state和zip),這五個(gè)子元素是作為USAddress聲明的一部分出現(xiàn)的。根據(jù)USAddress的相關(guān)類型定義,shipTo和billTo元素也可以包含country屬性。
PurchaseOrderType類型定義包含了一個(gè)orderDate屬性聲明,就像在USAddress中的country屬性聲明一樣,它被標(biāo)識(shí)為一個(gè)簡(jiǎn)單類型。實(shí)際上,所有的屬性聲明必須引用簡(jiǎn)單類型。這是因?yàn)閷傩耘c元素聲明不同,是不能包含其它元素或者屬性的。
迄今為止,我們描述的元素聲明對(duì)每一個(gè)元素名都使用了一個(gè)現(xiàn)存的類型定義。然而有時(shí)候,使用一個(gè)現(xiàn)存的元素比應(yīng)用一個(gè)類型來定義一個(gè)新的元素更為方便(參閱代碼 5)。
<!--代碼 5 使用現(xiàn)存的元素引用來定義元素-->
<xsd:element ref="comment" minOccurs="0"/>
代碼5這個(gè)元素聲明定義引用了一個(gè)現(xiàn)存的元素comment,該元素在購(gòu)買訂單模式文檔中的其它部分被定義。一般來說,ref屬性的值必須指向一個(gè)全局元素。也就是說應(yīng)當(dāng)是在元素下面被聲明的,而不是作為復(fù)合類型定義的一部分聲明的。代碼5聲明的含義是,一個(gè)叫comment的元素可以出現(xiàn)在實(shí)例文檔關(guān)于這個(gè)定義的相關(guān)部分中,它的內(nèi)容必須和那個(gè)被引用的元素的類型一致,在這個(gè)情況下是“string”。
全局元素和屬性
全局的元素和全局的屬性是在全局聲明時(shí)建立的,全局聲明都是作為元素的直接子元素出現(xiàn)的。一旦經(jīng)過定義,全局元素或者全局屬性就可以像先前描述的那樣,在一個(gè)或多個(gè)元素/屬性聲明中使用ref屬性引用。一個(gè)引用全局元素的聲明,在實(shí)例文檔中允許被引用的元素出現(xiàn)在與聲明相關(guān)的元素中。所以舉例來說,po.xml中的comment元素同樣可以在shipTo、billTo和items元素中出現(xiàn),因?yàn)橐胏omment的復(fù)合類型定義的聲明同樣出現(xiàn)在這三個(gè)元素的聲明中。
一個(gè)全局元素的聲明也允許元素在實(shí)例文檔中以頂級(jí)的文檔元素出現(xiàn),因此purchaseOrder元素,在po.xsd中是作為一個(gè)全局元素聲明的,能夠作為po.xml.中的頂級(jí)元素出現(xiàn)。值得注意的是,基于這個(gè)基本原理comment元素作為頂級(jí)元素出現(xiàn)在文檔如po.xml中也是被允許的。
關(guān)于使用全局的元素和屬性有很多限制,其中一個(gè)限制是全局的聲明不能夠包含引用。全局的聲明定義不能包含ref 屬性,它們必須使用type 屬性(或者像例子中使用過的跟隨了一個(gè)匿名的類型定義)。第二個(gè)限制是約束不能夠放在全局聲明中,盡管它們能夠放在引用全局聲明的局部聲明中。換句話說,全局聲明不能夠包含minOccurs、maxOccurs或者use屬性。關(guān)于約束的使用,將在下一節(jié)中給出。
出現(xiàn)次數(shù)約束
我們看到,在代碼5中的元素聲明中minOccurs屬性的值為0 ,所以comment元素在PurchaseOrderType類型中是一個(gè)可選項(xiàng)。一般來說,當(dāng)某個(gè)元素的minOccurs的值為1或者更多的時(shí)候,該元素就必須出現(xiàn)。一個(gè)元素可以出現(xiàn)的最大數(shù)量由聲明中的maxOccurs屬性所決定。這個(gè)值也許是一個(gè)正的整數(shù)如1,也可能是一個(gè)很大的整數(shù)100,或者以“unbounded”的形式來表明不限最大的出現(xiàn)數(shù)量。minOccurs和maxOccurs屬性的默認(rèn)值都是1。因此,當(dāng)一個(gè)元素如comment,它沒有定義maxOccurs屬性,那么此時(shí)該元素不可以出現(xiàn)超過一次。如果僅僅指定了minOccurs屬性值的話,那么它必須小于等于maxOccurs的默認(rèn)值,也就是說minOccurs如果單獨(dú)出現(xiàn),其取值只能為0或者1,這是因?yàn)閙inOccurs的有效值必須小于等于maxOccurs的有效值。同理,如果只指定了maxOccurs屬性,它就必須大于等于minOccurs的默認(rèn)值,也就是必須取值為1或者更多。如果兩個(gè)屬性都被省略了,那么元素必須出現(xiàn)且僅出現(xiàn)一次。
對(duì)于屬性而言,它可以有兩種選擇:出現(xiàn)一次或者根本不出現(xiàn),不會(huì)有其它的出現(xiàn)次數(shù)。所以指定屬性出現(xiàn)次數(shù)的語法與元素的語法有所不同。特別需要注意的,屬性聲明能夠使用一個(gè)use屬性來指明屬性是否需要出現(xiàn)(可參見代碼2,po.xsd中partNum屬性的聲明)。
屬性和元素的默認(rèn)值都是使用default屬性來聲明的,不過這個(gè)屬性在不同的情況下有不同的語義。當(dāng)一個(gè)屬性使用默認(rèn)值來聲明的時(shí)候,如果屬性在實(shí)例文檔中出現(xiàn)了,那么屬性的值就是屬性在實(shí)例文檔中出現(xiàn)的那個(gè)值,也就是實(shí)例文檔中的值是最終有效值。如果屬性沒有在實(shí)例文檔中出現(xiàn),模式處理器將認(rèn)為這個(gè)屬性的值等于聲明中default屬性的值。需要注意的是,屬性默認(rèn)值只在屬性本身為“可選的”時(shí)候才有意義。如果在聲明中,既指定了默認(rèn)值,同時(shí)又設(shè)置了use屬性為除“optional”以外其它值的話(也就是必須出現(xiàn)),處理器就會(huì)產(chǎn)生錯(cuò)誤。也就是說,屬性的默認(rèn)值只有當(dāng)屬性不在實(shí)例文檔中出現(xiàn)的時(shí)候才會(huì)生效。
當(dāng)一個(gè)元素聲明中有默認(rèn)值定義的時(shí)候,模式處理器在處理默認(rèn)元素值的時(shí)候,與處理屬性的默認(rèn)值相比則有一些不同。如果實(shí)例文檔中元素出現(xiàn)且?guī)в凶陨韮?nèi)容的時(shí)候,元素的值就是實(shí)例文檔中元素的內(nèi)容。如果元素沒有內(nèi)容,那么模式處理器就認(rèn)為這個(gè)元素的值(內(nèi)容)等于聲明中default屬性的值。如果元素在實(shí)例文檔中并不出現(xiàn),則模式處理器根本不認(rèn)為該元素出現(xiàn)。
總而言之,元素和屬性默認(rèn)值之間的區(qū)別可以認(rèn)為是當(dāng)屬性不出現(xiàn)時(shí)默認(rèn)的屬性值被應(yīng)用;當(dāng)元素內(nèi)容為空的時(shí)候,默認(rèn)的元素值被應(yīng)用;而元素不出現(xiàn)的時(shí)候,默認(rèn)的元素值不被應(yīng)用。
屬性和元素聲明中,都使用了fixed屬性來確保屬性和元素被設(shè)置為特殊的值。如po.xsd中包含了一個(gè)country屬性的聲明,該屬性聲明就有一個(gè)fixed屬性,值為US。這個(gè)聲明意味著在實(shí)例文檔中country屬性的出現(xiàn)是可選的(use屬性的默認(rèn)值是optional),但是如果屬性出現(xiàn)它的值必須為“US”;如果屬性不出現(xiàn),模式處理器將自動(dòng)設(shè)置country屬性值為“US”。需要注意的是,fixed值的概念和default值的概念是互斥的,如果同時(shí)聲明fixed和default屬性就會(huì)令模式處理器產(chǎn)生一個(gè)錯(cuò)誤。
值得注意的是,在全局的元素和屬性聲明中,minOccurs、maxOccurs、use都沒有出現(xiàn),也不能出現(xiàn)。