XML约束
1、概念
一个用来约束XML文档的书写规范的文件
2、常用的约束
- XML DTD
- XML Schema
3、DTD约束
① 概念
DTD(Document Type Definition),文档类型定义
文件扩展名是(*.dtd)
② 语法
(1)元素定义
使用 ELEMENT
来声明一个XML元素
<!ELEMENT 父标签 (子标签 | 子标签 | 子标签)>
用 | 分割表示子标签只能是其中一个
<!ELEMENT 父标签 (子标签, 子标签, 子标签)>
用 逗号 分割表示子标签的顺序必须和声明时的一致
<!ELEMENT 父标签 (子标签 | 子标签 | 子标签)*>
子标签的顺序可以是无序的
使用通配符来控制子标签出现的次数
<!ELEMENT 父标签 (子标签?)>
子标签出现零次或一次
<!ELEMENT 父标签 (子标签*)>
子标签出现零次或多次
<!ELEMENT 父标签 (子标签+)>
子标签出现一次或多次
如果标签没有子标签(自结束标签),则可以声明为 EMPTY
<!ELEMENT 标签名 EMPTY>
如果不限制标签的内容,则可以使用 ANY
<!ELEMENT 标签名 ANY>
如果子标签的内容需要解析器来解析,则可以使用 #PCDATA
【被解析的字符数据(Parsed Character Data)】
<!ELEMENT 标签名 (#PCDATA)>
(2)属性定义
使用 ATTLIST
来声明元素的属性
<!ATTLIST 元素名
属性名称 属性类型 属性类型 默认值
属性名称 属性类型 属性类型 默认值
>
属性类型:
CDATA 值为字符数据 (character data)【不会被解析器解析的文本】
(en1|en2|..) 此值是枚举列表中的一个值
属性值说明有3类:
#REQUIRED 属性值是必需的
#IMPLIED 属性不是必需的
#FIXED "value" 属性值是固定的
默认值:
注意:需要用引号引起来;如果属性类型是#REQUIRED或#IMPLIED,则不允许有默认值
③ 引入方式
-
内部引入:
直接在XML文件内编写约束(一般不用)
示例
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE animal [ <!ELEMENT animal (#PCDATA)> <!ATTLIST animal name CDATA #REQUIRED > ]> <animal name="Tom">Cat</animal>
-
外部引入:
DTD约束是一个独立的文件,并在XML中引入
<!DOCTYPE 文档根节点 SYSTEM "DTD文件路径">
DTD文件在本地
<!DOCTYPE 文档根节点 PUBLIC "DTD名称" "DTD文件的URL路径"> 例如: <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
DTD文件在网络上
④ 示例一
XML DTD文件
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT person (name?, age?, gender?, live?)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age EMPTY>
<!ATTLIST age
value CDATA #REQUIRED
>
<!ELEMENT gender EMPTY>
<!ATTLIST gender
value (man | woman) #REQUIRED
>
<!ELEMENT live EMPTY>
<!ATTLIST live
value CDATA #FIXED "yes"
>
XML文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE person SYSTEM "person.dtd">
<person>
<name>Tom</name>
<age value="14" />
<gender value="man" />
<live value="yes" />
</person>
⑤ 示例二
XML-DTD文件
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT users (user+)>
<!ELEMENT user (name?, age?, gender?, (height | weight)*)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age EMPTY>
<!ATTLIST age
value CDATA #REQUIRED
>
<!ELEMENT gender EMPTY>
<!ATTLIST gender
value (man | woman) #REQUIRED
>
<!ELEMENT height EMPTY>
<!ATTLIST height
value CDATA #IMPLIED
>
<!ELEMENT weight EMPTY>
<!ATTLIST weight
value CDATA "0"
>
XML文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE users SYSTEM "user.dtd">
<users>
<user>
<name>张三</name>
<age value="14" />
<gender value="man" />
<height value="174" />
<weight value="65" />
</user>
<user>
<name>李四</name>
<age value="12" />
<gender value="woman" />
<weight value="50" />
<height value="165" />
</user>
<user>
<name>王五</name>
<age value="17" />
<gender value="man" />
</user>
</users>
4、Schema约束
① 概念
XML Schema也是一种用于定义和描述XML文档结构与内容的模式语言
它是为了弥补XML DTD的局限性
文件扩展名是(*.xsd)
② 对比DTD
- XML Schema符合XML的语法结构
- DOM、SAX等XML API能很容易地解析出XML Schema文档中的内容
- XML Schema对namespace(名称空间)有着很好地支持
- XML Schema支持更多的数据类型,也支持自定义数据类型
- XML Schema有着更强的语法约束力
- XML Schema比XML DTD更为复杂,它是W3C组织的标准,是基于XML DTD的替代者
③ 语法
(1)定义标签
schema的所有约束内容,需要写在 schema
标签里
固定语法格式:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="名称空间"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="名称空间"
elementFormDefault="qualified">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
</xsd:schema>
elementFormDefault属性用来声明自定义标签的约束,其表示将所有声明的元素和属性都关联到指定的名称空间里,qualified
表示全部元素和属性,unqualified
表示只关联根元素
(2)名称空间
所有的schema文件都要有一个namespace,它用一个唯一的URI(Uniform Resource Identifier,统一资源标识符)来表示,该URI不一定存在
声明:URI写在 schema
标签里的 xmlns
和 targetNamespace
属性里
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://???"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://???"
elementFormDefault="qualified">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="根标签名">
</xsd:element>
</xsd:schema>
引用:需要将namespace和xsd文件路径(中间用空格隔开)都写在 XML根元素的 xsi:schemaLocation
属性里
<?xml version="1.0" encoding="UTF-8"?>
<根标签名 xmlns="http://???"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://??? ???.xsd">
</根标签名>
如果是引用多个schema的namespace,就需要取别名。而取别名的方式就是 xmlns:别名
也就是说如果引入了n个schema,则需要取n-1个别名
注意在schema声明里,需要指定 any
标签,否则就无法声明被引入的schema
声明:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://???"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://???">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="根标签名">
<xsd:complexType>
<xsd:sequence maxOccurs="unbounded">
<!-- 注意这个 -->
<xsd:any />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
根标签
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://???"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:别名="被引入名称空间"
targetNamespace="http://???"
elementFormDefault="qualified">
<xsd:import namespace="被引入名称空间" schemaLocation="被引入xsd文件" />
<xsd:element name="标签名" />
</xsd:schema>
被引入标签
引用:
<?xml version="1.0" encoding="UTF-8"?>
<根标签名 xmlns="http://???"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:别名="http://???"
xsi:schemaLocation="http://??? ???.xsd
http://??? ???.xsd">
<别名:标签名 />
</根标签名>
(3)声明标签
使用 element
标签来指定元素标签,其 name
属性是标签的名称
<xsd:element name="标签名">
</xsd:element>
通过 type
属性,来指定其标签填充的数据类型
<xsd:element name="标签名" type="xsd:string" />
字符串
<xsd:element name="标签名" type="xsd:integer" />
整数
<xsd:element name="标签名" type="xsd:boolean" />
逻辑
<xsd:element name="标签名" type="xsd:date" />
日期(yyyy-MM-dd)
<xsd:element name="标签名" type="xsd:time" />
时间(HH:mm:ss)
<xsd:element name="标签名" type="xsd:dateTime" />
日期时间(yyyy-MM-ddTHH:mm:ss)
注意日期和时间之间的“T”
通过 any
标签,来指定子标签可以是任意内容(标签/数据类型)
<xsd:element name="根标签名">
<xsd:complexType>
<xsd:sequence>
<xsd:any />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
在元素标签里使用 complexType
标签来指定其内容是 复合
类型
<xsd:element name="标签名">
<xsd:complexType>
</xsd:complexType>
</xsd:element>
在复合标签里使用 sequence
标签来指定其子元素标签的出现次数(最多或最少)
<xsd:element name="标签名">
<xsd:complexType>
<xsd:sequence maxOccurs="unbounded">
</xsd:sequence>
</xsd:complexType>
</xsd:element>
不限制最多次数
<xsd:sequence maxOccurs="1">
</xsd:sequence>
最多出现一次
<xsd:sequence minOccurs="1">
</xsd:sequence>
最少出现一次
④ 示例一
XML schema文件
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://???/schema/person"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://???/schema/person"
elementFormDefault="qualified">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="person">
<xsd:complexType>
<xsd:sequence maxOccurs="unbounded">
<xsd:element name="name" type="xsd:string" />
<xsd:element name="age" type="xsd:integer" />
<xsd:element name="live" type="xsd:boolean" />
<xsd:element name="date" type="xsd:date" />
<xsd:element name="time" type="xsd:time" />
<xsd:element name="birthday" type="xsd:dateTime" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
XML文件
<?xml version="1.0" encoding="UTF-8"?>
<person xmlns="http://???/schema/person"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://???/schema/person person.xsd">
<name>张三</name>
<age>14</age>
<live>true</live>
<date>2020-12-16</date>
<time>02:31:00</time>
<birthday>2020-12-16T02:31:00</birthday>
</person>
⑤ 示例二
XML schema文件
person.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://???/schema/person"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://???/schema/person">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="person">
<xsd:complexType>
<xsd:sequence>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element ref="body" />
<xsd:any namespace="##other" processContents="strict" minOccurs="0" maxOccurs="unbounded" />
</xsd:choice>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="body">
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="xsd:string">
<xsd:group ref="bodyElements" />
<xsd:attributeGroup ref="bodyAttributes" />
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:group name="bodyElements">
<xsd:sequence>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element ref="constructor-arg" />
<xsd:any namespace="##other" processContents="strict" minOccurs="0" maxOccurs="unbounded" />
</xsd:choice>
</xsd:sequence>
</xsd:group>
<xsd:element name="constructor-arg">
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="index" type="xsd:integer" />
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:attributeGroup name="bodyAttributes">
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="age" type="xsd:integer" />
</xsd:attributeGroup>
</xsd:schema>
pack.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://???/schema/pack"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:person="http://???/schema/person"
targetNamespace="http://???/schema/pack"
elementFormDefault="qualified">
<xsd:import namespace="http://???/schema/person" schemaLocation="person.xsd" />
<xsd:element name="bag">
<xsd:complexType>
<xsd:sequence maxOccurs="unbounded">
<xsd:element name="front">
<xsd:complexType>
<xsd:sequence maxOccurs="1">
<xsd:element name="name" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="back">
<xsd:complexType>
<xsd:sequence maxOccurs="unbounded">
<xsd:element name="one" type="xsd:string" />
<xsd:element name="two" type="xsd:string" />
<xsd:element name="three" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
XML文件
<?xml version="1.0" encoding="UTF-8"?>
<person xmlns="http://???/schema/person"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:pack="http://???/schema/pack"
xsi:schemaLocation="http://???/schema/person person.xsd
http://???/schema/pack pack.xsd">
<body name="张三" age="14">
<constructor-arg index="1" />
</body>
<pack:bag>
<pack:front>
<pack:name>card</pack:name>
</pack:front>
<pack:back>
<pack:one>phone</pack:one>
<pack:two>pad</pack:two>
<pack:three>mac</pack:three>
</pack:back>
</pack:bag>
</person>