2006
年
8
月
23
日
星期三
XSD
淺學筆記
?
簡單明快的
XSD
的入門筆記,希望能讓你和我一樣,用半天時間步入第一道門檻。
這一片記錄基礎知識,第二篇會是些進階知識和總結,然后你就可以寫出自己的第一個
XSD
文檔,并用來驗證一個
XML
文檔了。
XSD
是什么
?
一個
xml schema
是用來描述
xml
文檔結構的,而
XSD
是
xml schema definition
,
是繼
DTD
后的基于
xml
的
schema
語言,比起
DTD
,它有更好的擴展性,增加了功能,更重要的是,它本身就是以
xml
來寫的,而不需要象
DTD
那樣重新學一門語言。同時也可以利用所有對
xml
有效的便利。
那么為什么要有
schema
呢,
xml
的
well-formed
是不足夠的,一個語法上合法的
xml
仍然可能有錯誤,而這些錯誤可能導致嚴重的應用后果。
?
基礎概念
第一印象
??????
以下是一份
xml
文檔
<?xml version="1.0"?>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
?
而它對應的一份
xsd
會是這樣的:
?
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.w3schools.com"
xmlns="http://www.w3schools.com"
elementFormDefault="qualified">
<xs:element name="note">
??? <xs:complexType>
????? <xs:sequence>
?????? <xs:element name="to" type="xs:string"/>
?????? <xs:element name="from" type="xs:string"/>
?????? <xs:element name="heading" type="xs:string"/>
?????? <xs:element name="body" type="xs:string"/>
????? </xs:sequence>
??? </xs:complexType>
</xs:element>
</xs:schema>
?
簡單元素:
簡單元素是不包含其他元素和屬性的元素。
定義簡單元素的語法為:
<xs:element name="xxx" type="yyy"/>
常用的內建類型有:
xs:string
xs:decimal
xs:integer
xs:boolean
xs:date
xs:time
可以通過
default
屬性和
fixed
屬性來修飾。
<xs:element name="color" type="xs:string" default="red"/>
<xs:element name="color" type="xs:string" fixed="red"/>
?
屬性:
只有復合元素可以有屬性,但屬性本身總是被定義為簡單類型的。
<xs:attribute name="xxx" type="yyy"/>
除了和簡單元素的定義一樣可以用
default
和
fixed
來作為屬性之外,還可以用
use
屬性,如果把
use
屬性指定為“
required
”,就說明這個屬性在
xml
文檔中是必須指明的,默認情況下屬性的使用是可選的。
?
限制
當一個元素或者屬性定義了類型(
type
),
就可以用
restriction
來限制這個類型,
restriction
又叫
facet
,可以為類型增添更多的細節要求。當
xml
文檔中對應的元素值違反了這個
restriction
就不能通過檢驗。限制是
XSD
里比較常用的內容,我們會看大量的例子。
?
對數值大小的限制:(只能取
0
到
120
的閉區間)
<xs:element name="age">
<xs:simpleType>
? <xs:restriction base="xs:integer">
??? <xs:minInclusive value="0"/>
??? <xs:maxInclusive value="120"/>
? </xs:restriction>
</xs:simpleType>
</xs:element>
?
將值限制在一組既定值內:(類似于枚舉
enumeration
)
<xs:element name="car">
<xs:simpleType>
? <xs:restriction base="xs:string">
??? <xs:enumeration value="Audi"/>
??? <xs:enumeration value="Golf"/>
??? <xs:enumeration value="BMW"/>
? </xs:restriction>
</xs:simpleType>
</xs:element>
?
限制一定范圍的值:(只能取小寫的
26
個字母)
<xs:element name="letter">
<xs:simpleType>
? <xs:restriction base="xs:string">
??? <xs:pattern value="[a-z]"/>
? </xs:restriction>
</xs:simpleType>
</xs:element>
?
(只能取長度為
3
的大寫字母組合)
<xs:element name="initials">
<xs:simpleType>
? <xs:restriction base="xs:string">
??? <xs:pattern value="[A-Z][A-Z][A-Z]"/>
? </xs:restriction>
</xs:simpleType>
</xs:element>
?
(只能取長度為
3
的字母,大小寫均可)
<xs:element name="initials">
<xs:simpleType>
? <xs:restriction base="xs:string">
??? <xs:pattern value="[a-zA-Z][a-zA-Z][a-zA-Z]"/>
? </xs:restriction>
</xs:simpleType>
</xs:element>
?
(只能取
xyz
中的一個)
<xs:element name="choice">
<xs:simpleType>
? <xs:restriction base="xs:string">
??? <xs:pattern value="[xyz]"/>
? </xs:restriction>
</xs:simpleType>
</xs:element>
?
(只能取長度為
5
的數字串)
<xs:element name="prodid">
<xs:simpleType>
? <xs:restriction base="xs:integer">
??? <xs:pattern value="[0-9][0-9][0-9][0-9][0-9]"/>
? </xs:restriction>
</xs:simpleType>
</xs:element>
?
(只能取任意長度的小寫字符串,長度可以為
0
)
<xs:element name="letter">
<xs:simpleType>
? <xs:restriction base="xs:string">
??? <xs:pattern value="([a-z])*"/>
? </xs:restriction>
</xs:simpleType>
</xs:element>
?
(有了上一個,你自然也會猜到這一個:只能取長度大于
0
的字符串)
<xs:element name="letter">
<xs:simpleType>
? <xs:restriction base="xs:string">
??? <xs:pattern value="([a-z][A-Z])+"/>
? </xs:restriction>
</xs:simpleType>
</xs:element>
?
(選取,其實和前面的枚舉式功效類似,只能取其一)
<xs:element name="gender">
<xs:simpleType>
? <xs:restriction base="xs:string">
??? <xs:pattern value="male|female"/>
? </xs:restriction>
</xs:simpleType>
</xs:element>
?
(特定長度的字符數字串,用作密碼最合適。)
<xs:element name="password">
<xs:simpleType>
? <xs:restriction base="xs:string">
??? <xs:pattern value="[a-zA-Z0-9]{8}"/>
? </xs:restriction>
</xs:simpleType>
</xs:element>
?
(如果不需要在
base
上加內容限制,也可以這樣來表達長度)
<xs:element name="password">
<xs:simpleType>
? <xs:restriction base="xs:string">
??? <xs:length value="8"/>
? </xs:restriction>
</xs:simpleType>
</xs:element>
(設定長度區間)
<xs:element name="password">
<xs:simpleType>
? <xs:restriction base="xs:string">
??? <xs:minLength value="5"/>
??? <xs:maxLength value="8"/>
? </xs:restriction>
</xs:simpleType>
</xs:element>
?
另外,在
xml
里,空白符的情況比較特別,不小心處理就得不到你要的真正效果。
?
(保留所有的空白符)
<xs:element name="address">
<xs:simpleType>
? <xs:restriction base="xs:string">
??? <xs:whiteSpace value="preserve"/>
? </xs:restriction>
</xs:simpleType>
</xs:element>
?
(
所有的回車,過行,制表符,長空白都被替換成相應長度的空格符
)
<xs:element name="address">
<xs:simpleType>
? <xs:restriction base="xs:string">
??? <xs:whiteSpace value="replace"/>
? </xs:restriction>
</xs:simpleType>
</xs:element>
(所有空白符都被變為單空格符,首尾空白都被去掉)
<xs:element name="address">
<xs:simpleType>
? <xs:restriction base="xs:string">
??? <xs:whiteSpace value="collapse"/>
? </xs:restriction>
</xs:simpleType>
</xs:element>
?
最后,上面說到的所有的限制,還可以以下面這種格式來寫,把
simpleType
加上名字,在元素中的
type
引用這個名字,好處就是它不再單獨屬于這個元素或者屬性的定義了,其他元素可以復用這個類型限制,類似于面向對象編程語言中的包裝與復用。
<xs:element name="car" type="carType"/>
<xs:simpleType name="carType">
? <xs:restriction base="xs:string">
??? <xs:enumeration value="Audi"/>
??? <xs:enumeration value="Golf"/>
??? <xs:enumeration value="BMW"/>
? </xs:restriction>
</xs:simpleType>
?
復合元素
復合元素的定義就和簡單元素的剛好相反了,就是包含其他元素或屬性的元素。
細分一下有四種:
空元素;
<product pid="1345"/>
?
只包含其他元素的;
<employee>
<firstname>John</firstname>
<lastname>Smith</lastname>
</employee>
?
只有文本內容的;
<food type="dessert">Ice cream</food>
?
?
同時包括文本內容和其他元素的。
<description>
It happened on <date lang="norwegian">03.03.99</date> ....
</description>
而這四個同時又都可以有屬性。
?
接下來我們一一詳細介紹。
<product prodid="1345" />
空元素的定義語法:
<xs:element name="product">
? <xs:complexType>
??? <xs:attribute name="prodid" type="xs:positiveInteger"/>
? </xs:complexType>
</xs:element>
?
?
<person>
<firstname>John</firstname>
<lastname>Smith</lastname>
</person>
包含其他元素的復合元素定義:
<xs:element name="person">
? <xs:complexType>
??? <xs:sequence>
????? <xs:element name="firstname" type="xs:string"/>
????? <xs:element name="lastname" type="xs:string"/>
??? </xs:sequence>
? </xs:complexType>
</xs:element>
用
xs:sequence
來定義這些元素必須按照這個次序出現,類似于
sequence
這樣的指示符還有幾個,稍后統一介紹。
?
定義一個只有文本內容和屬性的復合元素,我們需要用一個
simpleContent
標記,再用一個
restriction
或者
extension
來限制文本的內容
:
?
<xs:element name="somename">
? <xs:complexType>
??? <xs:simpleContent>
????? <xs:extension base="basetype">
??????? ....
??????? ....
????? </xs:extension>????
??? </xs:simpleContent>
? </xs:complexType>
</xs:element>
或:
<xs:element name="somename">
? <xs:complexType>
??? <xs:simpleContent>
????? <xs:restriction base="basetype">
??????? ....
??????? ....
????? </xs:restriction>????
??? </xs:simpleContent>
? </xs:complexType>
</xs:element>
例子:
<xs:element name="shoesize">
? <xs:complexType>
??? <xs:simpleContent>
????? <xs:extension base="xs:integer">
??????? <xs:attribute name="country" type="xs:string" />
????? </xs:extension>
??? </xs:simpleContent>
? </xs:complexType>
</xs:element>
注意
extension
的
integer
是限制
shoesize
的文本內容,而
attribute
的
string
是限制
attribute
本身的內容的。
對應這個復合模式的
xml
可以是:
<shoesize country="france">35</shoesize>
?
要描述混合的復合元素:
<letter>
Dear Mr.<name>John Smith</name>.
Your order <orderid>1032</orderid>
will be shipped on <shipdate>2001-07-13</shipdate>.
</letter>
就可以用:
<xs:element name="letter">
? <xs:complexType mixed="true">
??? <xs:sequence>
????? <xs:element name="name" type="xs:string"/>
????? <xs:element name="orderid" type="xs:positiveInteger"/>
????? <xs:element name="shipdate" type="xs:date"/>
??? </xs:sequence>
? </xs:complexType>
</xs:element>
只是在包含其他元素的同時指定
mixed
等于“
true
“,而
sequence
或其他指示符的使用依然有效。你的文本可以穿插于元素之間,但元素的出現次序仍受
sequence
的限制。
?
記得簡單元素里的復用嗎,這里同樣可以,在
complexType
標記里加上
name
屬性,就完成了分離和復用了,對上面所有的復合類型都是通用的。即使寫
xsd
,也要象
oop
語言那樣,通過復用來提高修改的效率,同時讓頁面看起來整潔清晰,至少,我是有著這樣的偏執的,呵呵。
?
指示符里有以下幾種:
順序指示符:
All
所有元素可以不分順序出現,但只能出現一次。
Choice
只有其中一個可以出現
Sequence
前面說過了,必須按順序出現。
上面的限制可以配合次數指示符加以進一步的限制:
maxOccurs
最多出現次數
minOccurs
最少出現次數
例如:
<xs:element name="person">
? <xs:complexType>
??? <xs:sequence>
?
???? <xs:element name="full_name" type="xs:string"/>
????? <xs:element name="child_name" type="xs:string"
????? maxOccurs="10" minOccurs="0"/>
??? </xs:sequence>
? </xs:complexType>
</xs:element>
注意用了
all
的時候,最大次數還是不能超過
1
,最小可以是
0
或
1
。
?
組指示符:
Group
元素組
attributeGroup
屬性組
通過例子來看看:
<xs:group name="persongroup">
? <xs:sequence>
??? <xs:element name="firstname" type="xs:string"/>
??? <xs:element name="lastname" type="xs:string"/>
??? <xs:element name="birthday" type="xs:date"/>
? </xs:sequence>
</xs:group>
定義了一組元素,
group
必須包含已經用順序指示符包含起來的元素。
定義后,別的地方可以用
ref
來引用:
<xs:complexType name="personinfo">
? <xs:sequence>
??? <xs:group ref="persongroup"/>
??? <xs:element name="country" type="xs:string"/>
? </xs:sequence>
</xs:complexType>
?
以下這兩個是對應的
attribute group
的用法:
<xs:attributeGroup name="personattrgroup">
? <xs:attribute name="firstname" type="xs:string"/>
? <xs:attribute name="lastname" type="xs:string"/>
? <xs:attribute name="birthday" type="xs:date"/>
</xs:attributeGroup>
?
<xs:element name="person">
? <xs:complexType>
??? <xs:attributeGroup ref="personattrgroup"/>
? </xs:complexType>
</xs:element>
?
這一篇到這里為止。
?
posted on 2006-08-23 18:25
Ye Yiliang 閱讀(1215)
評論(7) 編輯 收藏 所屬分類:
Java