1. 程式人生 > >在XML中使用Schema

在XML中使用Schema

使用Schema知識總結

Schema概述

  1. XML Schema即模式。
    文件通常以單獨的檔案形式存在,副檔名為.xsd。
  2. 與DTD相比Schema的優勢如下:
    XML Schema可以針對未來的需求進行擴充套件
    Schema更加完善、功能也更強大
    XML Schema是基於XML進行編寫
    XML Schema支援資料型別
    XML Schema支援名稱空間
  3. XML Schema建議規範中有兩個基礎的名稱空間:
    一個是用於Schema文件的Schema URI,即http://www.w3.org/2001/XMLSchema。通常使用xs來代表該名稱空間。
    另一個用於XML文件,即http://www.w3.org/2001/XMLSchema-instance,通常使用xsi來代表該名稱空間。
  4. 例項程式碼:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
	<xs:element name="school">
		<xs:complexType>
			<xs:sequence>
				<xs:element name="name" type="xs:string"/>
				<xs:element name="major" type="xs:string" minOccurs="1" maxOccurs="unbounded"/>
			</xs:sequence> 
		</xs:complexType>
	</xs:element>
</xs:schema>

Schema的引用方法

  1. 當XML引入XML Schema時,根據XML文件的元素是否屬於某個特定名稱空間的,可以按照如下兩種方式引入:
    不屬於特定的名稱空間,通過屬性xsi:noNamespaceSchemaLocation引入
    屬於某個特定的名稱空間,通過屬性xsi:schemaLocation引入

  2. 通過xsi:noNamespaceSchemaLocation引入
    如果被引入的Schema檔案需要約束XML檔案中不屬於任何特定的名稱空間元素,使用xsi:noNamespaceSchemaLocation屬性引入。
    具體語法如下:
    <根元素名稱 xmlns:xsi=“

    http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=“XML Schema”>
    xsi:noNamespaceSchemaLocation :屬性值為一個Schema檔案的URI。該屬性值只能是一個Schema檔案URI,即只能使用一個Schema檔案。

  3. 通過xsi:schemaLocation引入
    如果被引入的Schema檔案需要約束XML檔案中屬於某個任何特定的名稱空間元素,則通過xsi:schemaLocation屬性引入。具體語法如下:
    <根元素名稱 [xmlns:命名空間別名=“名稱空間URI” ]+ xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance
    xsi:schemaLocation="[名稱空間URI Schema檔案路徑]+">
    xsi:schemaLocation="[名稱空間URI Schema檔案路徑]+" :該屬性值比較靈活,可以同時引入多個Schema檔案。每一個Schema的引入都需要一個名稱空間URI和Schema檔案路徑,名稱空間URI和Schema檔案路徑中間使用空格間隔。

  4. 示例程式碼:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs = "http://www.w3.org/2001/XMLSchema"
	targetNamespace="http://www.dlut.edu.cn/xml" xmlns:c="http:www.dlut.edu.cn/xml">
	<xs:element name="collage">
		<xs:complexType>
			<xs:sequence>
				<xs:element ref="c:name"></xs:element>
				<xs:element ref="c:major" minOccurs="1" maxOccurs="unbounded"></xs:element>
			</xs:sequence>
		</xs:complexType>
	</xs:element>
	<xs:element name="name" type="xs:string"/>
	<xs:element name="major" type="xs:string"/>
</xs:schema>

Schema的語法結構

  1. 元素
    語法1:語法1:
    <element name=”元素名稱” type=”資料型別” [default=”預設值”] [minOccurs=”最少出現的次數” ] [maxOccurs=”最多出現的次數”]/>
    語法2:
    <element name=”元素名稱” [default=”預設值”] [minOccurs=”最少出現的次數” ] [maxOccurs=”最多出現的次數”]> Element type </element>
    語法3:
    <element ref=”引用元素名稱” [default=”預設值”] [minOccurs=”最少出現的次數” ] [maxOccurs=”最多出現的次數”]/>

示例:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qulified"
	attributeFormDefault="unqualified">
	<xs:element name="root">
		<xs:complexType>
			<xs:sequence>
				<xs:element name="sub1" type="xs:string" default="sub1content"/>
				<xs:element ref="sub2" minOccurs="1" maxOccurs="unbounded"/>
			</xs:sequence>
		</xs:complexType>
	</xs:element>
	<xs:element name="sub2" type="xs:string"></xs:element>
</xs:schema>
  1. 屬性
    定義屬性的語法格式如下所示:
    語法1:
    <xs:attribute name=“屬性名” type=“屬性型別” [default=“預設值”]| [fixed=“固定值”] >
    </xs:attribute>
    語法2:
    <xs:attribute ref=“屬性名” >
    </xs:attribute>
    屬性說明如下:
    name:XML元素的屬性名
    type:屬性的資料型別,可以使用內建資料型別或simpleType元素定義的資料型別。
    default:屬性的預設值,該屬性可選(不能與fixed屬性同時存在)
    fixed:屬性的固定值,如果該屬性存在則屬性的值固定。(不能與default屬性同時存在)
    ref:引用已經定義好的屬性名稱

  2. 註釋
    註釋的具體方法包括兩種:

    1. XML語法中的註釋<!-- 被註釋的內容-->
    2. 通過標記<annotation>來增加註釋,該方式具有更好的可讀性。
      <annotation.../>:通常放在各種Schema元件定義的開始部分,用於說明該Schema元件的作用。內部可以出現多個<documentation.../><appinfo.../>而且順序和出現次數沒有限制。
      <documentation> :該子元素的註釋主要供人來閱讀使用。
      <appinfo>:該子元素的註釋主要供其它程式來使用。

Schema的資料型別

  1. Schema的資料型別可以根據該元素內容劃分為簡單型別和複雜型別。
    簡單型別是指元素的內容中即不包括子元素也不包括屬性。
    複雜型別是指元素的內容中包括子元素、包括屬性或既包括子元素也包括屬性。
    schema資料型別

  2. Schema允許使用者根據實際需要擴充套件資料型別。因此按照擴充套件方式可以分為:
    內建資料型別。
    使用者自定義型別。

    內建資料型別是被預先定義好的,這些資料型別全部位於名稱空間http://www.w3.org/2001/XMLSchema下,所有的內建資料型別都是簡單型別。
    內建資料型別

  3. 內建型別分為3個部分:
    任意型別
    內建基本資料型別
    內建擴充套件資料型別進行

    • 任意型別包括兩種:
      anyType:表示該元素為任意型別,與DTD的ANY類似。此型別對於元素的內容沒有任何約束。
      anysimpletype:表示該元素為任意簡單型別。即定義為該型別的元素除不能包含子元素和屬性外,沒有任何其它的約束。
    • 內建基本資料型別:
