DTD简介
DTD(Document Type Definition,文档类型定义)的作用是定义XML文档的合法构建模块。DTD使用一系列的合法构成成员来定义文档结构。
DTD构成
DTD可以在XML文档中直接写入,也可以单独形成文档。因此,DTD分为外部DTD和内部DTD两种。外部DTD就是已经编辑好的可以被不同的XML文档共享和调用的DTD,内部DTD就是在XML文档中直接设定DTD。
文档类型声明以<!DOCTYPE 为开始,以 ]> 结束。通常将开始和结束放在不同的行上,文档类型定义的内部子集(即内部DTD)的语法格式为:
<!DOCTYPE 根元素名称[ <!ELEMENT 子元素名称 (#PCDATA)> ]>
- <!DOCTYPE :关键字,表示定义DTD,必须大写
- 根元素名:一个XML文档只有一个根元素。如果XML文档使用DTD,那么文档中的根元素名就在内部子集中指定。
- <!ELEMENT 子元素名称 (#PCDATA)>:定义文档的构成元素
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE 员工[ <!ELEMENT 员工 (李亮,张合) > <!ELEMENT 李亮 (性别,出生日期) > <!ELEMENT 张合 (性别,出生日期) > <!ELEMENT 性别 (#PCDATA) > <!ELEMENT 出生日期 (#PCDATA) > ]> <员工> <李亮> <性别>男</性别> <出生日期>1993.1.1</出生日期> </李亮> <张合> <性别>男</性别> <出生日期>1992.1.1</出生日期> </张合> </员工>
元素声明
元素是XML文档的核心部分,声明的语法格式如下:<!ELEMENT 元素名 EMPTY/(子元素内容)/(混合内容)/ANY/#PCDATA >
- !ELEMENT:关键字
- 元素名:文档中根元素下所包含的子元素名称,在DTD中通常称为基本表示符
元素声明分类
常见的元素类型有五种,但元素声明的种类不止五种,具体分类如下:
- 声明空元素
空元素使用EMPTY来定义,改元素只能有属性而不会有字符数据或子元素,语法如下:
<!ELEMENT 元素名 EMPTY>例如:<!ELEMENT 员工 EMPTY>
- 声明只有PADATA(字符数据)的元素
PCDATA类型的元素不包含其他任何元素,只包含字符数据(即文本数据)的元素,语法如下:
<!ELEMENT 元素名 (#PCDATA)>
- 声明可以包含任何内容的元素
包含任何内容的元素声明类型为ANY,可以包含任何可解析数据的组合,如DTD中定义的其他任何元素或已编译的字符数据,包括PCDATA、元素或元素和PCDATA的混合内容,语法如下:
<!ELEMENT 元素名 ANY>
- 声明带有子元素的元素
父元素声明用于指定某个元素可以包含哪些子元素以及出现次序,语法如下:
(1)序列
序列结构用于描述根元素下,必须要出现的子元素,如下所示:
<!ELEMENT 员工 (姓名,性别)>(2)选择
选择结构定义了根元素下的可选元素。如下所示:
<!ELEMENT 出行 (步行|公交)>该声明表示根元素出行必须包含子元素公交或子元素步行,但不能同事包含两个。
- 声明子元素
- 声明只出现一次的元素
- 声明至少出现一次的元素
- 声明混合类型元素
元素指示符
元素的频率即出现的次数使用加号“+”、星号“*”、问号“?”来指定,其表示如下:
在DTD中,属性声明使用ATTLIST属性列表声明指定元素的属性列表,语法如下:
字符 | 出现次数 |
+ | >=1 |
* | >=0 |
? | 0或1 |
- 声明只出现一次的元素
- 声明至少出现一次的元素
- 声明出现零次或多次的元素
- 声明出现零次或一次的元素
- 声明混合型的内容
<!ELEMENT note (#PCDATA|to|from|hrader|message)*>
属性
属性类型 | 含义 |
CDATA | 字符数据,即没有标记的文本 |
枚举 | 被选属性值的值列表 |
ID | 该属性在文档中具有唯一性 |
IDREF | 文档中元素的ID类型属性的值 |
IDREFS | 由空格分隔的元素的多个ID |
ENTITY | 在DTD中声明的实体的名称 |
ENTITIES | 在DTD中声明的由空格分隔的多个实体的名称 |
NMTOKEN | XML名称标记 |
NMTOKENS | 由空格分隔的多个XML名称标记 |
NOTATION | 在DTD中声明的记法的名称 |
属性附加声明:
属性默认值 | 含义 |
#required | 元素的每个实例必须具有该属性 |
#IMPLIED | 元素实例不需要包含该属性 |
#FIXED+固定值 | 属性值被指定为固定值,用户不能改变该属性值 |
默认值 | 如果元素中不包含该属性值,那么默认值将作为属性值 |
<!ATTLIST name id CDATA #required>
DTD引用
引用内部DTD
前面介绍,均使用内部DTD
引用外部DTD
使用外部DTD时,要在DOCTYPE中使用SYSTEM或PUBLIC关键字,来指定外部DTD位置。
除了使用
SYSTEM和PUBLIC指定外部DTD的位置以外,XML中需要以standalone="no"来表示该文档引用的是外部DTD
(1)定义DTD文件xmldtd.dtd
<?xml version="1.0" encoding="UTF-8"?> <!ELEMENT 水果与季节 (季节+,水果+) > <!ELEMENT 季节 (#PCDATA) > <!ATTLIST 季节 id ID #required > <!ATTLIST 季节 名称 CDATA #required > <!ELEMENT 水果 (#PCDATA) > <!ATTLIST 水果 f_id IDREF #required > <!ATTLIST 水果 名称 CDATA #required >(2 )定义对应的XML文件标记,并引用上述DTD文件
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE 水果与季节 SYSTEM "xmldtd.dtd"> <水果与季节> <季节 id="f1" 名称="春天"></季节> <季节 id="f2" 名称="夏天"></季节> <水果 f_id="f1" 名称="草莓"></水果> <水果 f_id="f2" 名称="西瓜"></水果> </水果与季节>
混合引用DTD
如果XML文件同时带有内部DTD和外部DTD文件,那么XML解析器会将二者合一。语法如下
<!DOCTYPE 根标记名 SYSTEM "URI" [ 内部DTD内容 ]>或
<!DOCTYPE 根标记名 PUBLIC FPI "URI" [ 内部DTD内容 ]>将上述实例保持DTD不变,修改其XML文件,同时使用内部和外部DTD,增加水果元素的属性:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE 水果与季节 SYSTEM "xmldtd.dtd" [ <!ATTLIST 水果 性味 CDATA #required> ]> <水果与季节> <季节 id="f1" 名称="春天"></季节> <季节 id="f2" 名称="夏天"></季节> <水果 f_id="f1" 名称="草莓" 性味="性凉"></水果> <水果 f_id="f2" 名称="西瓜" 性味="性寒"></水果> </水果与季节>
实体声明与引用
普通实体
实体基本意思是指与XML文档相关的存储单元。根据实体内容与DTD的包含关系可以将实体分为内部实体和外部实体。
<!ENTITY img PUBLIC "-//ISO9//ME/IMG/EN" "temp.jpg">
若想引用上述实体,则如 &hello; 与&img;
对于public格式,语法如下:
<!ENTITY name PUBLIC FPI "URI">
FPI的格式为:
"前缀//使用者标识//文本类/文本描述/所用语言"
FPI的详细介绍如下:
- 前缀:前缀为“+”(注册公共标识)或“-”(未注册公共标识)
- 使用者标识:标识拥有这个公共标识的个人或组织。注册可以确保使用者标识的唯一性
- 文本类:文本类表明和公共标识相联系的文本类型。常见的有XML文档或DTD
- 文本描述:有关文档的描述,不可以包含“//”字符串
- 语言:文档使用的语言
参数实体
例如:
<?xml version="1.0" encoding="UTF-8"?> <!ENTITY % 介绍 "(生产日期,库存量)"> <!ELEMENT PC机 %介绍;> <!ELEMENT 生产日期 (#PCDATA)> <!ELEMENT 库存量 (#PCDATA)>