XML學習筆記5——XSD復雜數據類型


  和簡單數據類型對應就是復雜數據類型了,XML元素的數據類型可以是簡單數據類型,也可以是復雜數據類型,而XML屬性的數據類型就只能是簡單數據類型。這篇筆記,就來學習一下XSD中的復雜數據類型了。

1、定義復雜數據類型

(1)和<simpleType>元素用來定義簡單數據類型相對應,可以使用<complexType>元素來定義復雜數據類型。其語法為:

<complexType    
  id
=ID   
  name
=NCName   
  abstract
=true|false   
  mixed
=true|false   
  block
=(#all|extension與restriction的自由組合)   
  final
=(#all|extension與restriction的自由組合)   
  any-attributes
> (annotation?,(simpleContent|complexContent|((group|all|choice|sequence)?,((attribute|attributeGroup)*,anyAttribute?)))) </complexType>

其中<complexType>元素的屬性說明如下:

屬性 說明
id 唯一標識<complexType>元素本身
name 使用<complexType>元素新定義的數據類型的名稱
abstract 是否為抽象的數據類型,如為抽象的,則不能在XML文檔中直接使用這種數據類型
mixed

是否為混合類型,如果是混合類型,則允許同時出現字符數據和子元素

如果子元素是<simplexContent>,則不能使用該屬性

如果子元素是<complexContent>,則mixed屬性可以被<complexContet>元素的mixed屬性重寫

block 防止使用指定派生類型的復雜類型來替換當前定義的復雜類型
final 防止使用指定派生類型來派生新的類型
any attributes 指定non-schema命名空間的任何其他屬性

(2)復雜數據類型只能用於元素而不能用於屬性,進一步,可以根據能應用的元素對數據類型進行分類:

  • 簡單數據類型:相應的元素內容是簡單類型值,並且元素不能有屬性,使用<simpleType>定義
  • 含簡單內容的復雜數據類型:相應的元素內容是簡單類型值,但元素具有屬性,使用<complexType> <simpleContent> </simpleContent> </complexType>定義,其中<simpleContent>元素的語法如下:
<simpleContent id=ID any-attributes>
  (annotation?,(restriction|extension))
</simpleContent>
  • 含復雜內容的復雜數據類型:相應的元素可以是包含子元素的元素,空元素或包含混合內容的元素,而不管元素是否有屬性,使用<complexType> <complexContent> </complexContent> </complexType>定義,其中<complexContent>元素的語法如下:
<complexContent id=ID mixed=true|false any-attributes>
  (annotation?,(restriction|extension))
</complexContent>

(3)在根元素<schema>下定義的復雜數據類型為全局的,此時name屬性是必須的,否則為局部的。

(4)final屬性用於指定不能以那種方式派生新類型,可以取的值有#all,extension和restriction的自由組合,默認值為根元素<schema>的finalDefault屬性值。這個屬性其實和<simplexType>的final屬性類似,只是<simplexType>的final屬性取值可以是#all或restriction、list、union的自由組合。

(5)block屬性指定不能使用指定方式派生出來的類型來替換所定義的類型,可以取的值和final相同,默認值為根元素<schema>的blockDefault屬性值。

2、定義元素

(1)在定義復雜數據類型時,需要定義子元素和屬性,那么怎么定義元素呢?在XSD中,可以使用<element>元素來定義元素,其語法如下:

<element 
  id=ID
  name=NCName
  ref=QName
  type=QName
  substitutionGroup
=QName
  default=string
  fixed=string
  form=qualified|unqualified
  maxOccurs=nonNegativeInteger|unbounded
  minOccurs=nonNegativeInteger
  nillable=true|false
  abstract
=true|false
  block=(#all|extension、restriction和substitution的自由組合)
  final=(#all|extension和restriction的自由組合)
  any-attributes> (annotation?,((simpleType|complexType)?,(unique|key|keyref)*) </element>

其中element元素的各屬性如下表:

屬性 說明
id 唯一標識<element>元素
name 新定義元素的名稱,根元素<schema>下定義時為必須屬性
ref 對另一個元素的引用,可包含一個命名空間前綴
type 數據類型,可以是內建數據類型、simpleType或complexType定義的類型
substitutionGroup 可用來替代該元素的元素名稱,必須具有相同的類型或從其派生類型
default 默認值,元素內容是簡單類型或textOnly時使用
fixed 固定值,元素內容是簡單類型或textOnly時使用,默認值default和固定值fixed不能同時指定
form 是否通過命名空間前綴限定該元素,默認值為<schema>元素的elementFormDefault屬性值
maxOccurs 在父元素中出現的最大次數,非負整數或無限制(unbounded),默認值為1
minOccurs 在父元素中出現的最少次數,必須小於或等於maxOccurs,默認值為1
nillable 是否可以將顯示的零值分配給該元素,默認為false,如果為true,則在XML文檔中可以設定該元素的nil屬性為true
abstract 是否為抽象元素,如為抽象元素,則不能直接在XML文檔中使用
block 阻止使用指定派生方式的元素來替換當前元素
final 設置element元素上final屬性的默認值
any attributes 指定non-schema命名空間的任何其他屬性

其中父元素是根元素<schema>時,不能使用ref、form、maxOccurs、minOccurs等屬性,而substitutionGroup、final等屬性則只能使用在父元素為根元素的情況下。

(2)可以通過<group>元素將一組屬性定義在一起,然后在其它需要元素的地方用元素組的引用就可以了。語法如下:

<group 
  id=ID
  name=NCName
  ref=QName
  maxOccurs=nonNegativeInteger|unbounded
  minOccurs=nonNegativeInteger
  any-attributes> (annotation?,(all|choice|sequence)?) </group>

看一個例子:

<xs:group name="personGroup">
  <xs:sequence>
     <xs:element name="firstname" type="xs:string"/>
     <xs:element name="lastname" type="xs:string"/>
  </xs:sequence>
</xs:group>

<xs:element name="person" type="personType"/>

<xs:complexType name="personType">
  <xs:sequence>
    <xs:group ref="personGroup"/>
    <xs:element name="country" type="xs:string"/>
  </xs:sequence>
</xs:complexType>

這里涉及到了三種順序指示器,用於定義元素的順序:

  • all:子元素能以任意順序出現,但是每個子元素必須只出現一次,這個時候可以把minOccurs設置為0或1,並且只能把maxOccurs設置為1
  • choice:子元素是互斥的關系,只能出現其中之一
  • sequence:子元素必須按照指定的順序出現

(3)元素通配符

  在某些情況下,如果無法確定指定元素還需要包含哪些子元素、哪些屬性,這時候可使用通配符。XSD中使用<any>元素作為元素通配符,表示任何元素,即<any>元素出現的位置可以使用任何元素代替,其語法格式如下:

<any
  id=ID
  maxOccurs=nonNegativeInteger|unbounded
  minOccurs=nonNegativeInteger
  namespace=namespace
  processContents=lax|skip|strict
  any-attributes>
  (annotation?)
</any>

<any>元素的屬性:

屬性 說明 取值/取值類型 默認值
id 唯一標識該元素 ID類型  
maxOccurs 該元素最多可出現的次數 非負整數或unbounded 1
minOccurs 該元素最少可出現的次數 非負整數,必須小於maxOccurs 1
namespace 指定可代替該通配符的元素必須來自哪個空間
  • ##any:任意命名空間的元素
  • ##other:來自當前命名空間之外的其它任意命名空間的元素
  • ##local:無命名空間限定的元素
  • ##targetNamespace:當前命名空間的元素
  • 命名空間URI:指定命名空間的元素
  • 上面多個值的列表:值列表中的任意一個命名空間的元素
 
processContents 指定應用程序或XML處理器如何對替換元素進行驗證
  • strict:XML處理器必須獲得由namespace指定的命名空間對應的Schema,並驗證來自該命名空間的所有元素
  • lax:XML處理器嘗試獲取由namespace指定的命名空間對應的Schema,成功則驗證所有元素,否則也不報錯
  • skip:XML處理器不會獲取所需命名空間,也不會進行任何驗證
strict

(4)元素替換

XSD還提供了一種機制,允許使用一個元素替換另一個元素,如果想定義某個元素可替換另一個元素,可以為該元素增加substitutionGroup屬性,其值就是該元素想替換的元素的名字。使用元素替換需注意兩點:

  • 替換元素和被替換元素必須以全局元素的形式來聲明
  • 替換元素和被替換元素要么有相同的數據類型,要么替換元素類型是被替換元素類型的派生類型

另外,

  • 可以使用final屬性來阻止自己被指定派生類型替換
  • 可以使用block屬性來阻止指定派生類型的替換

3、定義屬性

  定義屬性和定義元素是完全統一的,只是定義屬性使用<attribute>元素,其語法格式如下:

<attribute 
  id=ID
  name=NCName
  ref=QName
  type=QName
  default=string
  fixed=string
  form=qualified|unqualified
  uese
=optional|prohibited|required
  any-attributes> (annotation?,(simpleType?)) </attribute>

(1)<attribute>元素的屬性基本和<element>元素相同,不同的是form屬性的默認值是根元素<schema>的attributeFormDefault屬性的值。另外,use屬性是<element>所沒有的,它表示怎么使用這個屬性,可以取的值有:

  • optional:屬性是可選的,並且可以具有指定數據類型的任意值
  • prohibited:不能使用屬性(既然不能使用,為何還要定義?主要是在派生新類型使用,用來刪除原類型的某個屬性)
  • required:必須的屬性,此時不能指定default和fixed

(2)在根元素<schema>下定義的屬性稱之為全局屬性,其它的屬性則可以通過<attribute>元素的ref屬性來引用全局屬性;也可以直接將<attribute>放在<complexType>元素內部定義屬性。

(3)類似<group>元素定義元素組,還可以使用<attributeGroup>元素定義屬性組,其語法格式如下:

<attributeGroup id=ID name=NCName ref=QName any-attributes>
 (annotation?,((attribute|attributeGroup)*,anyAttribute?))
</attributeGroup>

(4)屬性通配符

  類似於元素通配符,可以使用<anyAttribute>表示屬性通配符,其語法格式如下:

<anyAttribute
  id=ID
  namespace=namespace
  processContents=lax|skip|strict
  any-attributes>
(annotation?)
</anyAttribute>

其中屬性含義與元素通配符<any>相同。

4、再看看怎么派生復雜數據類型

  知道怎么定義元素和屬性之后,就可以進一步看怎么定義復雜數據類型了,總的來說,定義復雜數據類型需要弄清兩個問題:第一個問題是基類型的問題——定義復雜數據類型的基礎是哪個類型?第二個問題就是派生方式的問題——派生復雜數據類型可以使用限制<restriction>和擴展<extension>兩種方式。

(1)基類型

  • anyType類型:和DTD中的ANY類似,XSD中也有一個anyType類型,這種類型的元素沒有任何限制,可以包含子元素,可以包含字符串內容,還可以添加任何屬性(但這些屬性需要在XSD文件中定義過),anyType類型是所有簡單類型和所有復雜類型的基類型,通常用於派生新的類型,而不是直接用來定義元素。
  • 簡單類型
  • 含簡單內容的復雜類型:元素內容是簡單類型值,但元素包括屬性
  • 空元素類型:用於定義內容為空或空字符串的元素,但是該元素可以接受屬性。定義空元素類型有兩種方式:
    • 擴展長度為0的字符串:如果該元素不需要包含屬性,那么直接使用長度為0的字符串類型定義該元素即可
    • 限制anyTye:限制anyType時不定義任何子元素,只定義所需屬性即可
<xs:simpleType name="emptyString">
  <xs:restriction base="xs:string">
     <xs:maxLength value="0"/>
  </xs:restriction>
</xs:simpleType>
<xs:element name="book">
  <xs:complexType>
    <xs:simpleContent>
       <!--以空字符串為基礎派生新的復雜類型-->
       <xs:extension base="emptyString">
         <!--添加一個屬性-->
         <xs:attribute name="name" type="xs:token"/>
       </xs:extension>
    </xs:simpleContent>
  </xs:complexType>
</xs:element>


<xs:element name="book2">
  <xs:complexType>
    <!--不指定子元素,即定義了一個空元素-->
    <!--添加一個屬性-->
    <xs:attribute nae="name" type="xs:token"/>
  </xs:complexType>
</xs:element>
  • 包含子元素的類型
  • 混合內容類型

(2)派生方式

  • 限制<restriction>
  • 擴展<extension> 

下面是我從這基類型和派生方式兩個維度統計的一個列表:

基類型 派生方式 定義時使用的XSD元素 說明
anyType類型 限制

<complexType><complexContent><restriction>

因為anyType只能限制,不能擴展,所以可以省略<complexContent><restriction>元素,

而直接在<complexType>內部使用<all>|<choice>|<sequence>等元素

擴展

 

anyType類型已經沒有任何限制了,所以也就不需要再擴展了

簡單類型  限制

<simpleType>

限制簡單類型最終結果也是一個簡單類型,因此使用<simpleType>元素
擴展

<complexType><simpleContent><extension>

可以通過添加屬性或屬性組派生復雜數據類型
包含簡單內容的復雜類型  限制

<complexType><simpleContent><restriction>

  • 為元素內容增加進一步的約束
  • 為元素的屬性類型增加進一步的約束
  • 刪除某些屬性
擴展

<complexType><simpleContent><extension>

 添加屬性
空元素類型 限制

<complexType><complexContent><restriction>

  • 對指定屬性增加進一步的約束
  • 刪除某個屬性
擴展

<complexType><complexContent><extension>

  • 為原有類型增加屬性:派生出來的新類型依然是空元素類型
  • 為原有類型增加子元素:派生出來的新類型將是包含子元素的類型
  • 為原有類型增加mixed="true":派生出來的新類型將是混合內容類型
包含子元素的類型 限制 

<complexType><complexContent><restriction>

  • 可以對指定屬性的類型增加進一步約束
  • 可以對指定子元素的類型增加進一步約束
  • 可以刪除指定屬性
  • 可以刪除指定元素
擴展

<complexType><complexContent><extension>

  • 為基類型增加新的子元素
  • 為基類型增加新的屬性
混合內容類型 限制

<complexType><complexContent><restriction>

 限制混合內容類型的方式和限制包含子元素的類型基本相同
擴展

<complexType><complexContent><extension>

 擴展混合內容類型的方式和擴展包含子元素的類型基本相同,但是必須保留mixed="true"

  派生類型的另外一種用法:

  假設在XSD中定義了元素<book>,其類型是book_type(包含一個name屬性),同時還定義了book_type的派生數據類型extended_book_type(在book_type基礎上添加就價格price屬性),這種情況下,在實際XML文檔中, 可以以如下兩種方式使用<book>元素:

<!--1。第一種方式,book元素實際類型為book_type類型-->
<book name="example1"/>

<!--2。第二種方式,使用xsi:type指定book元素的實際類型為extended_book_type,這里xsi為命名空間http://www.w3.org/2001/XMLSchema-instance對應的前綴-->
<book name="example2" xsi:type="extended_book_type" price="100"/>

5、一致性約束

  定義元素還可以指定3種類型的約束:

  • key約束:相當於DB里面的主鍵約束,要求指定內容必須存在而且唯一
  • keyref約束:相當於DB里面的外鍵約束,要求指定內容的值必須使用refer屬性引用另一個key約束或unique約束
  • unique約束:相當於DB里面的唯一約束,要求指定內容必須唯一,但可以不存在

這3個一致性約束都只能在<element>元素內定義,且只能在<element>元素的最后面定義。

  在DB中定義約束時,不僅需要指定使用哪類約束,還需要定義應該對哪些字段應用約束,在XSD中定義一致性約束也完全類似,也需要指定該約束將對哪些部分起作用,因此需要在約束內使用如下兩個子元素:

  • <selector>:需指定一個xpath屬性,其值是一個XPath表達式,用來確定一個元素范圍,在一次約束定義中,<selector>必須且只能出現一次
  • <field>:需要指定一個xpath屬性,其值是一個XPath表達式,在一次約束定義中,<field>至少要出現一次,也可以出現多次

這兩個元素的含義是:在<selector>元素的XPath表達式表示的范圍內,<field>元素的XPath表達式所表示的內容必須遵守一致性約束,如果有多個<field>元素,則它們的XPath表達式內容的組合必須遵守一致性約束,當XPath表達式所表示的內容無需遵守,這個概念相當於DB中的多列組合約束。

  看下例子:

<xs:element name="book-list">
  <xs:complexType>
     <xs:sequence>
        <xs:element ref="book" maxOccurs="unbounded"/>
     </xs:sequence>
  </xs:complexType>
  <!--定義key約束,只在book-list之內有效-->
  <xs:key name="nameKey">
    <!--在當前上下文的book元素之內(即book-list/book之內)-->
    <xs:selector xpath="book"/>
    <!--指定book-list/book元素之內的name元素的值必須存在且唯一-->
    <xs:field xpath="name"/>
  </xs:key>
</xs:element>

6、定義符號

最后看一下和DTD中對應的定義符號的用法,在XSD中使用<notation>元素定義符號,用來標識XML文檔中的外部數據,該元素可接受的屬性有:

  • id:指定該符號的唯一標識,通常無需指定
  • name:指定該符號的名稱,是一個必填屬性,而且該名稱在整個XSD內必須是唯一的
  • public:指定該符號所標識數據的外部格式或對應處理程序,必填屬性,相當於DTD中<!NOTATION>中PUBLIC的作用
  • system:指定該符號所標識數據的外部格式或對應處理程序,可選屬性,相當於DTD中<!NOTATION>中SYSTEM的作用

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM