DTD介绍
- DTD( Document Type Definition)文档类型定义。在XML标准中,描述了如何创建DTD,以及如何将它与根据它的规则所编写的XML文档相关联,并且还定义了XML处理器应该如何对DTD进行处理,有了DTD就可以检测XML文档的结构是否正确。
- DTD在实际应用中的作用主要包括:
- 可以验证XML文档数据的有效性
- 可以为某类XML文档提供统一的格式和相同的结构
- 可以保证在一定范围内,XML文档数据的交流和共享
- 一个程序设计人员根据DTD就能够知道对应的XML文档逻辑结构,从而编写出相应的处理应用程序。
- 第一个DTD例子:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE 根元素名称 [
<!ELEMENT 根元素名称(第一个子元素, 第二个子元素)>
<!ELEMENT 第一个子元素(#PCDATA)>
<!ELEMENT 第二个子元素(#PCDATA)>
<!ATTLIST 第一个子元素 属性一 CDATA #REQUIRED>
]>
<根元素名称>
<第一个子元素 属性一="任意内容">
文本内容1
</第一个子元素>
<第二个子元素>
文本内容1
</第二个子元素>
</根元素名称>
DTD的基本语法
- DTD内部可以包含下列语句:
- 元素类型声明语句<!ELEMENT ......>
- 属性列表声明语句<!ATTLIST ......>
- 实体声明语句<!ENTITY .......>
- 符号声明语句<!NOTATION ......>
- 注释语句
- 一个DTA即可以是独立的文档,该文档的扩展名为.dtd。DTD也可以存在于文档内部,如果存在于XML文档内部,则DTD的内容放置于
- 例如:demodtd.dtd如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!-- root元素中包含了两个子元素 --!>
<!ELEMENT root (sub1, sub2)>
<!ELEMENT sub1(#PCDATA)>
<!ELEMENT sub2(#PCDATA)>
<!ATTLIST root param1 NOTATION(Jpeg | Png) # REQUIRED
param2 CDATA # IMPLIED>
<!ENTITY NAME "ENTITY VALUE">
<!NOTATION Jpeg SYSTEM "Image/jpeg">
<!NOTATION Png SYSTEM "Image/png">
引入在XML文档中,代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYE root SYSTEM "demodtd.dtd">
<root param1 = "Jpeg">
<sub1>&NAME;</sub1>
<sub2>any word </sub2>
</root>
直接内置于XML文档中时,代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root[
<!--root元素中包含了2个子元素-->
<!ELEMENT root (sub1,sub2)>
<!ELEMENT sub1 (#PCDATA)>
<!ELEMENT sub2 (#PCDATA)>
<!ATTLIST root param1 CDATA #REQUIRED
param2 CDATA #IMPLIED>
<!ENTITY NAME1 "ENTITY VALUE">
<!ENTITY PIC SYSTEM "Sunset.jpg" NDATA jpr>
<!NOTATION jpr SYSTEM "mspaint.exe">
]>
<root param1="PIC">
<sub1>&NAME1;</sub1>
<sub2>any word</sub2>
</root>
引入DTD的方式
- 外部DTD
外部DTD的引用须事先已有一个dtd文件,将DTD的约束写到文件中,然后在XML文档中按以下语法格式添加:
<!DOCTYPE (根元素名称) SYSTEM "外部DTD的URL地址">
SYSTEM关键字表示文档使用的是私有DTD文件,“外部DTD文件的URI”可以是相对URI或者绝对URI,相对URI是相对于文档类型声明所在文档的位置。“外部DTD文件的URI”这部分也被称为系统标识符(system identifier). - 内部DTD
使用DTD的最简单的方式,内部DTD就是指将语义约束与XML文档的内容放在同一个XML文档中。紧跟在XML声明和处理指令之后,以<!DOCTYPE[开始,以]>结束语法格式如下:
<!DOCTYPE 根元素名称 [ 元素描述 ]>
- 公用DTD
公用DTD与外部DTD类似,但是该DTD引用公用的DTD的语法格式如下:
<!DOCTYPE (根元素名称) PUBLIC "DTD的标识名" "公用DTD的URL地址">
公共DTD名称要遵循一些约定。如果一项DTD是ISO标准,它的名字要以字符串“ISO”开始,如果是一个非ISO的标准组织批准的DTD,它的名字以“+”开始。如果不是标准组织批准的DTD,它的名字以连字符“-”开始。这些开始字符或字符串后面接//和DTD所有者的名字,之后是另一个双斜杠和DTD描述的文档类型,接着又是一个双斜杠后接ISO 639语言标识符,如EN表示英语,ZH表示中文。
例如:
-
自定义的dtd
//tanglin //DTD STUDENT1.0/ZH
<!DOCTYPE HR PUBLIC "//tanglin //DTD STUDENT1.0/ZH " "http://city.dlut.edu.cn/xml/dtds/students.dtd">
-
HTML网页的文档类型声明
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
DTD中的元素
- 元素定义语法
语法如下所示:
<!ELEMENT 元素名 元素类型描述>
语法详细说明:
- 元素名:即文档中元素的名称。
- 元素类型描述:元素类型描述用于指定元素本身是否为对空元素,如果不为空元素元素的内容包括哪些。
- 元素类型
元素类型具体包括以下5类:
-
字符串类型:即#PCDATA,表示该元素的内容只能是字符串。
-
空元素:EMPTY,表示该元素只能是空元素。
-
包含子元素:表示该元素内部嵌套其它元素,具体包含子元素可能有:有序子元素、无序互斥子元素、无序组合子元素。子元素出现的次数也会根据实际的定义而不同。
-
混合类型:即内容中即包括字符串类型又包括子元素,但混合类型在实际应用中不建议使用。
-
任意类型:即ANY,表示该标记对于元素内容没有限制,该标记的内容可以是字符串类型、也可以包含子元素、即包含字符串又包括自元素的混合类型、该标记也可以是空元素。在实际应用中尽量避免。
-
子元素如下:
- 有序子元素
用逗号分隔,表示子元素的出现顺序必须与声明时一致,并且不能被省略。 - 无序互斥子元素
用竖线(|)分隔,表示任选其一,即多个子元素在文档定义中只能出现一个。 - 无序组合子元素
子元素出现频率可以根据不同的符号进行设定这些符号的含义如表2-2所示:
子元素出现频率符号及其含义
修饰符 含义
+ 一次或多次
? 0次或一次
* 0次或多次
缺省 一次
这些修饰符可以限制元素出现的次数,也可以结合圆括号( )批量设置
- 混合类型
混合类型定义的子元素即可以包含字符串又可以包含子元素,其定义方法稍微复杂一些,典型的混合类型定义方法形如<!ELEMENT root (#PCDATA|sub1|sub2)*>。但在实际用该类型使用较少,也不建议使用。
- DTD中的属性
在DTD中声明元素属性的语法:
<!ATTLIST 元素名称 [属性名 属性类型 [约束] [缺省值]]+>
在一个ATTLIST 中可以定义同一个元素下的一个或多个属性。如果包含多个属性声明,属性声明之间使用空格间隔。
- 元素名称:属性所属的元素名称
- 属性名:属性名称
- 属性类型:属性的值类型,
- 约束:元素对属性的约束
修饰符 | 含义 |
---|---|
#REQUIRED | 表示该属性是必需的,不能没有 |
#IMPLIED | 表示该属性可以有也可以没有 |
#FIXED | 表示在XML文档中只会给出一个元素属性所定义的固定值。只有当约束为该值时,才能给出缺省值,注意缺省值必须给出 |
- 定义示例:
<? xml version="1.0" encoding="UTF-8"?>
<! DOCTYPE root[
<!ELEMENT root (#PCDATA)>
<!ATTLIST root reqParam CDATA #REQUIRED>
<!ATTLIST root impParam CDATA #IMPLIED
fixParam CDATA #FIXED "default value">
]>
<root reqParam = "required value">
</root>
- DTD中的ENTITY实体
- ENTITY 实体,在一个甚至多个XML文档中频繁使用某一条数据,我们可以预先定义一个这条数据的“别名”,即一个ENTITY,然后在这些文档中需要该数据的地方调用它。
- 实体分类关系图
-
通用内部解析实体
内部实体是最简单的一种实体,该实体的内容为字符串的文本内容。所有的内部实体都是解析实体。内部实体的语法格式如下:<!ENTITY 实体名称 "实体内容">
例如:
<!ENTITY one "one">
<!ENTITY two "&one; I am two">
- 实体名称:实体名称由DTD程序员自己定义,但必须满足唯一性,即不能重名。同时满足XML的命名规范。
- 实体内容:所需要表达的文本内容。
-
通用外部解析实体
定义外部解析实体的语法如下:
<!ENTITY 实体名称 SYSTEM|PUBLIC ["公共实体标识符"] "URI/URL">
- URI/URL:所引用的外部文件的路径地址,被引用的外部文件必须是可以被解析的,扩展名没有限制。
- 实体为PUBLIC时才会有相应的“公共实体标识符” ,如果为SYSTEM则没有“公共实体标识符”.
实例如下:<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE aa[ <!ELEMENT aa (#PCDATA)> <!ELEMENT copyright SYSTEM "outer.txt"> ]> <aa>©right; </aa>
-
通用外部未解析实体:
<!ENTITY 实体名称 SYSTEM “URL/URL” NDATA 标记名>
URI/URL:所引用的外部文件的路径地址
标记名:被定义的符号的名称。
实例代码:
<!ENTITY PICTURE SYSTEM 'pic.jpg' NDATA msp>
-
参数内部解析实体
参数实体和普通实体只能在XML文档中引用,如果需要在DTD中使用实体则必须使用参数实体
声明参数内部解析实体的语法:
<!ENTITY % 参数实体名称 "实体内容">
参数实体名称:实体名称由DTD程序员自己定义,但必须满足唯一性,即不能重名。同时满足XML的命名规范。
实体内容:所需要表达的文本内容。 -
参数外部解析实体
声明参数外部解析实体的语法:
<!ENTITY % 参数实体名称 SYSTEM “URL/URL”>
URI/URL:所引用的外部文件的路径地址
引用参数实体的语法:
%参数实体名称;
-
- DTD符号
普通符号的语法格式:
<!NOTATION 符号名称 SYSTEM | PUBLIC ["公共符号标识符"] "URI\URL">
- 符号名称:名称由DTD程序员自己定义,但必须满足唯一性,即不能重名。同时满足XML的命名规范
- URI\URL:外部来处理这些未解析数据的程序路径
- 符号为PUBLIC时才会有相应的“公共符号标识符” ,如果为SYSTEM则没有“公共符号标识符”
DTD定义格式缺点
- DTD本身是基于正则表达式的,描述能力相对较弱。
- DTD不支持数据类型,对数据的约束不够准确。
- DTD约束能力不足,无法对语义作出更精细的语义限制。
- DTD的结构不够好,可重用性较差。