一、什么是XML约束
在XML技术里,可以编写一个文档来约束一个XML文档的书写规范,约束文档定义了在XML中允许出现的元素名称、属性及元素出现的顺序等等。
二、为什么需要约束
由于xml的标签由用户自己定义,因此在开发的时候,每个人都可以根据自己的需求来定义xml标签,这样导致项目中的xml难以维护,因此需要使用一定的规范机制来约束xml文件中的标签书写。
三、XML约束有哪些
XML的约束有两种,分别为:
- XML DTD
- XML Schema
四、DTD约束的使用方法
(一)DTD快速入门
第一步:先定义自己的一个XML文件
<?xml version="1.0" encoding="UTF-8"?>
<users>
<user>
<name>zhangsan</name>
<age>23</age>
<addr>shanghai</addr>
</user>
<user>
<name>lisi</name>
<age>24</age>
<addr>beijing</addr>
</user>
</users>
第二步:书写DTD文件来约束xml文件。
DTD文件在定义的时候,扩展名就是dtd。
<?xml version="1.0" encoding="UTF-8" ?>
<!ELEMENT users (user+)>
<!ELEMENT user (name,age,addr)>
<!ELEMENT name (#PCDATA) >
<!ELEMENT age (#PCDATA)>
<!ELEMENT addr (#PCDATA)>
第三步:引入DTD
- DTD的引入方式由如下三种
DTD主要用来约束xml文件,DTD可以单独写在文件中,也可以直接定义在xml中,可以在xml中引入第三方的公共DTD。
方式一:
外部DTD的引入方式:外部DTD主要指的一个独立的DTD文件。
首先要书写DTD文件,然后在要被约束的xml文件中引入。
<!DOCTYPE 文档根结点 SYSTEM "DTD文件的URL">
文档根结点 指的是当前xml中的根标签。
SYSTEM 引入的系统中存在文件
"DTD文件的URL" DTD存放的位置
方式二:
引入公共的DTD:
<!DOCTYPE 文档根结点 PUBLIC "DTD名称" "DTD文件的URL">
文档根结点 指的是当前xml中的根标签。
PUBLIC 表示当前引入的DTD是公共的DTD
如:<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
方式三:
在xml中直接书写DTD
<!DOCTYPE 根标签名 [
具体的标签的约束
]>
- 此处,在XML文件中使用的引入方式是使用的第三种
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE users[
<!ELEMENT users (user+) >
<!ELEMENT user (name,age,addr) >
<!ELEMENT name (#PCDATA) >
<!ELEMENT age (#PCDATA) >
<!ELEMENT addr (#PCDATA) >
]>
<users>
<user>
<name>zhangsan</name>
<age>23</age>
<addr>shanghai</addr>
</user>
<user>
<name>lisi</name>
<age>24</age>
<addr>beijing</addr>
</user>
</users>
(二)DTD约束语法细节
元素定义:
当定义DTD约束xml时候,这时需要在DTD中使用ELEMENT来定义当前xml中可以出现的标签名称。
格式:
<!ELEMENT 标签名 约束> 约束来限定当前标签中可以有的子标签,或者当前标签中可以书写的内容
在定义标签名的时候,约束中可以使用一些符号标签具体出现次数
? 零次或者一次
* 零次或者多次
+ 一次或者多次
如: users (user+) 表示当前的users标签下可以有一个或者多个user标签
, 用来限定当前的子标签出现的顺序user (name,age,addr)
如:上面的快速入门中,user标签下只能有name age addr 子标签,并且必须按照name age addr的顺序书写
| user (name|age,addr) user下可以name或者age ,但必须有addr,并且addr必须name或age后面
#PCDATA 表明该元素可包含任何字符数据,但不能在其中包含任何子元素。使用该类型时,要用圆括号括起来
EMPTY 表明该元素不能有任何子元素或文本,仅可以使用属性。
ANY 表明该元素中可以包含任何DTD中定义的元素内容 如:<!ELEMENT note ANY>
<!ELEMENT age EMPTY > 当前的age标签是个空标签,它不能有文本内容。
属性定义:
格式:
<!ATTLIST 标签名
属性名 属性的类型 属性的约束
>
如果一个标签上有多个属性
<!ATTLIST 标签名
属性名 属性的类型 属性的约束
属性名 属性的类型 属性的约束
属性名 属性的类型 属性的约束
......
>
属性值类型:
CDATA:表示属性的取值为普通的文本字符串
ENUMERATED (DTD没有此关键字):表示枚举,只能从枚举列表中任选其一,如(鸡肉|牛肉|猪肉|鱼肉)
ID:表示属性的取值不能重复,属性的值只能由字母,下划线开始,不能出现空白字符
属性的约束
#REQUIRED:表示该属性必须出现
#IMPLIED:表示该属性可有可无
#FIXED:表示属性的取值为一个固定值。语法:#FIXED "固定值"
直接值:表示属性的取值为该默认值
a.使用FIXED约束
<!ATTLIST user
name CDATA #FIXED "zhangsan"
>
<user name=”zhangsan”>
b.使用直接值约束
<!ATTLIST user
name CDATA "张三"
>
<user />
实体定义:
实体用于为一段内容创建一个别名,以后在XML文档中就可以使用别名引用这段内容了。
在DTD定义中,一条<!ENTITY …>语句用于定义一个实体。
实体可以理解成Java中预先定义好的一个常量,然后xml文件中就可以引入当前这个定义的实体。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE users[
<!ELEMENT users (user+) >
<!ELEMENT user (name,age,addr) >
<!ELEMENT name (#PCDATA) >
<!ELEMENT age EMPTY >
<!ELEMENT addr (#PCDATA) >
<!ATTLIST user id ID #REQUIRED >
<!ENTITY temp "湖南长沙">
]>
<users>
<user id="u001">
<name>zhangsan</name>
<age></age>
<addr>&temp;</addr>
</user>
<user id="u002">
<name>lisi</name>
<age/>
<addr>&temp;</addr>
</user>
</users>
五、Schema约束的使用方法
(一) Schema简介
Schema它也来约束xml文件的,DTD在约束xml的时候一个xml中只能引入一个DTD,同时DTD它无法对属性以及标签中的数据做数据类型的限定。
Schema是想要用来代替DTD来约束xml的,但是目前还没实现。
Schema文件本身就是使用xml文件书写的,同时它对需要约束的xml中的数据有严格的限定。学习Schema主要来学习W3C组织定义的如何在Schema中约束xml的标签以及属性,还有属性的数据类型,以及标签中子标签的顺序。
要定义一个Schema文件,这时它的扩展名必须是.xsd。在这个文件中根元素必须是schema。
使用Schema来约束xml,Schema在书写的时候,只需要使用W3C组织提前定义的限定标签即可。
(二)Schema快速入门
第一步:书写xml文件
<?xml version="1.0" encoding="UTF-8"?>
<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.itcast.cn/20151111"
xsi:schemaLocation="http://www.itcast.cn/20151111 test.xsd">
<name>zhangsan</name>
<name>zhangsan</name>
<name>zhangsan</name>
<age>20</age>
</person>
第二步:定义schema文件
test.xsd
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.itcast.cn/20151111"
elementFormDefault="qualified">
<element name="person">
<complexType>
<sequence>
<!-- <all> -->
<!-- <choice> -->
<element name="name" type="string" maxOccurs="unbounded"></element>
<element name="age" type="int"></element>
<!-- </choice> -->
<!-- </all> -->
</sequence>
<attribute name="id1" type="int" use="required"></attribute>
</complexType>
</element>
</schema>
(三)对上述文件中相关元素及属性的解释
在schema文件里面
xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.itcast.cn/20151111"
elementFormDefault="qualified">
xmlns="http://www.w3.org/2001/XMLSchema"
- 表示当前xml文件是一个约束文件
targetNamespace="http://www.itcast.cn/20151111"
- 给当前的Schema文件起名字(命名空间),可以自己随便取
- 作用是当哪个xml要引入这个schema约束的时候,必须通过当前targetNamespace 后面书写的uri地址来引入
elementFormDefault="qualified"
- 用的很少
在被约束文件里面引入约束文件
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.itcast.cn/20151111"
xsi:schemaLocation="http://www.itcast.cn/20151111 test.xsd">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- 表示xml是一个被约束文件
xmlns="http://www.itcast.cn/20151111"
- 是约束文档里面的 targetNamespace
xsi:schemaLocation="http://www.itcast.cn/20151111 test.xsd">
- 此属性有两个值。第一个值是需要使用的命名空间。第二个值是供命名空间使用的约束文档的实际位置,两者之间用空格分隔
(四)Schema的名称空间
在XML Schema中,每个约束模式文档都可以被赋以一个唯一的名称空间,名称空间用一个唯一的URI(Uniform Resource Identifier,统一资源标识符)表示。 在Xml文件中书写标签时,可以通过名称空间声明(xmlns),来声明当前编写的标签来自哪个Schema约束文档。
注意:
名称空间的名字语法容易让人混淆,尽管以 http:// 开始,那个 URL 并不指向一个包含模式定义的文件。事实上,这个 URL根本没有指向任何文件,只是一个分配的名字。
(五) Schema约束语法细节
- XMLSchema 简易元素和复杂元素
简易元素:指那些仅包含文本的元素。它不会包含任何其他的元素或属性。
<element name="xxx" type=“string"/>
复杂元素:复杂类型元素是包含子元素或者属性的元素
使用<complexType>:表示复杂类型 ;
<sequence>:表示有顺序
如:
<element name="person">
<complexType>
<sequence>
<element name="to" type="string" />
<element name="from" type="string" />
</sequence>
</complexType>
</element>
- XMLSchema 复杂元素指示器
All: 表示只能出现一次
Choice: 只能出现其中的一个
Sequence: 元素按照顺序出现
maxOccurs=“unbounded” 表示出现次数没限制
如:
<element name="name" type="double" maxOccurs="unbounded"/>
定义属性(必须是复杂元素):<attribute name="p1" type="string" use="required"></attribute>
<any></any>: 表示任意元素,但是必须是约束文档中定义好的
(六)XMLSchema 进阶例子
- company.xsd
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org/company"
elementFormDefault="qualified">
<element name="company">
<complexType>
<sequence>
<element name="employee">
<complexType>
<sequence>
<!-- 引用任何一个元素 -->
<any></any>
<!-- 员工名称 -->
<element name="name"></element>
</sequence>
<!-- 为employee元素添加属性 -->
<attribute name="age" type="int"></attribute>
</complexType>
</element>
</sequence>
</complexType>
</element>
</schema>
- department.xsd
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org/department"
elementFormDefault="qualified">
<!-- 部门名称 -->
<element name="name" type="int"></element>
</schema>
- company.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- 数据文件 引用多个Schema -->
<company xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xmlns:comp = "http://www.example.org/company"
xmlns:dept="http://www.example.org/department"
xsi:schemaLocation="http://www.example.org/company company.xsd http://www.example.org/department department.xsd"
>
<employee age="30">
<!-- 部门名称 -->
<dept:name>100</dept:name>
<!-- 员工名称 -->
<comp:name>王晓晓</comp:name>
</employee>
</company>
注意:
由于一个标签上不能出现两个同名的属性,所以在引入多个约束文档时,需要给名称空间起一个别名。如company.xml中的第3,4,5行。在之后指定哪一个约束文档时,只需要使用别名即可。
Java新手,若有错误,欢迎指正!