一、简介
XML Schema 语言也称作 XML Schema 定义(XML Schema Definition,XSD)。XML Schema 的作用是定义 XML 文档的合法构建模块,类似 DTD。
XML Schema:
- 定义可出现在文档中的元素
- 定义可出现在文档中的属性
- 定义哪个元素是子元素
- 定义子元素的次序
- 定义子元素的数目
- 定义元素是否为空,或者是否可包含文本
- 定义元素和属性的数据类型
- 定义元素和属性的默认值以及固定值
XML Schema 使用 XML 语法,因此有很多好处:
- 不必学习新的语言,了解XML即可
- 可使用 XML 编辑器来编辑 Schema 文件
- 可使用 XML 解析器来解析 Schema 文件
- 可通过 XML DOM 来处理 Schema
- 可通过 XSLT 来转换 Schema
如果对XML的命名空间不理解的可参考:XML学习笔记
1.1 XSD - <schema> 元素
<schema> 元素是每一个 XML Schema 的根元素:
<?xml version="1.0"?>
<xs:schema>
...
</xs:schema>
<schema> 元素可包含属性。一个 schema 声明往往看上去类似这样:
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.w3school.com.cn"
xmlns="http://www.w3school.com.cn"
elementFormDefault="qualified">
...
</xs:schema>
上面代码解释:
xmlns:xs="http://www.w3.org/2001/XMLSchema"
显示 schema 中用到的元素和数据类型来自命名空间 "http://www.w3.org/2001/XMLSchema"。同时它还规定了来自命名空间 "http://www.w3.org/2001/XMLSchema" 的元素和数据类型应该使用前缀 xs:
targetNamespace="http://www.w3school.com.cn"
显示被此 schema 定义的元素来自命名空间: "http://www.w3school.com.cn"。
xmlns="http://www.w3school.com.cn"
指出默认的命名空间是 "http://www.w3school.com.cn"。
elementFormDefault="qualified"
指出任何 XML 实例文档所使用的且在此 schema 中声明过的元素必须被命名空间限定。
1.2 在 XML 文档中引用 Schema
<?xml version="1.0"?>
<note xmlns="http://www.w3school.com.cn"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.w3school.com.cn note.xsd">
...
</note>
其中note只是这个XML文件的根元素。
上面代码解释:
xmlns="http://www.w3school.com.cn"
规定了默认命名空间的声明。此声明会告知 schema 验证器,在此 XML 文档中使用的所有元素都被声明于 "http://www.w3school.com.cn" 这个命名空间。
一旦您拥有了可用的 XML Schema 实例命名空间:
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
您就可以使用 schemaLocation 属性了。此属性有两个值。第一个值是需要使用的命名空间。第二个值是供命名空间使用的 XML schema 的位置:
xsi:schemaLocation="http://www.w3school.com.cn note.xsd"
XML和Schema的命名空间标签使用格式是相同的(这也是Schema相对与DTD的优势),但XML和Schema都有各自的独特的属性,这也是由他们不同的功能决定的,Schema主要给XML提供服务,所以会规定好targetNameSpace来声明命名空间的名字,而XML需要使用schema的服务,所以需要SchemaLocation来声明使用的命名空间。
二、Schema深入之简单的类型
XML Schema 拥有很多内建的数据类型:
- xs:string
- xs:decimal
- xs:integer
- xs:boolean
- xs:date
- xs:time
2.1 XSD 简易元素
XML Schema 可定义 XML 文件的元素。简易元素指那些只包含文本的元素,它不会包含任何其他的元素或属性。
定义简易元素的语法:
<xs:element name="xxx" type="yyy"/>
此处 xxx 指元素的名称,yyy 指元素的数据类型。
简易元素也可以设置默认值和固定值,通过default属性指定默认值,使用fixed属性指定固定值,示例如下:
简易元素定义:
<xs:element name="lastname" type="xs:string"/>
<xs:element name="age" type="xs:integer"/>
<xs:element name="dateborn" type="xs:date"/>
对应的XML 元素使用示例:
<lastname>Smith</lastname>
<age>28</age>
<dateborn>1980-03-27</dateborn>
2.2 XSD 属性
简易元素无法拥有属性。假如某个元素拥有属性,它就会被当作某种复合类型。但是属性本身总是作为简易类型被声明的。
定义属性的语法是:
<xs:attribute name="xxx" type="yyy"/>
在此处,xxx 指属性名称,yyy 则规定属性的数据类型。
同样属性也可以设置默认值和固定值,通过default属性指定默认值,使用fixed属性指定固定值
在缺省的情况下,属性是可选的。如需规定属性为必选,我们需要使用 "use" 属性:
<xs:attribute name="lang" type="xs:string" use="required"/>
2.3 XSD 限定 / Facets
当 XML 元素或属性拥有被定义的数据类型时,就会向元素或属性的内容添加限定。假如 XML 元素的类型是 "xs:date",而其包含的内容是类似 "Hello World" 的字符串,元素将不会(通过)验证。这是对简易元素/属性的基本限定。
限定(restriction)用于为 XML 元素或者属性定义可接受的值。对 XML 元素的限定被称为 facet。
如果使用限定,那么气type(类型)属性就不能使用内建的数据类型,这个时候我们就需要使用自定义类型了,其形式如下:
<xs:element name="...">
<xs:simpleType>
...
</xs:simpleType>
</xs:element>
但是有时候也会遇到下面的形式:
<xs:element name="..." type="typeName">
<xs:simpleType name="typeName">
...
</xs:simpleType>
</xs:element>
有什么区别吗?第一种形式中xs:element中没有指定type类型,因为它默认使用的就是其内部定义的类型。然而xs:simpleType并不是当前定义元素的组成部分,换句话说,其可以被其它xs:element所使用。这样只需要在xs:element标签的属性type中指定这个xs:simpleType的name值即可,这也就是第二种形式。
然后使用restriction 元素定义对simpleType等元素进行定义约束,restriction元素包含一个必选属性base,该属性规定在该 schema(或由指定的命名空间指示的其他 schema)中定义的内建数据类型、simpleType 或 complexType 元素的名称。形式如下:
<xs:element name="...">
<xs:simpleType>
<xs:restriction base="...">
...
</xs:restriction>
</xs:simpleType>
</xs:element>
restriction语法如下:
<restriction id=ID base=QName any attributes >
Content for simpleType:
(annotation),(simpleType),(minExclusive|minInclusive|
maxExclusive|maxInclusive|totalDigits|fractionDigits|
length|minLength|maxLength|enumeration|whiteSpace|pattern)*))
Content for simpleContent:
(annotation),(simpleType),(minExclusive |minInclusive|
maxExclusive|maxInclusive|totalDigits|fractionDigits|
length|minLength|maxLength|enumeration|whiteSpace|pattern)*)?,
((attribute|attributeGroup)*,anyAttribute?))
Content for complexContent:
(annotation?,(group|all|choice|sequence)?,
((attribute|attributeGroup)*,anyAttribute?))
</restriction>
2.3.1 对值的限定(minInclusive&maxInclusive)
下面的例子定义了带有一个限定且名为 "age" 的元素。age 的值不能低于 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>
2.3.2 对一组值的限定(enumeration)
如需把 XML 元素的内容限制为一组可接受的值,我们要使用枚举约束(enumeration constraint)。
下面的例子定义了带有一个限定的名为 "car" 的元素。可接受的值只有:Audi, Golf, BMW:
<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>
2.3.3 对一系列值的限定(pattern)
如需把 XML 元素的内容限制定义为一系列可使用的数字或字母,我们要使用模式约束(pattern constraint)。
下面的例子定义了带有一个限定的名为 "letter" 的元素。可接受的值只有小写字母 a - z 其中的一个:
<xs:element name="letter">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:pattern value="[a-z]"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
注:如果您对正则表达式有所了解,name对value值就不会感到陌生。正则表达式可不止只是上面的这一个功能,更多详细正则表达式功能在此不详细叙述。关于pattern的一些示例可以参考:http://www.w3school.com.cn/schema/schema_facets.asp
2.3.4 对空白字符的限定(whiteSpace)
如需规定对空白字符(whitespace characters)的处理方式,我们需要使用 whiteSpace 限定。
下面的例子定义了带有一个限定的名为 "address" 的元素。whiteSpace 限定的值包含如下几个:
- replace:意味着 XML 处理器将移除所有空白字符(换行、回车、空格以及制表符)
- collapse:这意味着 XML 处理器将移除所有空白字符(换行、回车、空格以及制表符会被替换为空格,开头和结尾的空格会被移除,而多个连续的空格会被缩减为一个单一的空格)
- preserve:意味着 XML 处理器不会移除任何空白字符:
<xs:element name="address">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:whiteSpace value="preserve"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
2.3.5 对长度的限定(length&minLength&maxLength)
如需限制元素中值的长度,我们需要使用 length、maxLength 以及 minLength 限定。
本例定义了带有一个限定且名为 "password" 的元素。其值必须精确到 8 个字符:
<xs:element name="password">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:length value="8"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
定义了带有一个限定的名为 "password" 的元素。其值最小为 5 个字符,最大为 8 个字符:
<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>
三、Schema深入之复杂的类型
复合元素是指包含其他元素及/或属性的 XML 元素,其包含有四种类型的复合元素:
- 空元素
- 包含其他元素的元素
- 仅包含文本的元素
- 包含元素和文本的元素
注释:上述元素均可包含属性!
在 XML Schema 中,我们有两种方式来定义复合元素,下面以这个XML来进行举例:
<employee>
<firstname>John</firstname>
<lastname>Smith</lastname>
</employee>
<1> 通过命名此元素,可直接对"employee"元素进行声明
<xs:element name="employee">
<xs:complexType>
<xs:sequence>
<xs:element name="firstname" type="xs:string"/>
<xs:element name="lastname" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
假如您使用上面所描述的方法,那么仅有 "employee" 可使用所规定的复合类型。请注意其子元素,"firstname" 以及 "lastname",被包围在指示器 <sequence>中。这意味着子元素必须以它们被声明的次序出现。(指示器会在下面进行详细介绍)
<2> "employee" 元素可以使用 type 属性
其实我们在上面已经提及了这部分,type属性的作用是引用要使用的复合类型的名称:
<xs:element name="employee" type="personinfo"/>
<xs:complexType name="personinfo">
<xs:sequence>
<xs:element name="firstname" type="xs:string"/>
<xs:element name="lastname" type="xs:string"/>
</xs:sequence>
</xs:complexType>
这样做的好处是任何xs:element定义的时候都可以引用name="personinfo"的这个xs:complexType。
我们也可以在已有的复合元素之上以某个复合元素为基础,然后添加一些元素,这非常像平常说的继承关系,就像这样:
<xs:element name="employee" type="fullpersoninfo"/>
<xs:complexType name="personinfo">
<xs:sequence>
<xs:element name="firstname" type="xs:string"/>
<xs:element name="lastname" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="fullpersoninfo">
<xs:complexContent>
<xs:extension base="personinfo">
<xs:sequence>
<xs:element name="address" type="xs:string"/>
<xs:element name="city" type="xs:string"/>
<xs:element name="country" type="xs:string"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
其中<xs:extension base="personinfo"></xs:sequence>就是将此元素定位基础。
3.1 XSD 复合空元素
空的复合元素不能包含内容,只能含有属性。下面是一个空的 XML 元素:
<product prodid="1345" />
在Schema中声明此 "product" 元素如下:
<xs:element name="product">
<xs:complexType>
<xs:attribute name="prodid" type="xs:positiveInteger"/>
</xs:complexType>
</xs:element>
或者您可以为一个 complexType 元素起一个名字,然后为 "product" 元素设置一个 type 属性并引用这个 complexType 名称(通过使用此方法,若干个元素均可引用相同的复合类型):
<xs:element name="product" type="prodtype"/>
<xs:complexType name="prodtype">
<xs:attribute name="prodid" type="xs:positiveInteger"/>
</xs:complexType>
3.2 XSD 复合类型 - 仅含元素
XML 元素,"person",仅包含其他的元素:
<person>
<firstname>John</firstname>
<lastname>Smith</lastname>
</person>
我们可以在 schema 中这样定义 "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>
注意:其中使用了指示器,这意味着被定义的元素必须按上面的次序出现在 "person" 元素中。我们也可以为 complexType 元素设定一个名称,并让 "person" 元素的 type 属性来引用此名称,与上面类同,就不在举例了。
3.3 XSD 仅含文本复合元素
仅含文本的复合元素可包含文本和属性。
此类型仅包含简易的内容(文本和属性),因此我们要向此内容添加 simpleContent 元素。当使用简易内容时,我们就必须在 simpleContent 元素内定义扩展或限定,就像这样:
<xs:element name="某个名称">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="basetype">
....
....
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
或者:
<xs:element name="某个名称">
<xs:complexType>
<xs:simpleContent>
<xs:restriction base="basetype">
....
....
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
</xs:element>
注意:需要使用 extension 或 restriction 元素来扩展或限制元素的基本简易类型。
示例如下:
这里有一个 XML 元素的例子,"shoesize",其中仅包含文本:
<shoesize country="france">35</shoesize>
下面这个例子声明了一个复合类型,其内容被定义为整数值,并且 "shoesize" 元素含有名为 "country" 的属性:
<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>
我们也可为 complexType 元素设定一个名称,并让 "shoesize" 元素的 type 属性来引用此名称(通过使用此方法,若干元素均可引用相同的复合类型):
<xs:element name="shoesize" type="shoetype"/>
<xs:complexType name="shoetype">
<xs:simpleContent>
<xs:extension base="xs:integer">
<xs:attribute name="country" type="xs:string" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
3.4 XSD 带有混合内容的复合类型
混合的复合类型可包含属性、元素以及文本。详见:http://www.w3school.com.cn/schema/schema_complex_mixed.asp
3.5 XSD 复合类型指示器
通过指示器,我们可以控制在文档中使用元素的方式。有七种指示器:
- Order 指示器:
- All
- Choice
- Sequence
- Occurrence 指示器:
- maxOccurs
- minOccurs
- Group 指示器:
- Group name
- attributeGroup name
3.5.1 Order 指示器
Order 指示器用于定义元素的顺序。
<1> All 指示器
<all> 指示器规定子元素可以按照任意顺序出现,且每个子元素必须只出现一次:
<xs:element name="person">
<xs:complexType>
<xs:all>
<xs:element name="firstname" type="xs:string"/>
<xs:element name="lastname" type="xs:string"/>
</xs:all>
</xs:complexType>
</xs:element>
注:当使用 <all> 指示器时,你可以把 <minOccurs> 设置为 0 或者 1,而只能把 <maxOccurs> 指示器设置为 1
<2> Choice 指示器
<choice> 指示器规定可出现某个子元素或者可出现另外一个子元素(非此即彼):
<xs:element name="person">
<xs:complexType>
<xs:choice>
<xs:element name="employee" type="employee"/>
<xs:element name="member" type="member"/>
</xs:choice>
</xs:complexType>
</xs:element>
提示:如需设置子元素出现任意次数,可将 <maxOccurs> 设置为 unbounded(无限次)。
<3> Sequence 指示器
<sequence> 规定子元素必须按照特定的顺序出现:
<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>
3.5.2 Occurrence 指示器
Occurrence 指示器用于定义某个元素出现的频率。
注:对于所有的 "Order" 和 "Group" 指示器(any、all、choice、sequence、group name 以及 group reference),其中的 maxOccurs 以及 minOccurs 的默认值均为 1。
<1> maxOccurs 指示器
<maxOccurs> 指示器可规定某个元素可出现的最大次数:
<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"/>
</xs:sequence>
</xs:complexType>
</xs:element>
上面的例子表明,子元素 "child_name" 可在 "person" 元素中最少出现一次(其中 minOccurs 的默认值是 1),最多出现 10 次。
<2> minOccurs 指示器
<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>
上面的例子表明,子元素 "child_name" 可在 "person" 元素中出现最少 0 次,最多出现 10 次。
提示:如需使某个元素的出现次数不受限制,请使用 maxOccurs="unbounded" 这个声明。
3.5.3 Group 指示器
Group 指示器用于定义相关的数批元素。
<1> 元素组
元素组通过 group 声明进行定义:
<xs:group name="组名称">
...
</xs:group>
您必须在 group 声明内部定义一个 all、choice 或者 sequence 元素。下面这个例子定义了名为 "persongroup" 的 group,它定义了必须按照精确的顺序出现的一组元素:
<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 定义完毕以后,就可以在另一个定义中引用它了:
<xs:element name="person" type="personinfo"/>
<xs:complexType name="personinfo">
<xs:sequence>
<xs:group ref="persongroup"/>
<xs:element name="country" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<2> 属性组
属性组通过 attributeGroup 声明来进行定义:
<xs:attributeGroup name="组名称">
...
</xs:attributeGroup>
下面这个例子定义了名为 "personattrgroup" 的一个属性组:
<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>
3.6 XSD <any> 元素
<any> 元素使我们有能力通过未被 schema 规定的元素来拓展 XML 文档!换句话说,我们用<any>元素进行占位,然后就可以使用任意元素进行插入了,也就是说我们想拓展原来的元素,只需要在其位置插入<any>元素,然后在其它地方定义即可,这样既不会破坏原来的结构,也进行了相应的拓展。
详细参见:http://www.w3school.com.cn/schema/schema_complex_any.asp
3.7 XSD <anyAttribute> 元素
<anyAttribute> 元素使我们有能力通过未被 schema 规定的属性来扩展 XML 文档!
与上面的Any类同,只不过是一个拓展的是元素,一个拓展的是属性。
详细参见:http://www.w3school.com.cn/schema/schema_complex_anyattribute.asp
注:<any> 和 <anyAttribute> 均可用于制作可扩展的文档!它们使文档有能力包含未在主 XML schema 中声明过的附加元素。
3.8 XSD 元素替换(Element Substitution)
通过 XML Schema,一个元素可对另一个元素进行替换。
详细参见:http://www.w3school.com.cn/schema/schema_complex_subst.asp
w3cschool提供的XSD 实例:http://www.w3school.com.cn/schema/schema_example.asp
四、Schema深入之数据类型
4.1 字符串
字符串数据类型用于可包含字符串的值。字符串数据类型可包含字符、换行、回车以及制表符。
注:如果您使用字符串数据类型,XML 处理器就不会更改其中的值。
scheme 中字符串声明的例子:
<xs:element name="customer" type="xs:string"/>
规格化字符串数据类型(NormalizedString Data Type):规格化字符串数据类型同样可包含字符,但是 XML 处理器会移除折行,回车以及制表符。
schema 中规格化字符串数据类型的例子:
<xs:element name="customer" type="xs:normalizedString"/>
Token 数据类型(Token Data Type):Token 数据类型同样可包含字符,但是 XML 处理器会移除换行符、回车、制表符、开头和结尾的空格以及(连续的)空格。
schema 中有关 token 声明的例子:
<xs:element name="customer" type="xs:token"/>
字符串数据类型:请注意,所有以下的数据类型均衍生于字符串数据类型(除了字符串数据类型本身)!
对字符串数据类型的限定(Restriction)
可与字符串数据类型一同使用的限定:
- enumeration
- length
- maxLength
- minLength
- pattern (NMTOKENS、IDREFS 以及 ENTITIES 无法使用此约束)
- whiteSpace
4.2 日期及时间数据类型(Date and Time Data Types)
详见:http://www.w3school.com.cn/schema/schema_dtypes_date.asp
4.3 数值类型
详见:http://www.w3school.com.cn/schema/schema_dtypes_numeric.asp
4.4 杂项数据类型(Miscellaneous Data Types)
其他杂项数据类型包括逻辑、base64Binary、十六进制、浮点、双精度、anyURI、anyURI 以及 NOTATION。
详见:http://www.w3school.com.cn/schema/schema_dtypes_misc.asp
待参考资料: