抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

摘要:本文学习了如何通过DTD和XSD验证XML文档。

1 DTD

1.1 介绍

DTD是文档类型定义 (Document Type Definition) 的缩写,定义了XML文档的结构以及合法的元素和属性。

在使用XML进行数据交换时,DTD可以作为一种验证机制,保证接收到的XML文档是有效的。

1.2 语法

1.2.1 声明

XML文档在声明DTD时,可以使用文档内的DTD规则,也可以引用文档外的DTD文件。

声明位置是在文档顶部,如果文档有序言,则在序言之后声明,根元素在声明后面。

1.2.1.1 内部

使用文档内的DTD规则:

xml
1
2
3
4
5
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE 根元素名 [
<!ELEMENT 元素名 (元素内容)>
<!ELEMENT 元素名 (#PCDATA)>
]>
1.2.1.2 外部

可以引用私有的DTD文件:

xml
1
2
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE 根元素名 SYSTEM "DTD位置">

也可以引用公共的DTD文件,多了一个DTD名称:

xml
1
2
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE 根元素名 PUBLIC "DTD名称" "DTD位置">

外部DTD文件格式:

dtd
1
2
<!ELEMENT 元素名 (元素内容)>
<!ELEMENT 元素名 (#PCDATA)>

1.2.2 元素

声明空元素:

dtd
1
<!ELEMENT 元素名 EMPTY>

空元素在XML文档里需要使用自闭和标签。

DTD示例:

dtd
1
<!ELEMENT br EMPTY>

XML示例:

xml
1
<br/>

声明PCDATA元素:

dtd
1
<!ELEMENT 元素名 (#PCDATA)>

PCDATA元素在XML文档里需要使用文本内容。

DTD示例:

dtd
1
<!ELEMENT name (#PCDATA)>

XML示例:

xml
1
<name>张三</name>

声明元素内部的子元素:

dtd
1
2
3
<!ELEMENT 元素名 (子元素1, 子元素2)>
<!ELEMENT 子元素1 (#PCDATA)>
<!ELEMENT 子元素2 (#PCDATA)>

DTD示例:

dtd
1
2
3
<!ELEMENT person (name, age)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>

XML示例:

xml
1
2
3
4
<person>
<name>张三</name>
<age>20</age>
</person>

1.2.3 属性

声明属性:

dtd
1
<!ATTLIST 元素名 属性名 属性类型 属性值>

属性类型:

  • CDATA:字符串
  • ID:唯一标识符
  • (value1|value2|value3):枚举值

属性值:

  • #REQUIRED:必须
  • #IMPLIED:可选
  • #FIXED value:固定值

DTD示例:

dtd
1
2
3
4
<!ELEMENT person (name, age)>
<!ATTLIST person id ID #REQUIRED>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>

XML示例:

xml
1
2
3
4
<person id="1">
<name>张三</name>
<age>20</age>
</person>

1.2.3 实体

1.2.3.1 内部实体

声明实体:

dtd
1
<!ENTITY 实体名 "实体内容">

引用实体:

xml
1
&实体名;

DTD示例:

dtd
1
<!ENTITY zhangsan "张三">

XML示例:

xml
1
<author>&zhangsan;</author>
1.2.3.2 外部实体

声明实体:

dtd
1
<!ENTITY 实体名 SYSTEM "实体位置">

引用实体:

xml
1
&实体名;

DTD示例:

dtd
1
<!ENTITY zhangsan SYSTEM "http://example.com/dtd/zhangsan.dtd">

XML示例:

xml
1
<author>&zhangsan;</author>

2 XSD

2.1 介绍

XSD是XML模式定义 (XML Schema Definition) 的缩写,用于定义XML文档的合法构建模块,提供了比DTD更强大的功能,是DTD的继任者。

XSD与DTD的比较:

  • 技术年代:DTD是1993年提出的,XSD是2001年提出的。
  • 语法规则:DTD是非XML的独立语法,XSD是纯XML文件,可自描述。
  • 数据类型:DTD支持数据类型较少,XSD支持多种数据类型,并且还可以自定义类型。
  • 命名空间:DTD不支持命名空间,XSD支持命名空间。

2.2 语法

2.2.1 外部引用

XML文档在声明XSD时,规范合理的方式是引用文档外的XSD文件:

xml
1
2
3
4
5
<?xml version="1.0" encoding="UTF-8"?>
<根元素名 xmlns:官方前缀="http://www.w3.org/2001/XMLSchema-instance"
官方前缀:noNamespaceSchemaLocation="对应XSD文件的路径">
<!-- 其他元素 -->
</根元素名>

说明:

  • 使用xmlns:官方前缀定义官方命名空间的前缀,适配官方属性,不能省略
  • 使用官方前缀:noNamespaceSchemaLocation使用noNamespaceSchemaLocation官方属性定义对应XSD文件的路径

XML示例:

xml
1
2
3
4
5
6
<?xml version="1.0" encoding="UTF-8"?>
<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://example.com/xsd/person.xsd">
<name>张三</name>
<age>20</age>
</person>

外部XSD文件格式:

xsd
1
2
3
4
5
<?xml version="1.0" encoding="UTF-8"?>
<内部前缀:schema xmlns:内部前缀="http://www.w3.org/2001/XMLSchema"
elementFormDefault="unqualified">
<!-- 其他元素 -->
</内部前缀:schema>

说明:

  • 使用xmlns:内部前缀定义XSD文件命名空间的前缀,适配XSD文件内部元素,省略内部前缀设置默认命名空间,适配没有前缀的元素
  • 使用elementFormDefault定义XML文档的局部元素是否使用命名空间,默认unqualified设置局部元素不使用命名空间,可以省略

XSD示例:

xsd
1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="person">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="age" type="xs:integer"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

XSD示例,没有指定命名空间的前缀,使用默认命名空间:

xsd
1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema">
<element name="person">
<complexType>
<sequence>
<element name="name" type="string"/>
<element name="age" type="integer"/>
</sequence>
</complexType>
</element>
</schema>

2.2.2 命名空间

XML文档在声明XSD时,支持命名空间:

xml
1
2
3
4
5
6
<?xml version="1.0" encoding="UTF-8"?>
<指定前缀:根元素名 xmlns:指定前缀="命名空间"
xmlns:官方前缀="http://www.w3.org/2001/XMLSchema-instance"
官方前缀:schemaLocation="命名空间 对应XSD文件的路径">
<!-- 其他元素 -->
</指定前缀:根元素名>

说明:

  • 使用xmlns:指定前缀定义XML文档命名空间的前缀,适配XML文档内部元素,省略指定前缀设置默认命名空间,适配没有前缀的元素
  • 使用xmlns:官方前缀定义官方命名空间的前缀,适配官方属性,不能省略
  • 使用官方前缀:schemaLocation使用schemaLocation官方属性定义XML文档命名空间和对应XSD文件的路径

XML示例:

xml
1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8"?>
<px:person xmlns:px="person-xs"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="person-xs http://example.com/xsd/person.xsd">
<px:name>张三</px:name>
<px:age>20</px:age>
</px:person>

外部XSD文件格式:

xsd
1
2
3
4
5
6
<?xml version="1.0" encoding="UTF-8"?>
<内部前缀:schema xmlns:内部前缀="http://www.w3.org/2001/XMLSchema"
targetNamespace="命名空间"
elementFormDefault="qualified">
<!-- 其他元素 -->
</内部前缀:schema>

说明:

  • 使用xmlns:内部前缀定义XSD文件命名空间的前缀,适配XSD文件内部元素,省略内部前缀设置默认命名空间,适配没有前缀的元素
  • 使用targetNamespace定义XML文档命名空间,省略targetNamespace表示XML文档不使用命名空间
  • 使用elementFormDefault定义XML文档的局部元素是否使用命名空间,使用qualified设置局部元素使用命名空间

XSD示例:

xsd
1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="person-xs"
elementFormDefault="qualified">
<xs:element name="person">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="age" type="xs:integer"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

2.2.3 简单元素

2.2.3.1 内置类型

声明内置类型:

xsd
1
<内部前缀:element name="元素名" type="内部前缀:数据类型"/>

常用数据类型:

  • string:字符串
  • integer:整数
  • decimal:小数
  • boolean:布尔值
  • date:日期
  • time:时间
  • dateTime:日期时间

XSD示例:

xsd
1
<xs:element name="name" type="xs:string"/>

XML示例:

xml
1
<name>张三</name>
2.2.3.2 限制类型

声明限制类型:

xsd
1
2
3
4
5
<内部前缀:simpleType name="类型名">
<内部前缀:restriction base="内部前缀:数据类型">
<内部前缀:限制类型属性 value="属性值"/>
</内部前缀:restriction>
</内部前缀:simpleType>

限制类型属性:

  • minInclusive:最小值
  • maxInclusive:最大值
  • minLength:最小长度
  • maxLength:最大长度
  • pattern:正则表达式
  • enumeration:枚举值

XSD示例:

xsd
1
2
3
4
5
6
7
8
<xs:element name="gender" type="genderType"/>
<xs:simpleType name="genderType">
<xs:restriction base="xs:string">
<xs:enumeration value="male"/>
<xs:enumeration value="female"/>
<xs:enumeration value="other"/>
</xs:restriction>
</xs:simpleType>

XML示例:

xml
1
<gender>male</gender>
2.2.3.3 列表类型

声明列表类型:

xsd
1
2
3
<内部前缀:simpleType name="类型名">
<内部前缀:list itemType="内部前缀:数据类型"/>
</内部前缀:simpleType>

XSD示例:

xsd
1
2
3
4
<xs:element name="names" type="namesType"/>
<xs:simpleType name="namesType">
<xs:list itemType="xs:string"/>
</xs:simpleType>

XML示例:

xml
1
<names>张三 李四 王五</names>

2.2.4 声明属性

声明属性:

xsd
1
<内部前缀:attribute name="属性名" type="内部前缀:数据类型"/>

属性是作为简易类型声明的,但简单元素不支持设置属性,只有复杂类型的元素才支持设置属性。

2.2.5 复杂类型

2.2.5.1 元素顺序

声明元素顺序:

xsd
1
2
3
4
5
<内部前缀:complexType name="类型名">
<内部前缀:顺序类型属性>
<!-- 元素 -->
</内部前缀:顺序类型属性>
</内部前缀:complexType>

顺序类型属性:

  • all:所有元素都必须出现,顺序可以改变
  • choice:至少有一个元素必须出现
  • sequence:所有元素都必须出现,顺序不能改变

XSD示例:

xsd
1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="person" type="personType"/>
<xs:complexType name="personType">
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="age" type="xs:integer"/>
</xs:sequence>
</xs:complexType>
</xs:schema>

XML示例:

xml
1
2
3
4
5
6
<?xml version="1.0" encoding="UTF-8"?>
<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://example.com/xsd/person.xsd">
<name>张三</name>
<age>20</age>
</person>
2.2.5.2 元素频率

声明元素频率:

xsd
1
<内部前缀:element name="元素名" type="内部前缀:数据类型" 频率类型属性="属性值"/>

频率类型属性:

  • minOccurs:频率指示器,规定某个元素最小出现次数
  • maxOccurs:频率指示器,规定某个元素最大出现次数

使用数字表示具体次数,使用unbounded表示无限制次数。

XSD示例:

xsd
1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="person" type="personType"/>
<xs:complexType name="personType">
<xs:sequence>
<xs:element name="name" type="xs:string" minOccurs="1" maxOccurs="1"/>
<xs:element name="age" type="xs:integer" minOccurs="1" maxOccurs="1"/>
<xs:element name="hobby" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:schema>

XML示例:

xml
1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8"?>
<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://example.com/xsd/person.xsd">
<name>张三</name>
<age>20</age>
<hobby>篮球</hobby>
<hobby>足球</hobby>
</person>
2.2.5.3 分组

声明分组:

xsd
1
2
3
<内部前缀:分组方式 name="分组名">
<!-- 分组内容 -->
</内部前缀:分组方式>

分组方式:

  • group:元素组,定义多个元素
  • attributeGroup:属性组,定义多个属性

XSD示例:

xsd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="person" type="personType"/>
<xs:complexType name="personType">
<xs:sequence>
<xs:group ref="personGroup"/>
<xs:element name="work" type="workType"/>
</xs:sequence>
</xs:complexType>
<xs:group name="personGroup">
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="age" type="xs:integer"/>
</xs:sequence>
</xs:group>
<xs:complexType name="workType">
<xs:sequence>
<xs:element name="address" type="xs:string"/>
</xs:sequence>
<xs:attributeGroup ref="workAttributeGroup"/>
</xs:complexType>
<xs:attributeGroup name="workAttributeGroup">
<xs:attribute name="id" type="xs:integer"/>
<xs:attribute name="number" type="xs:string"/>
</xs:attributeGroup>
</xs:schema>

XML示例:

xml
1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="UTF-8"?>
<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://example.com/xsd/person.xsd">
<name>张三</name>
<age>20</age>
<work id="1" number="W1001">
<address>北京市朝阳区</address>
</work>
</person>

2.2.6 特殊类型

2.2.6.1 空元素

声明没有元素和属性的空元素:

xsd
1
2
3
<内部前缀:complexType name="类型名">
<内部前缀:sequence/>
</内部前缀:complexType>

XSD示例:

xsd
1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="person" type="personType"/>
<xs:complexType name="personType">
<xs:sequence>
<xs:element name="work" type="emptyType"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="emptyType">
<xs:sequence/>
</xs:complexType>

</xs:schema>

XML示例:

xml
1
2
3
4
5
<?xml version="1.0" encoding="UTF-8"?>
<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://example.com/xsd/person.xsd">
<work/>
</person>

声明没有元素只有属性的空元素:

xsd
1
2
3
<内部前缀:complexType name="类型名">
<内部前缀:attribute name="属性名" type="内部前缀:数据类型"/>
</内部前缀:complexType>

XSD示例:

xsd
1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="person" type="personType"/>
<xs:complexType name="personType">
<xs:sequence>
<xs:element name="work" type="emptyType"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="emptyType">
<xs:attribute name="id" type="xs:integer"/>
</xs:complexType>
</xs:schema>

XML示例:

xml
1
2
3
4
5
<?xml version="1.0" encoding="UTF-8"?>
<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://example.com/xsd/person.xsd">
<work id="1"/>
</person>
2.2.6.2 混合内容

声明包含元素和文本的元素:

xsd
1
2
3
4
5
<内部前缀:complexType mixed="true" name="类型名">
<内部前缀:sequence>
<内部前缀:element name="元素名" type="内部前缀:数据类型"/>
</内部前缀:sequence>
</内部前缀:complexType>

XSD示例:

xsd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="person" type="personType"/>
<xs:complexType name="personType">
<xs:sequence>
<xs:element name="work" type="workType"/>
</xs:sequence>
</xs:complexType>
<xs:complexType mixed="true" name="workType">
<xs:sequence>
<xs:element name="address" type="xs:string"/>
</xs:sequence>
<xs:attribute name="id" type="xs:integer"/>
</xs:complexType>
</xs:schema>

XML示例:

xml
1
2
3
4
5
<?xml version="1.0" encoding="UTF-8"?>
<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://example.com/xsd/person.xsd">
<work id="1">工作地点:<address>北京市朝阳区</address></work>
</person>
2.2.6.3 文本内容

声明只有文本内容和属性的元素:

xsd
1
2
3
4
5
6
7
<内部前缀:complexType name="类型名">
<内部前缀:simpleContent>
<内部前缀:extension base="内部前缀:数据类型">
<内部前缀:attribute name="属性名" type="内部前缀:数据类型"/>
</内部前缀:extension>
</内部前缀:simpleContent>
</内部前缀:complexType>

XSD示例:

xsd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="person" type="personType"/>
<xs:complexType name="personType">
<xs:sequence>
<xs:element name="work" type="workType"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="workType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="id" type="xs:integer"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:schema>

XML示例:

xml
1
2
3
4
5
<?xml version="1.0" encoding="UTF-8"?>
<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://example.com/xsd/person.xsd">
<work id="1">北京市朝阳区</work>
</person>

2.2.7 继承类型

声明继承自其他类型的元素:

xsd
1
2
3
4
5
6
7
8
9
<内部前缀:complexType name="类型名">
<内部前缀:complexContent>
<内部前缀:处理方式 base="其他类型">
<内部前缀:sequence>
<内部前缀:element name="元素名" type="内部前缀:数据类型"/>
</内部前缀:sequence>
</内部前缀:处理方式>
</内部前缀:complexContent>
</内部前缀:complexType>

处理方式:

  • extension:扩展,继承其他类型的所有元素和属性,并添加新的元素和属性
  • restriction:限制,继承其他类型的所有元素和属性,并删除某些元素和属性

评论