資料型別 描述
string 表示字串,原封不動地保留所有空白
QName 表示一個包含XML名稱空間在內的名稱
decimal 表示標定精度的數字
float 表示單精度32位浮點數,支援科學計數法
double 表示雙精度的64位浮點數,支援科學計數法
hexBinary 表示十六進位制數
date 表示日期YYYY-MM-DD格式的時間
gYearMonth 表示年月YYYY-MM格式的時間
gYear 表示年YYYY格式的時間
gMonthDay 表示月日- -MM-DD格式的時間
getDay 表示日期-DD格式的時間
getMonth 表示月份-MM格式的時間
duration 表示持續時間PnYnMnDTnHnMnS,P起始定界符,T分隔符,s前面的n可以是小數
dateTime 表示特定的時間YYYY-MM-DDThh:mm:ss:sss,sss表示毫秒數
time 表示特定的時間hh:mm:ss:sss,sss表示毫秒數
boolean 布林型,只能接受true,false,0,1
anyURI 表示一個URI,用來定位檔案
base64Binary 表示任意base64編碼的二進位制數
hexBinary 表示任意16進位制編碼的二進位制數
  1. 使用者自定義型別
    使用者自定義型別還可以按照複雜程度劃分,分為簡單型別和複雜型別。
    自定義簡單資料型別
    自定義簡單型別是在內建資料型別的基礎上通過限制、列表和聯合中一種或幾種方式形成的新資料型別。簡單資料型別的定義語法:
    <xs:simpleType [name=“自定義型別名稱”]>
    [限制、列表、聯合一種或幾種方式]
    </xs:simpleType>
    name屬性:自定義的資料型別名稱。當定義的簡單資料型別為全域性資料型別,即直接在標記中定義,必須寫出該屬性。如果為區域性資料型別,則沒有該屬性。
  • Restriction
    限制
    如果通過限制方式產生自定義型別,需要使用的標記為restriction。語法格式如下:
    <xs:simpleType [name=“自定義型別名稱”]>
    <xs:restriction base=“基型別” >
      [約束特徵]+
    </xs:restriction>
    </xs:simpleType>
    例項程式碼:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
	<xs:element name="resctrictionValue">
		<xs:complexType>
			<xs:sequence>
				<xs:element ref="firstValue"/>
				<xs:element ref="secondValue"/>
				<xs:element ref="thirdValue"/>
				<xs:element ref="forthValue"/>
				<xs:element ref="fifthValue"/>
				<xs:element ref="sixValue"/>
				<xs:element ref="sevenValue"/>
			</xs:sequence>
		</xs:complexType>
	</xs:element>
	<xs:element name="firstValue">
		<xs:simpleType>
			<xs:restriction base="xs:normalizedString">
				<xs:length value="5"/>
				<xs:whiteSpace value="collapse"/>
			</xs:restriction>
		</xs:simpleType>
	</xs:element>
	<xs:element name="secondValue">
		<xs:simpleType>
			<xs:restriction base="xs:decimal">
				<xs:minExclusive value="1"/>
				<xs:maxExclusive value="100"/>
			</xs:restriction>
		</xs:simpleType>
	</xs:element>
	<xs:element name="thirdValue">
		<xs:simpleType>
			<xs:restriction base="xs:decimal">
				<xs:minInclusive value="1"/>
				<xs:maxInclusive value="100"/>
			</xs:restriction>
		</xs:simpleType>
	</xs:element>
	<xs:element name="forthValue">
		<xs:simpleType>
			<xs:restriction base="xs:decimal">
				<xs:totalDigits value="5"/>
				<xs:fractionDigits value="1"/>
			</xs:restriction>
		</xs:simpleType>
	</xs:element>
	<xs:element name="fifthValue">
		<xs:simpleType>
			<xs:restriction base="xs:string">
				<xs:minLength value="3"/>
				<xs:maxLength value="5"/>
			</xs:restriction>
		</xs:simpleType>
	</xs:element>
	<xs:element name="sixValue">
		<xs:simpleType>
			<xs:restriction base="xs:string">
				<xs:enumeration value="123T"/>
				<xs:enumeration value="456T"/>
			</xs:restriction>
		</xs:simpleType>
	</xs:element>
	<xs:element name="sevenValue" type="mytype"/>
	<xs:simpleType name="mytype">
		<xs:restriction base="xs:string">
			<xs:pattern value="T\w{1,5}."/>
		</xs:restriction>
	</xs:simpleType>
</xs:schema>

  • List
    列表
    Schema中定義列表型別使用<list…/>元素,它可以由單個數據型別擴展出列表型別,因此使用該元素時必須指出列表元素的型別,為元素指定列表元素型別有兩種方式:
    為<list…/>元素的itemType屬性指定列表元素的資料型別:

     <xs:simpleType [name="自定義型別名稱"]>
      		<xs:list itemType="列表元素型別" ></xs:list >
      </xs:simpleType>
    

為<list…/>元素增加<simpleType…/>子元素來指定列表元素的資料型別:

<xs:simpleType [name="自定義型別名稱"]>
		<xs:list>
           		<simpleType.../>
           </xs:list >
</xs:simpleType>
  • Union
    Schema使用<union…/>元素將多個簡單型別聯合成新的型別,為<union…/>元素指定簡單型別有兩種方式:
    為<union…/>元素的memeberTypes屬性指定一個或多個簡單型別,多個簡單型別之間以空格隔開。

    <xs:simpleType [name=“自定義型別名稱”]>
    <xs:union memeberTypes="[列表元素型別]+" ></xs:union>
    </xs:simpleType>

