XML Schema使用参考手册
1. 概述
之前定义XML文档的时候要定义一个DTD文件来描述XML的定义,DTD的语法简单,非常容易定义,但是也有一些局限性,XML Schema是和DTD功能类似的一种文档,作用是定义XML文档的合法构建模块。目前大家公认XML Schema会取代DTD。
XMLSchema比DTD强大的地方:支持数据类型;使用XML语法定义;
先举一个例子。有一个简单的XML文档
<?xml version="1.0"?>
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
对应的XML Schema文件为
<?xml version="1.0"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"//schema中用到的元素和数据
来自此命名空间,并规定此命
名空间的元素和数据都应该使
用前缀xs
targetNamespace="http://www.w3school.com.cn"//被此schema定义的元素来自此命名空间
xmlns="http://www.w3school.com.cn"//默认的命名空间
elementFormDefault="qualified">
<xs:element name="note">
<xs:complexType>
<xs:sequence>
<xs:elementname="to" type="xs:string"/>
<xs:elementname="from" type="xs:string"/>
<xs:elementname="heading" type="xs:string"/>
<xs:elementname="body" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
其中,<schema> 元素是每一个 XML Schema 的根元素,标签中的属性定义了一些命名空间等信息,在XML中引用schema的方式为
<?xml version="1.0"?>
<notexmlns="http://www.w3school.com.cn"//默认命名空间
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"//实例命名空间
xsi:schemaLocation="http://www.w3school.com.cnnote.xsd">//命名空间和使用的schema的
位置,两属性用空格隔开
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
2. XSD的各种类型
2.1 简单的类型
XSD简易元素就是指那些只包含文本的元素,它不包含任何其他的元素或属性。文本可以是 XML Schema 定义中包括的类型中的一种(布尔、字符串、数据等等),或者它也可以是我们自行定义的定制类型。
定义简易元素的语法是<xs:elementname=”xxx” type=”yyy” />其中name是指元素的名称,type是指元素的类型,常用的类型是•xs:string •xs:decimal •xs:integer •xs:Boolean •xs:date •xs:time。
简易元素可以定义默认值和固定值,例如:
<xs:element name="color"type="xs:string" default="red"/>
<xs:element name="color"type="xs:string" fixed="red"/>
XSD属性均作为简易类型来声明。但是注意,简易元素无法拥有属性,假如一个元素拥有属性,它就会被当作某种复合类型。
定义属性的语法是<xs:attribute name=”xxx” type=”yyy” />其中name是指属性的名称,type是指属性的类型,常用的类型是•xs:string •xs:decimal •xs:integer •xs:Boolean •xs:date •xs:time。
同理,属性也可以定义默认值和固定值,例如:
<xs:attribute name="lang"type="xs:string" default="EN"/>
<xs:attribute name="lang"type="xs:string" fixed="EN"/>
在缺省的情况下,属性是可选的。如需规定属性为必选,请使用 "use" 属性
<xs:attribute name="lang"type="xs:string" use="required"/>
限定用于为XML元素或者属性定义可接受的值,对XML元素的限定被称为facet。
对值的限定,下面的例子定义了一个带有一个限定且名为“age”的元素,age的值不能低于0或者高于120
<xs:element name="age">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:minInclusivevalue="0"/>
<xs:maxInclusive value="120"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
对一组值的限定,即需把XML元素的内容限制为一组可接受的值,要使用枚举约束。举例说明,下面的例子定义了带有一个限定的名为 "car" 的元素。可接受的值只有:Audi, Golf, BMW,
<xs:element name="car" type="carType"/>
<xs:simpleTypename="carType">
<xs:restriction base="xs:string">
<xs:enumeration value="Audi"/>
<xs:enumeration value="Golf"/>
<xs:enumeration value="BMW"/>
</xs:restriction>
</xs:simpleType>
这种定义的方式和上边age的有所不同,其中的cartype可以被其他元素使用。
对一系列值的限定,将XML元素的内容限定为一系列可使用的数字或字母,可使用模式约束,举例说明,下面的例子定义了带有一个限定的名为 "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>
更多正则表达式的例子参考http://www.w3school.com.cn/schema/schema_facets.asp
对长度的限定,使用length、maxlength、minlength等限定,例子如下
<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>
2.2 复杂的类型
Xsd复合元素包含了其他元素及/或属性,有四种类型的复合元素:
•空元素
•包含其他元素的元素
•仅包含文本的元素
•包含元素和文本的元素
注释:上述元素均可包含属性!
在XML Schema中,有两种方式可以定义复合元素,一种是可以直接声明,另一种是引用要使用的复合类型,下面举例说明,
复合XML元素employee仅包含其他元素,
<employee>
<firstname>John</firstname>
<lastname>Smith</lastname>
</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>
引用声明的话:
<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>
使用引用声明的话,type就可以被复用了,比如
<xs:element name="employee" type="personinfo"/>
<xs:element name="student" type="personinfo"/>
<xs:element name="member" type="personinfo"/>
也可以在已有的复合元素之上以某个复合元素为基础,添加一些元素,比如:
<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>
下面说明几种特殊的复合元素如何定义。
复合空元素
类似于这种,<product prodid=”12345” />不能包含内容,只能包含属性的。可以这样定义:
<xs:element name="product">
<xs:complexType>
<xs:attribute name="prodid"type="xs:positiveInteger"/>
</xs:complexType>
</xs:element>
当然也可以单独抽取个type出来:
<xs:element name="product" type="prodtype"/>
<xs:complexType name="prodtype">
<xs:attribute name="prodid"type="xs:positiveInteger"/>
</xs:complexType>
仅含元素的元素
<employee>
<firstname>John</firstname>
<lastname>Smith</lastname>
</employee>
类似于这种,上边已有描述,不再赘述。
仅含文本的元素
类似于这种<shoesize country="france">35</shoesize>,可含有文本和属性,定义为:
<xs:element name="shoesize">
<xs:complexType>
<xs:simpleContent>
<xs:extensionbase="xs:integer">
<xs:attribute name="country" type="xs:string"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
同理可以抽取个type出来,这里不再赘述。
2.3 混合的复合类型
可包含属性、元素以及文本。
举例说明:
<letter>
Dear Mr.<name>John Smith</name>.
Your order <orderid>1032</orderid>
will be shipped on<shipdate>2001-07-13</shipdate>.
</letter>
在这个xml中,letter元素既包含其他元素,又包含文本,可以这样定义:
<xs:element name="letter">
<xs:complexType mixed="true">
<xs:sequence>
<xs:elementname="name" type="xs:string"/>
<xs:element name="orderid"type="xs:positiveInteger"/>
<xs:element name="shipdate" type="xs:date"/>
</xs:sequence>
</xs:complexType>
</xs:element>
注释:为了使字符数据可以出现在"letter" 的子元素之间,mixed 属性必须被设置为 "true"。<xs:sequence> 标签 (name、orderid 以及 shipdate ) 意味着被定义的元素必须依次出现在 "letter" 元素内部。
同理,我们可以抽取type出来。
3. 指示器
通过指示器,我们可以控制在文档中使用元素的方式,共有三大类指示器,下面一一阐述:
3.1 Order指示器
用于定义元素的顺序,其中包含All指示器、Choice指示器和Sequence指示器
<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>
<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>
<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.2 Occurrence指示器
用于定义某个元素出现的频率,包含maxOccurs指示器和minOccurs指示器。
<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>
<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>
如需使某个元素的出现次数不受限制,请使用 maxOccurs="unbounded" 这个声明:
给出一个较完整的例子:
<?xml version="1.0"encoding="ISO-8859-1"?>
<personsxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="family.xsd">
<person>
<full_name>Tony Smith</full_name>
<child_name>Cecilie</child_name>
</person>
<person>
<full_name>David Smith</full_name>
<child_name>Jogn</child_name>
<child_name>mike</child_name>
<child_name>kyle</child_name>
<child_name>mary</child_name>
</person>
<person>
<full_name>Michael Smith</full_name>
</person>
</persons>
其相应的xsd文件为:(family.xsd)
<?xml version="1.0"encoding="ISO-8859-1"?>
<xs:schemaxmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:element name="persons">
<xs:complexType>
<xs:sequence>
<xs:element name="person" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="full_name" type="xs:string"/>
<xs:element name="child_name" type="xs:string"
minOccurs="0" maxOccurs="5"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
3.3 Group指示器
用于定义相关的数批元素,包含Group和attributeGroup。
Group指示器,在group内部必须声明一个all、choice或sequence元素。下面的例子定义了必须按照精确的顺序出现的一组元素:
<xs:groupname="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>
有了这个定义之后,就可以引用了:
<xs:element name="person"type="personinfo"/>
<xs:complexType name="personinfo">
<xs:sequence>
<xs:group ref="persongroup"/>
<xs:elementname="country" type="xs:string"/>
</xs:sequence>
</xs:complexType>
AttributeGroup指示器,例子:
<xs:attributeGroupname="personattrgroup">
<xs:attribute name="firstname"type="xs:string"/>
<xs:attribute name="lastname"type="xs:string"/>
<xs:attributename="birthday" type="xs:date"/>
</xs:attributeGroup>
同理,定义完属性组,就可以引用了:
<xs:element name="person">
<xs:complexType>
<xs:attributeGroup ref="personattrgroup"/>
</xs:complexType>
</xs:element>
3.4 试想,我们的xml文件有可能是需要拓展的,可能我们开始的时候定义了一些元素,也定义好了xsd文件,但是后来我们又想在xml中某个地方增加某些元素,如果xsd文件扩展性比较好的话,就可以兼容这些新的文件,<any>和<anyAttribute>元素可以达到这样的效果。
<any>元素的使用方法为:
首先,有一个对person元素的定义:引用于family.xsd,
<xs:element name="person">
<xs:complexType>
<xs:sequence>
<xs:element name="firstname" type="xs:string"/>
<xs:element name="lastname" type="xs:string"/>
<xs:any minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
其中,红色部分说明在这个部位可以添加任意的元素。
现在,我们希望使用 "children" 元素来扩展 "person" 元素。这此种情况下我们就可以这么做,即使以上这个 schema 的作者没有声明任何 "children" 元素。定义一个children.xsd:
<?xml version="1.0"encoding="ISO-8859-1"?>
<xs:schemaxmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.w3school.com.cn"
xmlns="http://www.w3school.com.cn"
elementFormDefault="qualified">
<xs:element name="children">
<xs:complexType>
<xs:sequence>
<xs:element name="childname" type="xs:string" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
下面这个 XML 文件(名为 "Myfamily.xml"),使用了来自两个不同的 schema 中的成分,"family.xsd"和 "children.xsd":
<?xml version="1.0"encoding="ISO-8859-1"?>
<personsxmlns="http://www.microsoft.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:SchemaLocation="http://www.microsoft.comfamily.xsd
http://www.w3school.com.cnchildren.xsd">
<person>
<firstname>David</firstname>
<lastname>Smith</lastname>
<children>
<childname>mike</childname>
</children>
</person>
<person>
<firstname>Tony</firstname>
<lastname>Smith</lastname>
</person>
</persons>
<anyAttribute> 和<any>类似,它使我们有能力通过未被 schema 规定的属性来扩展 XML 文档。
举一个例子来说明扩展的方法,同样从family.xsd中截取一段针对person元素的声明,通过 <anyAttribute> 元素,我们就可以向 "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:anyAttribute/>
</xs:complexType>
</xs:element>
现在我们定义一个属性文件,名为attribute.xsd:
<?xml version="1.0"encoding="ISO-8859-1"?>
<xs:schemaxmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.w3school.com.cn"
xmlns="http://www.w3school.com.cn"
elementFormDefault="qualified">
<xs:attribute name="gender">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:pattern value="male|female"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:schema>
有了前面两个文件的定义,下面的xml文件就是合法的了:
<?xml version="1.0"encoding="ISO-8859-1"?>
<personsxmlns="http://www.microsoft.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:SchemaLocation="http://www.microsoft.comfamily.xsd
http://www.w3school.com.cn attribute.xsd">
<person gender="female">
<firstname>Jane</firstname>
<lastname>Smith</lastname>
</person>
<person gender="male">
<firstname>David</firstname>
<lastname>Smith</lastname>
</person>
</persons>
4. 元素替换
下面简单说一下元素替换,不是一个必要的功能,但是有可能也用的上。
我们可以在 XML schema 中定义一个 substitutionGroup。首先,我们声明主元素,然后我们会声明次元素,这些次元素可声明它们能够替换主元素。
依然举例说明的,我们希望获得这样的效果:
<customer>
<name>John Smith</name>
</customer>
和
<kunde>
<navn>John Smith</navn>
</kunde>
的定义是等价的,那么可以如下定义
<xs:element name="name"type="xs:string"/>
<xs:element name="navn"substitutionGroup="name"/>
<xs:complexType name="custinfo">
<xs:sequence>
<xs:element ref="name"/>
</xs:sequence>
</xs:complexType>
<xs:element name="customer" type="custinfo"/>
<xs:element name="kunde"substitutionGroup="customer"/>
为防止其他的元素替换某个指定的元素,请使用 block 属性:
<xs:element name="name"type="xs:string" block="substitution"/>
注意:substitutionGroup 中的所有元素(主元素和可替换元素)必须被声明为全局元素,否则就无法工作!
全局元素指 "schema" 元素的直接子元素!本地元素(Local elements)指嵌套在其他元素中的元素。
关于schema的一个完整例子,参考http://www.w3school.com.cn/schema/schema_example.asp
这里不再赘述
5. 数据类型
XSD的数据类型,常用的数据类型无非是字符串、日期等,这里一一描述一下。
字符串
一般使用type=“xs:string”就可以了,由其衍生出许多其他的string类型,如:
type="xs:normalizedString" XML 处理器会移除折行,回车以及制表符
type="xs:token" XML 处理器会移除换行符、回车、制表符、开头和结尾的空格以及(连续的)空格
还有其他的衍生,估计不常用,暂不给出了。
日期
一般使用type="xs:date"定义,日期使用的格式为YYYY-MM-DD,如2002-02-24
时间
一般使用type="xs:time"定义,格式为hh:mm:ss,如09:00:00
日期时间
type="xs:dateTime",格式为YYYY-MM-DDThh:mm:ss,比如2002-05-30T09:00:00,注意中间有个T
数值
数值类型有很多种,比如:
type="xs:decimal"定义一个十进制的数值,如999.79,可规定的十进制数字的最大位数为18位。
type="xs:integer"规定无小数成分的数值,如999,+99,-99等。
还有其他类型的数值,见http://www.w3school.com.cn/schema/schema_dtypes_numeric.asp
其他杂项数据类型,见http://www.w3school.com.cn/schema/schema_dtypes_misc.asp