摘要:本文学习了如何通过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规则:
xml1 2 3 4 5
| <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE 根元素名 [ <!ELEMENT 元素名 (元素内容)> <!ELEMENT 元素名 (#PCDATA)> ]>
|
1.2.1.2 外部
可以引用私有的DTD文件:
xml1 2
| <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE 根元素名 SYSTEM "DTD位置">
|
也可以引用公共的DTD文件,多了一个DTD名称:
xml1 2
| <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE 根元素名 PUBLIC "DTD名称" "DTD位置">
|
外部DTD文件格式:
dtd1 2
| <!ELEMENT 元素名 (元素内容)> <!ELEMENT 元素名 (#PCDATA)>
|
1.2.2 元素
声明空元素:
dtd
空元素在XML文档里需要使用自闭和标签。
DTD示例:
dtd
XML示例:
xml
声明PCDATA元素:
dtd1
| <!ELEMENT 元素名 (#PCDATA)>
|
PCDATA元素在XML文档里需要使用文本内容。
DTD示例:
dtd1
| <!ELEMENT name (#PCDATA)>
|
XML示例:
xml
声明元素内部的子元素:
dtd1 2 3
| <!ELEMENT 元素名 (子元素1, 子元素2)> <!ELEMENT 子元素1 (#PCDATA)> <!ELEMENT 子元素2 (#PCDATA)>
|
DTD示例:
dtd1 2 3
| <!ELEMENT person (name, age)> <!ELEMENT name (#PCDATA)> <!ELEMENT age (#PCDATA)>
|
XML示例:
xml1 2 3 4
| <person> <name>张三</name> <age>20</age> </person>
|
1.2.3 属性
声明属性:
dtd1
| <!ATTLIST 元素名 属性名 属性类型 属性值>
|
属性类型:
- CDATA:字符串
- ID:唯一标识符
- (value1|value2|value3):枚举值
属性值:
- #REQUIRED:必须
- #IMPLIED:可选
- #FIXED value:固定值
DTD示例:
dtd1 2 3 4
| <!ELEMENT person (name, age)> <!ATTLIST person id ID #REQUIRED> <!ELEMENT name (#PCDATA)> <!ELEMENT age (#PCDATA)>
|
XML示例:
xml1 2 3 4
| <person id="1"> <name>张三</name> <age>20</age> </person>
|
1.2.3 实体
1.2.3.1 内部实体
声明实体:
dtd
引用实体:
xml
DTD示例:
dtd
XML示例:
xml1
| <author>&zhangsan;</author>
|
1.2.3.2 外部实体
声明实体:
dtd1
| <!ENTITY 实体名 SYSTEM "实体位置">
|
引用实体:
xml
DTD示例:
dtd1
| <!ENTITY zhangsan SYSTEM "http://example.com/dtd/zhangsan.dtd">
|
XML示例:
xml1
| <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文件:
xml1 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示例:
xml1 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文件格式:
xsd1 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示例:
xsd1 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示例,没有指定命名空间的前缀,使用默认命名空间:
xsd1 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时,支持命名空间:
xml1 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示例:
xml1 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文件格式:
xsd1 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示例:
xsd1 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 内置类型
声明内置类型:
xsd1
| <内部前缀:element name="元素名" type="内部前缀:数据类型"/>
|
常用数据类型:
- string:字符串
- integer:整数
- decimal:小数
- boolean:布尔值
- date:日期
- time:时间
- dateTime:日期时间
XSD示例:
xsd1
| <xs:element name="name" type="xs:string"/>
|
XML示例:
xml
2.2.3.2 限制类型
声明限制类型:
xsd1 2 3 4 5
| <内部前缀:simpleType name="类型名"> <内部前缀:restriction base="内部前缀:数据类型"> <内部前缀:限制类型属性 value="属性值"/> </内部前缀:restriction> </内部前缀:simpleType>
|
限制类型属性:
- minInclusive:最小值
- maxInclusive:最大值
- minLength:最小长度
- maxLength:最大长度
- pattern:正则表达式
- enumeration:枚举值
XSD示例:
xsd1 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
2.2.3.3 列表类型
声明列表类型:
xsd1 2 3
| <内部前缀:simpleType name="类型名"> <内部前缀:list itemType="内部前缀:数据类型"/> </内部前缀:simpleType>
|
XSD示例:
xsd1 2 3 4
| <xs:element name="names" type="namesType"/> <xs:simpleType name="namesType"> <xs:list itemType="xs:string"/> </xs:simpleType>
|
XML示例:
xml
2.2.4 声明属性
声明属性:
xsd1
| <内部前缀:attribute name="属性名" type="内部前缀:数据类型"/>
|
属性是作为简易类型声明的,但简单元素不支持设置属性,只有复杂类型的元素才支持设置属性。
2.2.5 复杂类型
2.2.5.1 元素顺序
声明元素顺序:
xsd1 2 3 4 5
| <内部前缀:complexType name="类型名"> <内部前缀:顺序类型属性> </内部前缀:顺序类型属性> </内部前缀:complexType>
|
顺序类型属性:
- all:所有元素都必须出现,顺序可以改变
- choice:至少有一个元素必须出现
- sequence:所有元素都必须出现,顺序不能改变
XSD示例:
xsd1 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示例:
xml1 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 元素频率
声明元素频率:
xsd1
| <内部前缀:element name="元素名" type="内部前缀:数据类型" 频率类型属性="属性值"/>
|
频率类型属性:
- minOccurs:频率指示器,规定某个元素最小出现次数
- maxOccurs:频率指示器,规定某个元素最大出现次数
使用数字表示具体次数,使用unbounded表示无限制次数。
XSD示例:
xsd1 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示例:
xml1 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 分组
声明分组:
xsd1 2 3
| <内部前缀:分组方式 name="分组名"> </内部前缀:分组方式>
|
分组方式:
- group:元素组,定义多个元素
- attributeGroup:属性组,定义多个属性
XSD示例:
xsd1 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示例:
xml1 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 空元素
声明没有元素和属性的空元素:
xsd1 2 3
| <内部前缀:complexType name="类型名"> <内部前缀:sequence/> </内部前缀:complexType>
|
XSD示例:
xsd1 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示例:
xml1 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>
|
声明没有元素只有属性的空元素:
xsd1 2 3
| <内部前缀:complexType name="类型名"> <内部前缀:attribute name="属性名" type="内部前缀:数据类型"/> </内部前缀:complexType>
|
XSD示例:
xsd1 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示例:
xml1 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 混合内容
声明包含元素和文本的元素:
xsd1 2 3 4 5
| <内部前缀:complexType mixed="true" name="类型名"> <内部前缀:sequence> <内部前缀:element name="元素名" type="内部前缀:数据类型"/> </内部前缀:sequence> </内部前缀:complexType>
|
XSD示例:
xsd1 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示例:
xml1 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 文本内容
声明只有文本内容和属性的元素:
xsd1 2 3 4 5 6 7
| <内部前缀:complexType name="类型名"> <内部前缀:simpleContent> <内部前缀:extension base="内部前缀:数据类型"> <内部前缀:attribute name="属性名" type="内部前缀:数据类型"/> </内部前缀:extension> </内部前缀:simpleContent> </内部前缀:complexType>
|
XSD示例:
xsd1 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示例:
xml1 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 继承类型
声明继承自其他类型的元素:
xsd1 2 3 4 5 6 7 8 9
| <内部前缀:complexType name="类型名"> <内部前缀:complexContent> <内部前缀:处理方式 base="其他类型"> <内部前缀:sequence> <内部前缀:element name="元素名" type="内部前缀:数据类型"/> </内部前缀:sequence> </内部前缀:处理方式> </内部前缀:complexContent> </内部前缀:complexType>
|
处理方式:
- extension:扩展,继承其他类型的所有元素和属性,并添加新的元素和属性
- restriction:限制,继承其他类型的所有元素和属性,并删除某些元素和属性
条