XML与DTD

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文件,接着定义相应的DTD文件,并在XML中添加引用
<?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(空)、子元素类型、混合型、ANY(任意)和#PCDATA五种类型。元素和混合类型的括号内指定了元素的内容,称为内容规范。

元素声明分类

常见的元素类型有五种,但元素声明的种类不止五种,具体分类如下:
  • 声明空元素
空元素使用EMPTY来定义,改元素只能有属性而不会有字符数据或子元素,语法如下:
<!ELEMENT 元素名 EMPTY>
例如:<!ELEMENT 员工 EMPTY>
  • 声明只有PADATA(字符数据)的元素
PCDATA类型的元素不包含其他任何元素,只包含字符数据(即文本数据)的元素,语法如下:
<!ELEMENT 元素名 (#PCDATA)>
  • 声明可以包含任何内容的元素
包含任何内容的元素声明类型为ANY,可以包含任何可解析数据的组合,如DTD中定义的其他任何元素或已编译的字符数据,包括PCDATA、元素或元素和PCDATA的混合内容,语法如下:
<!ELEMENT 元素名 ANY>
  • 声明带有子元素的元素
父元素声明用于指定某个元素可以包含哪些子元素以及出现次序,语法如下:
<!ELEMENT 元素名 (子元素列表)>
根据子元素间的关系,子元素内容模型可以有两种可能的结构:序列和选择。
(1)序列
序列结构用于描述根元素下,必须要出现的子元素,如下所示:
<!ELEMENT 员工 (姓名,性别)>
(2)选择
选择结构定义了根元素下的可选元素。如下所示:
<!ELEMENT 出行 (步行|公交)>
该声明表示根元素出行必须包含子元素公交或子元素步行,但不能同事包含两个。
  • 声明子元素
  • 声明只出现一次的元素
  • 声明至少出现一次的元素
  • 声明混合类型元素

元素指示符

元素的频率即出现的次数使用加号“+”、星号“*”、问号“?”来指定,其表示如下:
字符 出现次数
+ >=1
* >=0
? 0或1
  • 声明只出现一次的元素
<!ELEMENT 元素名称 (子元素名称)>
  • 声明至少出现一次的元素
<!ELEMENT 元素名称 (子元素名称+)>
  • 声明出现零次或多次的元素
<!ELEMENT 元素名称 (子元素名称*)>
  • 声明出现零次或一次的元素
<!ELEMENT 元素名称 (子元素名称?)>
  • 声明混合型的内容
<!ELEMENT note (#PCDATA|to|from|hrader|message)*>

属性

在DTD中,属性声明使用ATTLIST属性列表声明指定元素的属性列表,语法如下:
<!ATTLIST 元素名 属性名 属性类型 属性限定条件>

属性类型:

属性类型 含义
CDATA 字符数据,即没有标记的文本
枚举 被选属性值的值列表
ID 该属性在文档中具有唯一性
IDREF 文档中元素的ID类型属性的值
IDREFS 由空格分隔的元素的多个ID
ENTITY 在DTD中声明的实体的名称
ENTITIES 在DTD中声明的由空格分隔的多个实体的名称
NMTOKEN XML名称标记
NMTOKENS 由空格分隔的多个XML名称标记
NOTATION 在DTD中声明的记法的名称

属性附加声明:

属性默认值 含义
#REQUIRED 元素的每个实例必须具有该属性
#IMPLIED 元素实例不需要包含该属性
#FIXED+固定值 属性值被指定为固定值,用户不能改变该属性值
默认值 如果元素中不包含该属性值,那么默认值将作为属性值

例如:声明指定name元素具有id属性,该属性的类型为CDATA,每个name实例元素必须具有id属性
<!ATTLIST name id CDATA #REQUIRED>

DTD引用

引用内部DTD

前面介绍,均使用内部DTD

引用外部DTD

使用外部DTD时,要在DOCTYPE中使用SYSTEM或PUBLIC关键字,来指定外部DTD位置。
  • 使用SYSTEM关键字主要用于引用一个作者或组织所编写的众多XML文化中通用的DTD文件
  • 使用PUBLIC关键字引用外部DTD文件的基本语法格式中DTD-URL被称为FPI(正式公用标识符),也称作实体的“publicId”
除了使用 SYSTEM和PUBLIC指定外部DTD的位置以外,XML中需要以standalone="no"来表示该文档引用的是外部DTD
例如:定义一个DTD文件和XML文件,来描述水果和季节的信息
(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的包含关系可以将实体分为内部实体和外部实体。
内部实体是实体的内容已经包含在DTD文件本身中,如下所示:
<!ENTITY hello "How are you,&amp; 你好">
该实体的内容是“How are you,& 你好”。
外部实体的内容是通过URI引进DTD以外的其他文件。如下所示:
<!ENTITY img SYSTEM "temp.jpg">
<!ENTITY img PUBLIC "-//ISO9//ME/IMG/EN" "temp.jpg">	
若想引用上述实体,则如 &hello; 与&img;

对于public格式,语法如下:
<!ENTITY name PUBLIC FPI "URI">	
FPI的格式为:
"前缀//使用者标识//文本类/文本描述/所用语言"
FPI的详细介绍如下:
  • 前缀:前缀为“+”(注册公共标识)或“-”(未注册公共标识)
  • 使用者标识:标识拥有这个公共标识的个人或组织。注册可以确保使用者标识的唯一性
  • 文本类:文本类表明和公共标识相联系的文本类型。常见的有XML文档或DTD
  • 文本描述:有关文档的描述,不可以包含“//”字符串
  • 语言:文档使用的语言

参数实体

使用参数实体的DTD是放到一个单独的文件中,是因为在XML内部DTD中,参数实体引用不能在标记声明内部出现。语法如下:
<!ENTITY % name PUBLIC FPI "URI">	
例如:
<?xml version="1.0" encoding="UTF-8"?>
<!ENTITY % 介绍 "(生产日期,库存量)">
<!ELEMENT PC机 %介绍;>
<!ELEMENT 生产日期 (#PCDATA)>
<!ELEMENT 库存量 (#PCDATA)>







猜你喜欢

转载自blog.csdn.net/zzhao114/article/details/70929522