在XML中使用Schema
Schema概述
与DTD相比Schema的优势如下:
XML Schema是基于XML进行编写
XML Schema支持数据类型
XML Schema支持命名空间
XML Schema建议规范中有两个基础的命名空间:
一个是用于Schema文档的Schema URI,即http://www.w3.org/2001/XMLSchema。通常使用xs来代表该命名空间。
另一个用于XML文档,即http://www.w3.org/2001/XMLSchema-instance,通常使用xsi来代表该命名空间。
Schema作用
XML Schema即模式。文档通常以单独的文件形式存在,文件扩展名为.xsd。其主要作用如下:
定义可出现在文档中的元素
定义可出现在文档中的属性
定义哪个元素是子元素
定义子元素的次序
定义子元素的数目
定义元素是否为空,或者是否可包含文本
定义元素和属性的数据类型
定义元素和属性的默认值以及固定值
Schema的引用方法
当XML引入Schema时,根据XML文档的元素是否属于某个特定命名空间的,可以按照如下两种方式引入:
不属于特定的命名空间
通过属性xsi:noNamespaceSchemaLocation引入
属于某个特定的命名空间
通过属性xsi:shemaLocation引入
如果Schema文件要约束的XML文件中的元素不属于任何特定命名空间,使用xsi:noNamespaceSchemaLocation属性引入。具体语法如下:
<根元素名称
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="Schema文件路径">
xsi:noNamespaceSchemaLocation :属性值为一个Schema文件的URI。
该属性值只能是一个Schema文件URI,即只能使用一个Schema文件。
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
如果被引入的Schema文件需要约束XML文件中属于某个任何特定的命名空间元素,则通过xsi:schemaLocation属性引入。具体语法如下:
<根元素名称
[xmlns[:prefix]="命名空间URI"]+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="[命名空间URI Schema文件路径]+">
+代表可以写多个的意思
[xmlns[:prefix]="命名空间URI"]+ : 可选项。可以同时引入多个命名空间。
但必须是引用的Schema定义过的命名空间。另外可以给命名空间指明多个前缀。
xsi:schemaLocation=“[命名空间URI Schema文件路径]+” :该属性值可以引入Schema文件。
Schema的引入需要一个命名空间URI和Schema文件路径,
命名空间URI和Schema文件路径中间使用空格间隔。
命名空间URI需要与Schema文件中TargetNamespace定义的一样。
Schema的语法结构
Schema是扩展名为”.xsd”的文本文件,使用XML语法编写。
运行.xsd的文件路径有中文可能会出错。
<?xml version="1.0"?>
<xs:schema xmlns:xs=http://www.w3.org/2001/XMLSchema
targetNamespace="命名空间的URL"
[xmlns[:prefix]= "命名空间的URL"]
[elementFormDefault="qualified | unqualified"]
[attributeFormDefault="qualified | unqualified"]>
元素、属性、注释、数据类型、schema的复用等的定义
</xs:schema>
schema是每一个 XML Schema 的根元素。
xmlns:xs=http://www.w3.org/2001/XMLSchema表示schema文档中用到的元素来自该命名空间。
同时它还规定了元素应该使用前缀 xs:。比如<xs:element>,<xs:attribute>。
targetNamespace定义被此schema定义的XML文档的元素和属性的命名空间。
xmlns[:prefix]= "命名空间的URL",若要引用Schema文档中的元素,必须声明命名空间,
且URL为targetNamespace定义的命名空间。在该Schema文档中和引用该Schema文档的XML文档中,
给命名空间指定的前缀是独立的。
全局元素和局部元素以及全局属性和局部属性是根据元素或属性定义的位置决定的。
在schema中,定义在schema元素下的元素或属性称为全局元素或全局属性(即schema元素的子元素)。
全局元素可以被引用,全局属性必须被引用。
在schema中,定义在复杂类型中的元素或者属性,称之为局部元素或局部属性。
局部元素或局部属性仅能在定义该元素或属性的外部元素中使用。
elementFormDefault: 属性值是qualified或unqualified,
用于指定XML使用Schema中定义的局部元素是否使用命名空间限定。
默认值为unqualified,表示不使用命名空间限定。
attributeFormDefault:
注释
注释的具体方法包括两种:
1. XML语法中的注释<!-- 被注释的内容-->。
2. 通过标记<annotation>来增加注释,该方式具有更好的可读性。
<annotation>:用于说明该Schema组件的作用。
内部可以出现多个<documentation>和<appinfo>而且顺序和次数没有限制。
<documentation> :该子元素的注释主要供人来阅读使用。
<appinfo>:该子元素的注释主要供其它程序来使用。
Schema中定义元素的语法主要包括以下三类:
语法1:
<xs:element name="元素名称" type="数据类型" [default="默认值"] | [fixed="固定值"] [minOccurs="最少出现的次数"] [maxOccurs="最多出现的次数"]/>
例如:
<xs:element name="to" type="xs:string" minOccurs="0"/>
语法1:
<xs:element name="元素名称" type="数据类型" [default="默认值"] | [fixed="固定值"] [minOccurs="最少出现的次数"] [maxOccurs="最多出现的次数"]/>
例如:
<xs:element name="to" type="xs:string" minOccurs="0"/>
例如
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAnYldHL0FWby9mZvwFN4ETMfdHLkVGepZ2XtxSZ6l2clJ3LcV2Zh1Wa9M3clN2byBXLzN3btgHL9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsQTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5CNxUzN0EmNjJmYiVWYzIWNzYzXzADNxATM4IzLcBTMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
语法3:
<xs:element ref="引用元素名称" [default="默认值"]|[fixed="固定值"] [minOccurs="最少出现的次数"] [maxOccurs="最多出现的次数"]/>
<xs:element name="root">
<xs:complexType>
<xs:element ref="sub" minOccurs="1" maxOccurs="unbounded"/>
</xs:complexType>
</xs:element>
<xs:element name="sub" type="xs:string"/>
属性说明:
name : 由程序员指定,元素的名字
type : 元素类型
ref : 引用的元素名称。
default:元素的默认值,可选(不能与fixed属性同时存在)
fixed:元素的固定值,可选(不能与default属性同时存在)
minOccurs : 元素出现的最少次数,默认值为1,可选。
属性值为0则表示该元素是可选的。
minOccurs与maxOccurs不同时出现时,则该属性值只能为0或1。
maxOccurs : 元素出现的最大次数,默认值为1,可选。
属性值为“unbounded”时,指定元素可以出现任意多次。
minOccurs与maxOccurs不同时出现时,则该属性值大于0。
定义属性的语法格式如下所示:
语法1:
<xs:attribute name="属性名" type="属性类型"
[default="默认值"] | [fixed="固定值"] use="使用约束">
</xs:attribute>
语法2:
<xs:attribute ref="属性名" use="使用约束">
</xs:attribute>
注意:只有在复杂类型complexType中才能定义属性!
属性说明如下:
name:XML元素的属性名
type:属性的数据类型。
use:
Schema的数据类型
有一点需要特别注意的是,Schema的数据类型定义,只是在逻辑上对XML文本文档的内容进行了约束,并不对应一个实际的变量。比如把一个元素的内容定义为int型,表示的是,元素的文本内容只能是整数,不能是字符串等其它内容。但本质上,该内容是一个内容为整数的文本。
Schema的数据类型有很多作用,比如可保护数据通信。当数据从发送方被发送到接受方时,其要点是双方应有关于内容的相同的“期望值”。通过 XML Schema,发送方可以用一种接受方能够明白的方式来描述数据。一种数据,比如 “03-11-2004”,在某些国家被解释为11月3日,而在另一些国家为当作3月11日。但是一个带有数据类型的 XML 元素,比如:< date type=“date”>2004-03-11</ date>,可确保对内容一致的理解,这是因为 XML 的数据类型 “date” 要求的格式是 “YYYY-MM-DD”。
Schema的数据类型根据该元素内容可划分为简单类型和复杂类型。
简单类型指元素的内容中即不包括子元素也不包括属性。
复杂类型指元素的内容中包括子元素或属性。
Schema的数据类型按照扩展方式可以分为:
内置数据类型
用户自定义类型
内置数据类型
内置数据类型是被预先定义好的,这些数据类型全部位于命名空间http://www.w3.org/2001/XMLSchema下,所有的内置数据类型都是简单类型。
在W3C的官方网站上,描述了所有内置数据类型的继承关系。在Schema中,数据类型A继承数据类型B,实际上可以理解为数据类型A是在数据类型B的基础上做restriction(限制)操作得到的,即A的value space(取值范围)是B的value space的子集。
内置类型分为3个部分:
任意类型
内置基本数据类型
内置扩展数据类型
任意类型
任意类型包括两种:
anyType:表示该元素为任意类型,与DTD的ANY类似。此类型对于元素的内容没有任何约束。
anySimpleType:表示该元素为任意简单类型。即定义为该类型的元素除不能包含子元素和属性外,没有任何其它的约束。
内置基本数据类型
字符串类型 | |
string | 表示字符串,原封不动保留所有空白 |
QName | 表示一个包含在XML命名空间在内的合法名称(命名空间可省略) |
数值类型 | |
decimal | 数字 |
float | 单精度32位浮点数 |
double | 双精度64位浮点数 |
base64Binary | 任意base64编码的二进制数 |
hexBinary | 任意16进制编码的二进制数 |
日期类型 | |
date | 日期YYYY-MM-DD格式的时间 |
gYearMonth | 年月YYYY-MM格式的时间 |
gYear | 年YYYY格式的时间 |
gMonthDay | 月日- -MM-DD格式的时间 |
gDay | 日期—DD格式的时间 |
gMonth | 月份–MM格式的时间 |
时间类型 | |
duration | 表示持续时间PnYnMnDTnHnMnS,P起始定界符,T分隔符,s前面的n可以是小数 |
dateTime | 表示时间,YYYY-MM-DDThh:mm:ss:sss,sss表示毫秒数 |
time | 表示时间,hh:mm:ss:sss,sss表示毫秒数 |
Boolean类型 | |
boolean | 布尔型,只能接受true,false,0,1 |
anyURI类型 | |
anyURI | 表示一个URI,用来定位文件 |
Notation类型 | |
NOTATION | 表示XML中的NOTAITION类型,不能在模式中直接出现的抽象类型,只能用于派生其它类型。 |
内置扩展数据类型
String类型派生出来的类型及其描述 | |
normalizedString | 将字符串的换行、制表符和回车符替换为空格 |
token | 换行、制表符和回车符替换为空格,且字符串前后空白自动删除;中间多个连续的空白替换为单个空白 |
language | 定义合法的语言代码 |
Name | 含有一个有效的XML名称的字符串 |
NCName | 省略或不带有命名空间前缀的XML名称字符串,不含冒号 |
String类型派生出来用于约束属性的类型及其描述 | |
NMTOKEN | 必须是合法的XML名称,只能由字母、数字、“_”、“-”、“.”、“:”组成 |
NMTOKENS | 多个NMTOKEN,空格为分隔符 |
ID | 标识符 |
IDREF | 引用另一个ID |
IDREFS | 引用多个已有的ID,空格为分隔符 |
ENTITY | 外部实体 |
ENTITIES | 多个外部实体,空格为分隔符 |
decimal类型派生出来的类型及其描述
|
用户自定义类型
用户自定义类型按位置可以分为全局类型和局部类型。
全局类型是直接在schema标记内定义的类型,该类型可以被所有元素使用。
局部类型是定义在某个元素内部的类型,该类型只能被定义该类型的元素所引用
用户自定义类型还可以按照复杂程度划分,分为简单类型和复杂类型。
自定义简单数据类型
自定义简单类型是在内置数据类型的基础上通过限制、列表和联合中一种或几种方式形成的新数据类型。简单数据类型的定义语法:
<xs:simpleType [name="自定义类型名称"]>
[限制、列表、联合一种或几种方式]
</xs:simpleType>
name属性:自定义的数据类型名称。当定义的简单数据类型为全局数据类型,
即直接在<schema>标记中定义,必须写出该属性。
如果为局部数据类型,则没有该属性。
限制
如果通过限制方式产生自定义类型,需要使用的标记为restriction。语法格式如下:
<xs:simpleType [name="自定义类型名称"]>
<xs:restriction base="基类型" >
[约束特征]+
</xs:restriction>
</xs:simpleType>
列表
Schema中定义列表类型使用<list.../>元素,
它把单个简单数据类型扩展出列表类型,
因此使用该元素时必须指出列表元素的类型,
为<list/>元素指定列表元素类型有两种方式。
1是通过为<list.../>元素的itemType属性指定列表元素。
2是为<list.../>元素增加<simpleType.../>子元素来指定列表元素的数据类型。
为<list.../>元素的itemType属性指定列表元素的数据类型
<xs:simpleType [name="自定义类型名称"]>
<xs:list itemType="列表数据类型" ></xs:list >
</xs:simpleType>
为<list.../>元素增加<simpleType.../>子元素来指定列表元素的数据类型:
<xs:simpleType [name="自定义类型名称"]>
<xs:list>
<simpleType.../>
</xs:list >
</xs:simpleType>
联合
Schema中联合类型使用<union.../>元素,
它把单个简单数据类型扩展出联合类型。
为<union.../>元素指定联合元素类型有两种方式。
1是通过为<union.../>元素的memeberTypes属性指定列表元素。
2是为<union.../>元素增加一个或多个<simpleType.../>子元素,每个<simpleType.../>子元素指定一个简单数据类型。
为<union.../>元素的memberTypes属性指定一个或多个简单类型,多个简单类型之间以空格隔开。
<xs:simpleType [name="自定义类型名称"]>
<xs:union memberTypes="[列表数据类型]+" ></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="自定义类型名称">
<xs:sequence [maxOccurs="最多出现的次数"] [minOccurs="最少出现的次数"]>
定义元素[<xs:element>]+
</xs:sequence>
</xs:complexType>
选择<xs:choice>
使用该元素定义的数据类型用于设定子元素的选择关系,
表示该元素的子元素可以根据实际需要从子元素中选择一个使用。使用该元素的语法格式如下:
<xs:complexType name="自定义类型名称">
<xs:choice [maxOccurs="最多出现的次数"] [minOccurs="最少出现的次数"]>
定义元素[<xs:element>]+
</xs:choice>
</xs:complexType>
无序<xs:all>
使用<xs:all>元素定义的数据类型用于设定子元素可以按照任意顺序出现,且每个子元素必须只出现一次。
该元素设定子元素不能增加属性;不能与<xs:sequence>或<xs:choice>同时出现。
使用该元素的语法格式如下:
<xs:complexType name="自定义类型名称">
<xs:all minOccurs="0|1" maxOccurs="1">
定义元素[<xs:element>]+
</xs:all>
</xs:complexType>
简单内容< 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属性的元素被称为替换元素,属性的值为定义好的元素。替换元素允许被替换为被指定的定义好的元素。substitutionGroup属性指定的元素称为被替换元素,也叫头元素(Head Element),
需要注意的是:
替换元素与头元素(被替换元素)都必须是全局元素。
替换元素与头元素必须具有相同的数据类型,或者替换元素的类型是从非替换元素派生出来的。
当定义了替换元素之后,并非意味着不能使用头元素,它只是提供了一个允许元素可替换使用的机制。
抽象元素和抽象类型
当一个元素被声明为“abstract”时,那么该元素为抽象元素。
当一个类型被声明为“abstract”时,那么该类型为抽象类型。
抽象元素和抽象类型不能直接使用,必须有元素和类型对它们进行派生。使用抽象类型时,XML文档只能使用xsi:type属性指定抽象类型的派生类型。
限制替换元素和限制派生类型
当元素或者自定义复杂类型包含final属性时,表示元素或该类型限制派生。final属性值指定限制的方式:
#all:阻止以任何方式派生
extension:阻止以扩展方式派生
restriction:阻止以限制方式派生
extension和restriction:阻止同时以扩展方式和限制方式派生
限制替换类型
限制替换还可以对某个特定复杂类型进行约束,此时复杂类型的定义中< complexType>元素使用block属性。当某个特定类型增加限制时,表示使用该类型的元素被替换时,应该遵循类型中的限制。具体的限制方式依据block的属性值,具体指定限制的方式包括:
元素和属性的约束
key、unique和keyref标记的含义:
key约束:要求所约束的内容必须存在并保证唯一性;
unique约束:要求内容必须唯一,但可以不存在;
keyref约束:要求该内容必须引用一个key约束或unique约束的值。
<xs:key|unique|keyref name="约束名" [refer="参考的约束名"]>
<xs:selector xpath="指定的范围"/>
<xs:field xpath="指定的元素或属性"/>
</xs:key>
Schema的复用
使用include元素将另一份Schema包含到当前的Schema中要求如下:
被包含的Schema文件可以不属于任何命名空间,
但如果包含命名空间,该命名空间必须与包含文件的命名空间保持一致。
使用include元素的语法格式为:
<include schemaLocation=”被包含的Schema的文件”/>
redefine元素可以实现Schema的复用。
可以把redefine元素当成include的增强版,
redefine包含Schema文件还允许重新定义被包含的Schema组件。
语法格式为:
<redefine schemaLocation=”被包含的Schema的文件”/>
需要注意:
重定义的组件必须是Schema里已有的组件;
重定义的组件只能对被包含在Schema里已有的组件增加限制或增加扩展;
如果采用增加限制的方式来重定义原有的组件,则<restriction.../>元素里所包含的约束不能违反原类型已有的约束。
<import.../>元素专门用于复用不同命名空间的。
使用<import.../>元素导入另一份Schema,要求被导入的Schema文件必须与当前文件定义不同的命名空间。
使用该元素的语法:
<import schemaLocation="被包含的Schema的文件" [namespace="被包含的Schema的文件的命名空间"]/>
Schema空元素表示
空元素的定义方法具体包括两种:
minOccurs="0" 元素:
如果是为空值的复杂类型,并且希望它占用最小的空间,
则使用 minOccurs="0" 元素;
nillable="true" 元素:如果空值必须有占位符(例如当其在数组中出现时),
则使用 nillable="true" 元素。
注意nillabe属性值只能为true或false,
用于指定是否可以将显示的零值分配给该元素,该属性只对元素内容有效,
而对元素属性无效。属性的默认值为false。