為<union…/>元素增加一個或多個<simpleType…/>子元素,每個<simpleType…/>子元素指定一個簡單型別。

<xs:simpleType [name="自定義型別名稱"]>
		<xs:union>
           		 [<simpleType.../>]+
           </xs:union>
</xs:simpleType>

自定義複雜型別
複雜型別所約束的內容可能包含屬性、子元素或同時包含子元素和屬性。複雜元素也有可能在包含子元素的同時還包含字元內容,這樣的元素被稱為混合內容。定義複雜元素的語法格式如下所示:

<xs:complexType [name=”自定義元素名稱”] [mixed=”true|false”]>
	[順序、選擇、無序、簡單內容、複雜內容]+
</xs:complexType>

name屬性:自定義的資料型別名稱。當定義的簡單資料型別為全域性資料型別,即直接在標記中定義,必須寫出該屬性。如果為區域性資料型別,則沒有該屬性。
mixed屬性:如果mixed屬性值設定為true,則表示該元素的內容為混合內容。該屬性預設值為false。

  • 順序xs:sequence
    使用該元素定義的資料型別用於設定子元素的順序,表示該元素的子元素是有序的。使用該元素的語法格式如下:

    <xs:complexType name=“mytype”>
    <xs:sequence [maxOccurs=“最多出現的次數”] [minOccurs=“最少出現的次數”]>
    [<xs:element name=“test” type=“xs:string” minOccurs=“最少出現的次數” maxOccurs=“最多出現的次數” ></xs:element>]+
    </xs:sequence>
    </xs:complexType>

maxOccurs屬性:最多出現的次數,通常為一個固定的數字。可以作為sequence的屬性,也可以作為element的屬性。當最多次數沒有限制時該值為unbounded。
minOccurs屬性:最少出現的次數,為一個固定的數字。可以作為sequence的屬性,也可以作為element的屬性。

  • 選擇xs:choice
    使用該元素定義的資料型別用於設定子元素的選擇關係,表示該元素的子元素可以根據實際需要從子元素中選擇一個使用。使用該元素的語法格式如下

    <xs:complexType name=“mytype”>
    <xs:choice [maxOccurs=“最多出現的次數”] [minOccurs=“最少出現的次數”]>
    [<xs:element name=“test” type=“xs:string” minOccurs=“最少出現的次數” maxOccurs=“最多出現的次數” ></xs:element>]+
    </xs:choice>
    </xs:complexType>

maxOccurs屬性:最多出現的次數,通常為一個固定的數字。可以作為choice 的屬性,也可以作為element的屬性。當最多次數沒有限制時該值為unbounded。
minOccurs屬性:最少出現的次數,為一個固定的數字。可以作為choice 的屬性,也可以作為element的屬性。

  • 無序xs:all
    使用xs:all元素定義的資料型別用於設定子元素是沒有順序的,表示該元素的子元素是無序的。但是該元素設定中有一些約束子元素數量不能被設定,只能是一個;也不能增加屬性;不能與xs:sequencexs:choice同時出現;只能作為或的頂級元素。使用該元素的語法格式如下:

    <xs:complexType name=“mytype”>
    <xs:all minOccurs=“0|1” maxOccurs=“1”>
    [<xs:element minOccurs=“0|1” maxOccurs=“0|1” default=""></xs:element>]+
      </xs:all>
    </xs:complexType>

