简单说 xml schema 就是用 xml 来描述 xml 格式的特定 xml 文件.通常文件后缀是 xsd
, 它来自于 XML Schema Definition
的简写.
看看最简单的例子:
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<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>
上面的这个 xsd 文件描述了怎么样一个 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 文件中
- 一个 xml 根节点到底可以包含什么子元素
- 元素或者属性的字段类型
- 元素和属性的默认值等
为什么要学习 XML Schema 呢?
在 xml 的世界中, 我们经常会遇到各种各样的不同的 xml 文件.他们通常都是通过 xml schema 来规范约束的, 区别于 DTD 文件的是它本身就是 xml 文件.
XML schema 支持数据类型
这个可能是区别于其他约束 xml 的描述文件的最大特定
- 它可以很容易的描述这个文件到底有什么内容
- 验证数据的准确性
- 定义数据
- 数据格式
- 不用的数据格式之间的转换
xml schema 继续使用 xml 语法
- 你不需要多学习其他的语言语法等
- 你用 xml 编辑器就可以编辑 schema
- 你可以通过 xml 的读取方式来解析 schema 文件
- 通过 xml 文件可以生成 schema 文件
- 可以通过
XSLT
来转换格式
XML schemas 是可以扩展的因为它是 xml 写就
有了这个扩展性就可以做更多的事情:
- 复用 schema
- 定义新是数据类型基于标准的类型
- 在一个 xml 文档中引用多个 schema 文件
xml schema 增强的数据通信的安全性
当发送数据到对方的时候,双方都能够到期望的结果是必须的. 通过 xml schema, 发送方可以描述数据以至于让接收方能够理解.
例如一个数据03-11-2017
是什么意思呢, 是3月11号还是11月3号呢?
但是通过 xml 的元素表示,它就是简单的:
<date type='date'>2017-03-11</date>
这样双方都理解了它是一个 date
格式的数据, 就是 YYYY-MM-DD
的格式.
格式好并不够
一个格式完好的 xml 文档它是符合 xml 语法
的存在, 如:
- 必须以 xml 定义说明开始
- 必须有一个根节点
- 开始符必须和结束节点匹配
- 元素大小写敏感
- 所有的元素需要结束
- 所有元素需要正确的嵌套
- 所有的属性值应该括号包围
- 实体必须有特定的字符描述.
XSD 的元素
对于 xml schema 文件来说, <schema>
是它的根节点.
<?xml version="1.0"?>
<xs:schema>
...
...
</xs:schema>
这个<schema>
可以包含很多的属性, 看上去像这样:
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="https://www.w3schools.com"
xmlns="https://www.w3schools.com"
elementFormDefault="qualified">
...
...
</xs:schema>
而其中
xmlns:xs="http://www.w3.org/2001/XMLSchema"
就表明了这个 schema 文件里用到的元素和数据类型都是来自"http://www.w3.org/2001/XMLSchema"
这个命名空间里的. 同时指定所有来自这个命名空间里的元素和数据类型都应该使用 xs
作为前缀.
targetNamespace="https://www.w3schools.com"
它说明了定义在这个schema的元素*( note, to, from, heading, body)都是来自这个https://www.w3schools.com"
命名空间的,
而xmlns="https://www.w3schools.com"
表明它是默认的命名空间, elementFormDefault="qualified"
是表明所有使用该 schema的 xnl 文件里元素都应该使用命名空间约束.
引用这个 schema 文件到 xml 里
<?xml version="1.0"?>
<note xmlns="https://www.w3schools.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://www.w3schools.com note.xsd">
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
这里, xmlns="https://www.w3schools.com"
它说明默认的命名空间定义,也就是说所有在这里定义出现的元素都是从这个 schema 的命名空间里出现的.
而一旦你有了 xml schema 实例的命名空间,xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
你可以使用 schemaLocation
属性来定义,它有两个值, 通过空格隔开, 第一个是命名空间, 第二是 xml schema 文件的地址.
xsi:schemaLocation="https://www.w3schools.com note.xsd"
XSD 的简单元素
XSD 终归主干一件事情就是定义 xml 文件里的元素.
一个简单的元素也就是说它只能够包含文本,不能够包含子元素或者属性等.
- 如何定义呢:
<xs:element name="xxx" type="yyy"/>
这里的xxx
就是元素的名称, 而yyy
就是元素的数据类型.
xml schema 内置了很多的数据类型:
xs:string
xs:decimal
xs:integer
xs:boolean
xs:date
xs:time
例子:
如这个 xml 文件:
<lastname>Refsnes</lastname>
<age>36</age>
<dateborn>1970-03-27</dateborn>
它实际对应的 xsd 就是:
<xs:element name="lastname" type="xs:string"/>
<xs:element name="age" type="xs:integer"/>
<xs:element name="dateborn" type="xs:date"/>
而对于简单元素的默认和固定值又是什么样子
简单元素可以指定默认值或者是固定值.
<xs:element name="color" type="xs:string" default="red"/>
# or
<xs:element name="color" type="xs:string" fixed="red"/>
xsd 的属性
所有的属性都是按照简单元素的方式来定义的
-
什么是属性呢?
简单元素不能够有属性,如果一个元素有了属性,那它就是一个复合类型,但是这个属性它本身是以简单元素声明的. -
怎么定义?
<xs:attribute name="xxx" type="yyy"/>
其实上面这个虽然是属性的定义,但是和简单元素也基本上一样的, xxx
就是名字,而 yyy
就是类型
xs:string
xs:decimal
xs:integer
xs:boolean
xs:date
xs:time
例子,
# 如这个元素
<lastname lang="EN">Smith</lastname>
#对应的 xsd
<xs:attribute name="lang" type="xs:string"/>
同样对应属性的默认值和固定值:
<xs:attribute name="lang" type="xs:string" default="EN"/>
# or
<xs:attribute name="lang" type="xs:string" fixed="EN"/>
另外对于属性,它本身还可以是可选的
<xs:attribute name="lang" type="xs:string" use="required"/>
xsd 里对于值的约束
对于元素或者属性的值, 都是可以进行约束的.如下面的约束例子:
<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>
它就约束了 age
这个元素的值应该是0-120
的.
而且还可以这样约束一个值只能是 set 里的一项:
<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>
同样上面的写法可以变换成用来约束它的一个属性:
<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>
接着我们就来说说 xsd 里怎么描述复杂类型吧
xsd complex 元素
所谓一个复杂元素就是它还包含了子元素或者属性
- 什么是复杂元素
一个复杂元素就是包含了子元素或者属性的元素, 有四种:
- 空元素
- 元素只包含了其他元素
- 元素只包含了文本
- 元素包含了其他元素或者文本.
*这里说的元素都可以有属性
复杂元素
# A complex XML element, "product", which is empty:
<product pid="1345"/>
# A complex XML element, "employee", which contains only other elements:
<employee>
<firstname>John</firstname>
<lastname>Smith</lastname>
</employee>
# A complex XML element, "food", which contains only text:
<food type="dessert">Ice cream</food>
#A complex XML element, "description", which contains both elements and text:
<description>
It happened on <date lang="norwegian">03.03.99</date> ....
</description>
怎么定义复杂元素
<employee>
<firstname>John</firstname>
<lastname>Smith</lastname>
</employee>
我们可以通过2中方式来定义复杂元素.
- 就是直接通过复杂类型来生命元素:
<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>
来围绕的, 这就说明需要按照声明的顺序来书写.
- 这个
employee
元素可以有一个类型的属性来引用到一个复杂元素.
<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="employee" type="personinfo"/>
<xs:element name="student" type="personinfo"/>
<xs:element name="member" 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="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>
xsd 空元素
一个所谓的空复杂元素就是它不能够有内容
,只能有属性
<product prodid="1345" />
<xs:element name="product">
<xs:complexType>
<xs:attribute name="prodid" type="xs:positiveInteger"/>
</xs:complexType>
</xs:element>
xsd 定义只有元素的复杂元素
<person>
<firstname>John</firstname>
<lastname>Smith</lastname>
</person>
可以这样定义:
<xs:element name="person" type="persontype"/>
<xs:complexType name="persontype">
<xs:sequence>
<xs:element name="firstname" type="xs:string"/>
<xs:element name="lastname" type="xs:string"/>
</xs:sequence>
</xs:complexType>
xsd 只包含文本
xsd 复合元素
如
<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" type="lettertype"/>
<xs:complexType name="lettertype" 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>
ref