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 阅读(1198)
评论(7) 编辑 收藏 所属分类:
Java