在XML中使用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。

猜你喜欢

转载自blog.csdn.net/WilliamChancwl/article/details/85241268