验证xml格式
目前有两种为XML文档定义语义约束的方式:一种是采用DTD作为语义约束;一种是采用 XML Schema作为语义约束
DTD验证
可以使用DTD来定义XML文档的合法构建模块。DTD可以写在文档内部,也可以另外写一个文件
DTD约束简单易用,但是功能较弱
在XML文档中引入DTD主要有三种方式
- 内部DTD
- 外部DTD
- 公用DTD
内部DTD
内部DTD就是将DTD与XML数据定义放在同一份文档中
1 |
|
DTD包含在以上格式的声明中
1 | <!DOCTYPE 根元素 [元素声明]> |
外部DTD
如果DTD位于XML源文件外部,应该封装在一个DTD文档中,并在XML中声明,方便被多个XML文档共享
1 | <!DOCTYPE 根元素 SYSTEM "外部DTD地址"> |
公用DTD
有一种特殊的外部DTD,是由某个权威机构制定的,通过PUBLIC关键字引入,使用公用DTD时,还需要给该DTD指定一个标识名
1 | <!DOCTYPE 根元素 PUBLIC "DTD标识名" "公用DTD地址"> |
DTD结构
元素类型描述
元素声明的语法格式
1 | <!ELEMENT 元素名称 元素类型描述> |
元素类型描述的格式
#PCDATA
关键字#PCDATA说明元素只能是字符串,不能包含其他子元素,也不可以是空元素
例:
1 |
|
子元素
说明元素包含的是子元素。当一个元素只包含子元素时而没有字符数据时,表示此元素类型具有元素型类型。在该类型的元素声明时,通过内容模型来指定在其内容上的约束(内容模型是决定子元素类型和子元素出现顺序的一种简单语法)
例:
1 |
|
复杂一些的内容模型为
1 | <!-- |
混合内容
既可以包含子元素,也可以包含字符数据(使用混合内容模型时,#PCDATA关键字必须是模型中的第一个选项,不能在模型中使用逗号、问号或加号。只能用竖线来分隔#PCDATA和元素)
1 |
|
EMPTY
关键字EMPTY表明该元素只能是一个空元素,既不包含字符串,也不包含子元素
例:
1 |
ANY
关键字ANY表明该元素可以包含任何字符数据和子元素
1 | <!ELEMENT note ANY> |
元素属性定义
属性定义的格式
1 | <!ATTLIST 属性所属的元素 属性名 属性类型 [元素对属性的约束] [默认值]> |
元素对属性的约束类型
#REQUIRED
必需的属性,不能指定默认值#IMPLIED
可有可无,不能指定默认值#FIXED
固定的属性值,必须指定默认值- 没有约束时,必须为属性指定默认值
属性类型
CDATA 字符串类型
(en1|en2|en3) 一系列枚举
1
ID 有效地标识符,可用于标识该元素,在xml文档中必须唯一
IDREF 引用自另一个已有的ID属性值
IDREFS 引用自多个已有的ID属性值,多个ID属性值之间用空格隔开
NMTOKEN 一个合法的XML名称,指定了该属性值是字符串,但比CDATA有更强的约束性,表明该属性只能由字母、数字、英文下划线、英文横杠、英文点号、英文冒号组成
NMTOKENS 由多个NMTOKEN组成,多个NMTOKEN用空格隔开
ENTITY 是一个外部实体
ENTITIES 多个外部实体,之间使用空格隔开
NOTATION 该属性值是在DTD中声明过的符号,该规范已过期
xml: 该属性值是一个预定义的xml值
示例
1 |
|
XML Schema Definition
在DTD之后,W3C推出了新的规范来验证xml格式:XML Schema Definition
XML Schema 约束采用了XML文档定义,支持更详细的约束规则,功能强大,只是使用起来比较复杂
Schema语法格式
1 |
|
1 | <xs:schema |
Schema数据类型
Schema提供了强大的数据类型支持
简单类型 既能作为XML元素的类型,也可作为XML属性的类型
分为两大类
内建类型 可以直接拿来定义元素或属性的数据类型
自定义类型 自定义类型是由内件类型派生出来的,派生方式有3种
- 限制
使用<restriction...>元素为原有类型增加一个或多个额外的约束
- 列表
使用<list…>元素定义
- 联合
使用<union…>元素定义
- 限制
复杂类型 只能作为XML元素的类型
简单类型
string、normalizedString、token、base64Binary、hexBinary、integer、positiveInteger、negativeInteger、nonNegativeInteger、nonPositiveInteger、long、unsignedLong、int、unsignedInt、short、unsignedShort、byte、unSignedByte、decimal、float、double、boolean、duration、dateTime、date、time、gYear、gYearMonth、gMonth、gMonthDay、gDay、Name、QName、NCName、anyURI、language、ID、IDREF、IDREFS、ENTITY、ENTITIES、NOTATION、NMTOKEN、NMTOKENS
以字符串及相关类型为例
- string 原封不动的保留字符串内容前面、后面及中间的所有空白
- normalizedString 会将字符串内容中包含的换行、制表符、回车符都替换为空白
- token 会将字符串内容中包含的换行、制表符、回车符都替换为空白,并自动删除字符串前后的空白,如果字符串中间包含有多个连续的空白,多个连续的空白会被压缩为单个空白
1 | // 简易元素(仅包含文本的元素,不会包含子元素或属性) |
1 | // 属性 |
自定义限制类型
共有12中约束
- enumeration 指定元素或属性的值是枚举值
- fractionDigits 对于任意精度的十进制数起作用,用于定义小数点后的最大位数
- length 定义元素或属性的值的字符长度
- minExclusive 定义元素或属性的下界值,必须大于该值
- maxExclusive 定义元素或属性的上界值,必须小于该值
- minInclusive 定义元素或属性的下界值,必须大于等于该值
- maxInclusive 定义元素或属性的上界值,必须小于等于该值
- minLength 字符串的最小长度
- maxLength 字符串的最大长度
- pattern 数据类型的值必须匹配的指定的正则表达式
- totalDigits 指定decimal及其派生类型的数值最大能有几位数(包括小数和整数部分)
- whiteSpace 对字符串中的空白处理方式,取值为
- preserve 保留字符串中的空白
- replace 将所有的制表符、换行符和回车符都用空格代替
- collapse 先执行replace,然后取出首尾的空格,并将中间多个相邻的空格压缩为一个空格
1 | <!-- 定义一个新的数据类型 --> |
自定义列表类型
有两种方式可以来自定义列表类型
- `在
- 元素中增加
子元素来指定列表元素的数据类型``
1 | <xs:simpleType name="age_list_Type"> |
为<list…>元素的itemType属性指定列表元素的数据类型
1
2
3
4
5
6
7
8
9
10
11
12<!-- 定义一个新的数据类型 -->
<xs:simpleType name="age_Type">
<!-- 限定 用于XML元素或者属性定义可接受的值 -->
<xs:restriction base="xs:integer">
<xs:minInclusive value="0">
<xs:maxInclusive value="120">
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="age_list_Type">
<xs:list itemType="age_Type"></xs:list>
</xs:simpleType>
自定义联合类型
有两种方式可以自定义联合类型
在<union…>元素中增加一或多个<simpleType…>子元素来指定联合元素的数据类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23<xs:simpleType name="price_publish_Type">
<xs:union>
<!-- 定义一个新的数据类型 -->
<xs:simpleType>
<!-- 限定 用于XML元素或者属性定义可接受的值 -->
<xs:restriction base="xs:decimal">
<xs:minInclusive value="0">
<xs:maxInclusive value="120">
</xs:restriction>
</xs:simpleType>
<!-- 定义一个新的数据类型 -->
<xs:simpleType>
<!-- 限定 用于XML元素或者属性定义可接受的值 -->
<xs:restriction base="xs:date">
<xs:minInclusive value="2022-01-01">
<xs:maxInclusive value="2022-12-31">
</xs:restriction>
</xs:simpleType>
</xs:union>
</xs:simpleType>
在<union…>元素的memberTypes属性指定一或多个简单类型,多个简单类型只爱你使用空格隔开
1 | <!-- 定义一个新的数据类型 --> |
复杂类型
定义复杂类型使用complexType元素,有两种方式
- 定义全局命名复杂类型:
将<complexType…>元素作为<schema…>、<redefine…>元素的子元素使用,需要指定name属性,其值就是该复杂类型的类型名
- 定义局部匿名复杂类型:
将<complexType…>元素作为<element…>元素的子元素使用,无须指定name属性,仅用于指定其父元素<element…>所定义的元素的类型
1 | // 复合元素 |
<xs:element name="to" type="xs:string"/>
Schema的使用
同样的,在xml中需要声明Schema
1 |
|
1 | // 规定了默认的命名空间的声明 |