maxOccurs屬性:最多出現的次數,通常為一個固定的數字。可以作為all的屬性,此時該值只能為1,也可以作為element的屬性,此時該值可以為0或1。
minOccurs屬性:最少出現的次數,為一個固定的數字。可以作為all的屬性,也可以作為element的屬性,該值只能為0或1。

  • 簡單內容<simpleContent/>
    如果元素只包含屬性,不包含子元素,則可以使用該元素定義元素內容。具體的內容方式包括在基型別上擴充套件和限制兩種方式:
    限制<xs:特徵元素,對當前的基型別進行限制。restriction base=“基型別”></xs:restriction> :基型別必須為一個僅包含屬性的簡單型別。該標記中可以巢狀基於restriction元素內的所有
    擴充套件<xs:extension base=“基型別”></xs:extension> :基型別必須為一個簡單型別,該元素內可以包含屬性的定義,在簡單內容的基礎上增加屬性

  • 複雜內容<complexContent/>
    使用該元素有點類似於程式語言的繼承,相當於在某一基型別的基礎上進行擴充套件或限制。如果元素包含子元素(是否包含屬性不限制),則可以使用該元素對元素內容進行定義。
    限制<xs:restriction base="基型別"></xs:restriction>:基型別為一個已經定義好的複雜資料型別,在基型別的基礎上增加限制。
    擴充套件<xs:extension base="基型別"></xs:extension>:基型別為一個已經定義好的複雜資料型別。在基型別的基礎上擴充套件,可以既可以增加子元素,也可以增加屬性。

Schema元素替換

  • XML Schema提供了一種機制叫置換組。當元素定義為全域性元素時,允許使用substitutionGroup屬性,該屬性的值為預先定義好的元素。包含當前屬性的元素允許替換被指定的預先定義好的元素。substitutionGroup屬性指定的元素被成為被替換元素,也叫頭元素(Head Element),包含substitutionGroup屬性的元素被稱為替換元素。需要注意的是:
    替換元素與頭元素(被替換元素)都必須是全域性元素,必須作為全域性元素宣告。
    替換元素與頭元素必須具有相同的資料型別,或者替換元素的型別是從非替換元素派生出來的。
    當定義了替換元素之後,並非意味著不能使用頭元素,它只是提供了一個允許元素可替換使用的機制。

  • 當一個元素被宣告為“abstract”時,那麼該元素為抽象元素。
    當一個型別被宣告為“abstract”時,那麼該型別為抽象型別。

  • 例項程式碼:

<xs:element name="abstractElement" type="xs:string" abstract="true"/>
	<xs:element name="sub1Eelement" type="xs:string" substitutionGroup="abstractElement"/>

<xs:complexType name="abstractType" abstract="true">
		<xs:sequence>
			<xs:element name="sub1" type="xs:string"></xs:element>
			<xs:element name="sub2" type="xs:string"></xs:element>
		</xs:sequence>
	</xs:complexType>
	<!--自定義複雜型別,該型別擴充套件自抽象型別abstractType-->
	<xs:complexType name="noramlType">
		<xs:complexContent>
			<xs:extension base="abstractType">
				<xs:attribute name="id" type="xs:string"></xs:attribute>
			</xs:extension>
		</xs:complexContent>
	</xs:complexType>
	<!--root元素指定為抽象型別abstractType-->
	<xs:element name="root" type="abstractType"/>

限制替換元素和限制派生型別

與抽象元素相反的是限制替換元素,當元素的定義包含final型別時,該元素為限制替換元素。根據final屬性值指定的限制方式包括:
#all:阻止以任何方式替換當前元素
extension:阻止以當前元素派生擴充套件方式型別元素替換當前元素
restriction:阻止以當前元素派生限制方式型別元素替換當前元素
extension和restriction:阻止同時以當前元素派生擴充套件方式型別和當前元素派生限制方式型別元素替換當前元素

<!-- 定義元素element1,該元素沒有任何替換元素 -->
<xs:element name="element1"  type="xs:string" final="#all"></xs:element>
<!-- 定義元素element2,該元素的替換元素型別不能通過擴充套件方式派生 -->
<xs:element name="element2" final="extension" type="rootType"></xs:element>
<xs:complexType name="rootType">
	<xs:sequence>
		<xs:element name="sub1Elem" type="xs:string"></xs:element>
		<xs:element name="sub2Elem" type="xs:string"></xs:element>
	</xs:sequence>
</xs:complexType>
<xs:complexType name="rootTypeRestiction">
	<xs:complexContent>
		<xs:restriction base="rootType">
			<xs:sequence>
				<xs:element name="sub1Elem" type="xs:string"></xs:elment>
				<xs:element name="sub2Elem" type="xs:string" fixed="sub2Elem"></xs:element>
	</xs:sequence>
	</xs:restriction>
