DTD验证xml格式的三种方式详解
作者:bug生产者
验证xml格式
目前有两种为XML文档定义语义约束的方式:一种是采用DTD作为语义约束;一种是采用 XML Schema作为语义约束
DTD验证
可以使用DTD来定义XML文档的合法构建模块。DTD可以写在文档内部,也可以另外写一个文件
DTD约束简单易用,但是功能较弱
在XML文档中引入DTD主要有三种方式
- 内部DTD
- 外部DTD
- 公用DTD
内部DTD
内部DTD就是将DTD与XML数据定义放在同一份文档中
<?xml version="1.0"?> <!DOCTYPE note [ <!ELEMENT note (to,from,body)> <!ELEMENT to (#PCDATA)> <!ELEMENT from (#PCDATA)> <!ELEMENT body (#PCDATA)> ]> <note> <to>ll</to> <from>zh</from> <body>hello</body> </note>
DTD包含在以上格式的声明中
<!DOCTYPE 根元素 [元素声明]> XML文档主体部分
外部DTD
如果DTD位于XML源文件外部,应该封装在一个DTD文档中,并在XML中声明,方便被多个XML文档共享
<!DOCTYPE 根元素 SYSTEM "外部DTD地址">
公用DTD
有一种特殊的外部DTD,是由某个权威机构制定的,通过PUBLIC关键字引入,使用公用DTD时,还需要给该DTD指定一个标识名
<!DOCTYPE 根元素 PUBLIC "DTD标识名" "公用DTD地址">
DTD结构
元素类型描述
元素声明的语法格式
<!ELEMENT 元素名称 元素类型描述>
元素类型描述的格式
PCDATA
关键字#PCDATA说明元素只能是字符串,不能包含其他子元素,也不可以是空元素
例:
<?xml version="1.0"?> <!DOCTYPE name [ <!ELEMENT name (#PCDATA)> ]> <name>张三</name>
子元素
说明元素包含的是子元素。当一个元素只包含子元素时而没有字符数据时,表示此元素类型具有元素型类型。在该类型的元素声明时,通过内容模型来指定在其内容上的约束(内容模型是决定子元素类型和子元素出现顺序的一种简单语法)
例:
<?xml version="1.0"?> <!DOCTYPE note [ <!ELEMENT note (to,from,body)> <!ELEMENT to (#PCDATA)> <!ELEMENT from (#PCDATA)> <!ELEMENT body (#PCDATA)> ]> <note> <to>ll</to> <from>zh</from> <body>hello</body> </note>
复杂一些的内容模型为
<!-- 竖线| 表示这些至少存在一个 ? 表示可以有一个也可以没有 * 表示零个或者多个 + 表示一个或者多个,至少有一个 --> <!-- 该内容模型表示 简历中要有名字,性别,年龄,电话和手机任选一个,填写一个家庭住址或者不填,零个或者多个兴趣爱好,至少一个教育经历,工作经验可有可无 --> <!ELEMENT 简历 (名字,性别,年龄,(电话 | 手机), 家庭住址?, 兴趣爱好*, 教育经历+, 工作经验*)>
混合内容
既可以包含子元素,也可以包含字符数据(使用混合内容模型时,#PCDATA关键字必须是模型中的第一个选项,不能在模型中使用逗号、问号或加号。只能用竖线来分隔#PCDATA和元素)
<?xml version="1.0"?> <!DOCTYPE email [ <!ELEMENT email (#PCDATA | body)*> <!ELEMENT body (#PCDATA)> ]> <email> 邮件 <body>hello</body> </email>
EMPTY
关键字EMPTY表明该元素只能是一个空元素,既不包含字符串,也不包含子元素
例:
<!ELEMENT br EMPTY>
ANY
关键字ANY表明该元素可以包含任何字符数据和子元素
<!ELEMENT note ANY>
元素属性定义
属性定义的格式
<!ATTLIST 属性所属的元素 属性名 属性类型 [元素对属性的约束] [默认值]>
元素对属性的约束类型
REQUIRED 必需的属性,不能指定默认值
IMPLIED 可有可无,不能指定默认值
FIXED 固定的属性值,必须指定默认值
没有约束时,必须为属性指定默认值
属性类型
- CDATA 字符串类型
(en1|en2|en3) 一系列枚举
<!ATTLIST file type (txt|csv|json) #REQUIRED>
- ID 有效地标识符,可用于标识该元素,在xml文档中必须唯一
- IDREF 引用自另一个已有的ID属性值
- IDREFS 引用自多个已有的ID属性值,多个ID属性值之间用空格隔开
- NMTOKEN 一个合法的XML名称,指定了该属性值是字符串,但比CDATA有更强的约束性,表明该属性只能由字母、数字、英文下划线、英文横杠、英文点号、英文冒号组成
- NMTOKENS 由多个NMTOKEN组成,多个NMTOKEN用空格隔开
- ENTITY 是一个外部实体
- ENTITIES 多个外部实体,之间使用空格隔开
- NOTATION 该属性值是在DTD中声明过的符号,该规范已过期
- xml: 该属性值是一个预定义的xml值
示例
<?xml version="1.0"?> <!DOCTYPE email [ <!ELEMENT email (#PCDATA | body)*> <!ATTLIST email from CDATA #REQUIRED> <!ATTLIST email to CDATA #REQUIRED> <!ELEMENT body (#PCDATA)> ]> <email from="zh" to="ll"> 邮件 <body>hello</body> </email>
XML Schema Definition
在DTD之后,W3C推出了新的规范来验证xml格式:XML Schema Definition
XML Schema 约束采用了XML文档定义,支持更详细的约束规则,功能强大,只是使用起来比较复杂
Schema语法格式
<?xml version="1.0"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http:///j2j.idril.cn" xmlns="http://j2j.idril.cn" elementFormDefault="qualified"> <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="body" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:element>
<xs:schema // 指定了schema中用到的元素和数据类型来自的命名空间 还规定了来自此命名空间的元素和数据类型应该使用前缀xs: xmlns:xs="http://www.w3.org/2001/XMLSchema" // 说明此schema定义的元素来自的命名空间 targetNamespace="http:///j2j.idril.cn" // 指定了默认的命名空间,使用该命名空间下的Schema组件时,不需要使用任何前缀来作为限定 xmlns="http://j2j.idril.cn" // 指出任何XML实例文档所使用的且在此schema中声明过的元素必须被命名空间限定 elementFormDefault="qualified">
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 会将字符串内容中包含的换行、制表符、回车符都替换为空白,并自动删除字符串前后的空白,如果字符串中间包含有多个连续的空白,多个连续的空白会被压缩为单个空白
// 简易元素(仅包含文本的元素,不会包含子元素或属性) // 常用的type有xs:strig、xs:decimal、xs:integer、xs:Boolean、xs:date、xs:time <xs:element name="to" type="xs:string"/>
// 属性 // 常用的type有xs:strig、xs:decimal、xs:integer、xs:Boolean、xs:date、xs:time <xs:attribute name="lang" type="xs:string"/>
自定义限制类型
共有12中约束
- enumeration 指定元素或属性的值是枚举值
- fractionDigits 对于任意精度的十进制数起作用,用于定义小数点后的最大位数
- length 定义元素或属性的值的字符长度
- minExclusive 定义元素或属性的下界值,必须大于该值
- maxExclusive 定义元素或属性的上界值,必须小于该值
- minInclusive 定义元素或属性的下界值,必须大于等于该值
- maxInclusive 定义元素或属性的上界值,必须小于等于该值
- minLength 字符串的最小长度
- maxLength 字符串的最大长度
- pattern 数据类型的值必须匹配的指定的正则表达式
- totalDigits 指定decimal及其派生类型的数值最大能有几位数(包括小数和整数部分)
whiteSpace 对字符串中的空白处理方式,取值为
- preserve 保留字符串中的空白
- replace 将所有的制表符、换行符和回车符都用空格代替
- collapse 先执行replace,然后取出首尾的空格,并将中间多个相邻的空格压缩为一个空格
<!-- 定义一个新的数据类型 --> <xs:simpleType name="age_Type"> <!-- 限定 用于XML元素或者属性定义可接受的值 --> <xs:restriction base="xs:integer"> <xs:minInclusive value="0"> <xs:maxInclusive value="120"> </xs:restriction> </xs:simpleType> <!-- 使用自定义类型 --> <xs:element name="age" type="age_Type"></xs:element>
自定义列表类型
有两种方式可以来自定义列表类型
- 在<list…>元素中增加<simpleType…>子元素来指定列表元素的数据类型
<xs:simpleType name="age_list_Type"> <xs:list> <!-- 定义一个新的数据类型 --> <xs:simpleType name="age_Type"> <!-- 限定 用于XML元素或者属性定义可接受的值 --> <xs:restriction base="xs:integer"> <xs:minInclusive value="0"> <xs:maxInclusive value="120"> </xs:restriction> </xs:simpleType> </xs:list> </xs:simpleType>
为<list…>元素的itemType属性指定列表元素的数据类型
<!-- 定义一个新的数据类型 --> <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…>子元素来指定联合元素的数据类型
<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属性指定一或多个简单类型,多个简单类型只爱你使用空格隔开
<!-- 定义一个新的数据类型 --> <xs:simpleType name="price_Type"> <!-- 限定 用于XML元素或者属性定义可接受的值 --> <xs:restriction base="xs:decimal"> <xs:minInclusive value="0"> <xs:maxInclusive value="120"> </xs:restriction> </xs:simpleType> <!-- 定义一个新的数据类型 --> <xs:simpleType name="publish_date_Type"> <!-- 限定 用于XML元素或者属性定义可接受的值 --> <xs:restriction base="xs:date"> <xs:minInclusive value="2022-01-01"> <xs:maxInclusive value="2022-12-31"> </xs:restriction> </xs:simpleType> <xs:simpleType name="price_publish_Type"> <xs:union memberTypes="price_Type publish_date_Type"> </xs:union> </xs:simpleType>
复杂类型
定义复杂类型使用complexType元素,有两种方式
- 定义全局命名复杂类型:将<complexType…>元素作为<schema…>、<redefine…>元素的子元素使用,需要指定name属性,其值就是该复杂类型的类型名
- 定义局部匿名复杂类型:将<complexType…>元素作为<element…>元素的子元素使用,无须指定name属性,仅用于指定其父元素<element…>所定义的元素的类型
// 复合元素 <xs:element name="email"> <xs:complexType> <xs:sequence> <xs:element name="to" type="xs:string"/> <xs:element name="from" type="xs:string"/> <xs:element name="body" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:element>
<xs:element name="to" type="xs:string"/>
Schema的使用
同样的,在xml中需要声明Schema
<?xml version="1.0"?> <note xmlns="http://j2j.idril.cn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://j2j.idril.cn node.xsd"> <to>ll</to> <from>zh</from> <body>hello</body> </note>
// 规定了默认的命名空间的声明 xmlns="http://j2j.idril.cn" // 定义了XML Schema实例命名空间 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" // 包含两个值 第一个值是需要使用的命名空间 第二个值是供命名空间使用的XML Schema的位置 xsi:schemaLocation="http://j2j.idril.cn node.xsd"
以上就是DTD验证xml格式的三种方式详解的详细内容,更多关于DTD验证xml格式的资料请关注脚本之家其它相关文章!