</xs:complexContent>
</xs:complexType>
<xs:element name="element2Subst" type="rootTypeRestriction" substitutionGroup="element2"></xs:element>
<!-- 定義元素element3,該元素的替換元素型別不能通過限制方式派生 -->
<xs:element name="element2" final="restriction" type="rootType">
<xs:element name="element3Subst" type="rootTypeExtension" substitutionGroup="element3"></xs:element>

當自定義複雜型別包含final屬性時,表示該型別為限制派生型別。final屬性值指定限制的方式:
#all:阻止以任何方式派生
extension:阻止以擴充套件方式派生
restriction:阻止以限制方式派生

<xs:complexType name="base1Type" final="restriction"></xs:complexType>
<xs:complexType name="base1subType>
	<xs:complexContent>
		<!-- 通過擴充套件方式繼承base1Type -->
		<xs:extension base="base1Type">
			<xs:attribute name="id" type="xs:string"/>
		</xs:extension>
	</xs:complexContent>
</xs:complexType>
  • 限制替換型別
    限制替換還可以對某個特定複雜型別進行約束,此時複雜型別的定義中元素使用block屬性。當某個特定型別增加限制時,表示使用該型別的元素被替換時,應該遵循型別中的限制。具體的限制方式依據block的屬性值,具體指定限制的方式包括:
    #all:阻止替換該型別的元素
    extension:阻止擴充套件方式型別的元素替換該型別的元素
    restriction:阻止限制方式型別的元素替換該型別的元素

  • 元素和屬性的約束
    key、unique和keyref標記的含義:
    key約束:要求所約束的內容必須存在並保證唯一性;
    unique約束:要求內容必須唯一,但可以不存在;
    keyref約束:要求該內容必須引用一個key約束或unique約束的值。

Schema的複用

在一個文件中引入其它Schema文件,具體標記包括:
include
redefine
import

  • 使用include元素將另一份Schema包含到當前的Schema中要求如下:被包含的Schema檔案可以不屬於任何名稱空間,但如果包含名稱空間,該名稱空間必須與包含檔案的名稱空間保持一致。使用include元素的語法格式為:
    <include schemaLocation=”被包含的Schema的檔案”/>
    被包含檔案不屬於任何名稱空間
    包含檔案如果也不屬於任何名稱空間
    包含檔案如果屬於特定的名稱空間,則被包含檔案與包含檔案保持相同的名稱空間
    被包含檔案定義名稱空間
    當被複用的Schema檔案位於特定的名稱空間下時,包含檔案必須與被包含檔案保持相同的名稱空間才能實現複用。

  • redefine元素可以實現Schema的複用。可以把redefine元素當成include的增強版,redefine包含Schema檔案還允許重新定義被包含的Schema元件。語法格式為:
    <redefine schemaLocation=”被包含的Schema的檔案”/>
    需要注意:
    重定義的元件必須是Schema裡已有的元件;
    重定義的元件只能對被包含在Schema裡已有的元件增加限制或增加擴充套件;
    如果採用增加限制的方式來重定義原有的元件,則<restriction…/>元素裡所包含的約束不能違反原型別已有的約束。

  • 以上的include和redefine元素在複用時,都要求Schema位於相同的名稱空間。如果一個Schema想要複用的Schema檔案位於不同的名稱空間下,應該如何處理呢?<import…/>元素專門用於複用不同名稱空間的。
    使用<import…/>元素匯入另一份Schema,要求被匯入的Schema檔案必須與當前檔案定義不同的名稱空間。使用該元素的語法:
    <import schemaLocation=”被包含的Schema的檔案” [namespace=”被包含的Schema的檔案的名稱空間”]/>

  • 空元素的定義方法具體包括兩種:
    minOccurs=“0” 元素:如果是為空值的複雜型別,並且希望它佔用最小的空間,則使用 minOccurs=“0” 元素;
    nillable=“true” 元素:如果空值必須有佔位符(例如當其在陣列中出現時),則使用 nillable=“true” 元素。注意nillabe屬性值只能為true或false,用於指定是否可以將顯示的零值分配給該元素,該屬性只對元素內容有效,而對元素屬性無效。屬性的預設值為false。