转自:http://blog.csdn.net/skyer518/article/details/37904759
文档类型定义(DTD)可定义合法的XML文档构建模块。它使用一系列合法的元素来定义文档的结构。
DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用。
DTD是一套关于标记的语法规则,它定义了文档的逻辑结构,规定了文档中所使用的元素、实体、元素的属性、元素与实体之间的关系。DTD告诉你可以在哪些文档中使用哪些标记,各标记出现的次序,哪些标记出现在哪些标记中,哪些标记有属性等等。
DTD是XML文件的验证机制,定义好DTD,就可以使用XML解析器对编写好的XML文档进行DTD检查,判断XML文档内容是否为有效的XML文档内容。
用DTD提供统一格式。例如,用DTD规定个人简历文档的逻辑结构,包括所需填写内容和内容排列方式,所有按照这个DTD编写的个人简历都将具有统一格式。
用DTD验证数据有效性。DTD约束文档逻辑结构,可以根据DTD检查数据,验证其是否符合规定要求,确保数据正确和有效。
根据DTD编写文档样式单。DTD能在不提供原始资料的情况下,表示出一个网页或文档的架构元素,这意味着用户能先根据DTD为未来的文档编写样式单,然后再安全且不破坏结构的把用户的资料放上去,提高工作效率
DTD分类:
内部DTD:是指DTD与XML数据定义放在同一份文档中,即将DTD定义在XML文档内部。内部DTD紧跟在XML声明和处理指令之间。
<!DOCTYPE 根元素 [元素声明]>
文档类型声明以“<!DOCTYPE>” 开始,以“]>”结束。在XML处理指令和根元素之间定义。
standalone=“yes”表明了该文档 不依赖外部DTD文件
外部DTD:外部文件类型定义存在于独立文件中,文件扩展名为“.dtd”。外部DTD的好处是:可以方便地被多个XML文档共享,只需要定义一份DTD文档,即可为多个XML文档定义语义约束。为了让DTD能支持非西欧字符,应该为外部DTD文档指定声明,DTD声明和XML声明的语法完全相同。
<!DOCTYPE 根元素 SYSTEM "文件名">
公用DTD:有一种外部DTD,是由某个权威机构制定,供特定行业或公司,这种DTD又被称为公用DTD
公用DTD与外部DTD区别在于:公用DTD使用PUBLIC代替了原来的SYSTEM,并增加了DTD标识名。
DTD文档的结构
DTD文档并不是XML文档,而只是为XML定义语义约束的文档。DTD文档有如下结构:
DTD的结构一般由以下四种声明构成:
1、元素类型声明
2、属性列表声明
3、实体声明
4、记号声明
DTD对元素声明
使用ELEMENT声明XML元素的语法
<!ELEMENT 元素名称 (元素内容) > 或 <!ELEMENT 元素名称 类别>
元素声明以“<!”开始,以“>”结束
元素声明指令“ELEMENT”为关键字,必须大写
元素名:为当前元素指定的元素名称
元素内容: 元素名后面的内容用来指定元素的内容类型,它可以分为EMPTY(空)、子元素类型,混合型、ANY(任意)和#PCDATA 5种类型。
空元素类型―EMPTY:该元素只可能有属性不能有元素内容
空元素通过类别关键词EMPTY进行声明:
<!ELEMENT 元素名称 EMPTY>例子:
XML例子:
定义任意类型的元素:ANY是DTD中使用很频繁的一个关键字,特别是对于文档根元素的声明。在定义一个DTD文档时通常很难准确地确定一个元素是否具有子元素的情况,此时一般的做法是指定该元素的子元素为ANY型(表示可以是任意的元素),这样在它之中可以包含任何数据、任何声明的子元素及其数据和子元素的组合。如果需要定义某个元素的值可以是任意类型。
通过类别关键词 ANY 声明的元素,可包含任何可解析数据的组合:
<!ELEMENT 元素名称 ANY>例子:
DTD必须定义XML文档中允许出现的所有元素。由此可见,虽然XML文档允许开发者自由扩展各种标签,但一旦使用DTD为其增加了语义约束,该XML文档就只能出现在DTD中定义过的元素。
定义混合内容元素:某个元素既有字符串内容,又包含子元素,被称为混合内容的元素。一般来说,XML文档不推荐使用混合内容的元素。
1. #PCDATA必须放在最前面
2. #PCDATA和各子元素之间只能用竖线(|)分割
3. 子元素1,子元素2和子元素3之间的竖线(|)并不是表示互斥,而只是表 示这些元素能无序的重复出现,而且次数不受限制
4. 不能在各个子元素之后添加?,*。+等表示频率的修饰符
定义子元素:元素包含子元素是XML文档中最常见的情形,DTD可以有效地定义各元素之间的父子关系,从而有效地描述整个文档结构。定义元素包含的子元素时,各个元素之间存在几种逻辑关系:有序的子元素、互斥的子元素、无序的子元素。
有序的子元素:用英文逗号(,)作为子元素之间的分隔符,则子元素之间必须遵守所定义的顺序。
互斥的子元素:互斥的子元素表明一系列子元素之间只能出现其中一次。互斥子元素使用竖线(|)分隔,以竖线(|)分隔的多个元素只能出现其中之一。
子元素出现的频率:子元素的出现频率通过在元素声明后紧跟一个表
示频率的特殊标记来表示,DTD中表示频率的特殊
标记有3个:
+: 表明子元素可以出现1次或多次
*: 表明子元素可以出现0次或多次
?: 表明子元素可以出现0次或1次
如果在定义子元素时,没有在子元素后指定任何表示频率的特殊标记,则表明这些子元素只能出现一次,且必须一次。
无序的子元素:从理论上讲,DTD没有专门为定义无序子元素提供语法,如果希望使用DTD来表示某个元素之内可以接受无序的子元素。
DTD对属性声明
属性是描述元素的额外信息的,是对元素的修饰与补充。一般来说,信息详实的XML文档都是一个特点,即元素通过属性来描述边缘信息。
在 DTD 中,属性通过 ATTLIST 声明来进行声明。一个属性声明可以声明一个元素的多个属性。
语法 <!ATTLIST 元素名称 属性名称 属性类型 无素限制条件 默认值>
对属性的限定条件:
#REQUIRED: 必须的属性,意味着必须为该元素提供该属性
#IMPLIED: 该属性是可有可无的
#FIXED: 该属性的值是固定的,定义是必须制定固定值。使用该元素时无需为其分配该属性,XML处理器会自动为给属性增加固定值
“属性限定条件”和“默认值‘两部分是可选行,有下面几种情况
1.在没有指定“元素对属性的约束”时,必须为该属性指定“默认值”;
2.当“元素对属性的约束”是#REQUIRED时,不能为该属性指定“默认值”;
3.当“元素对属性的约束”是“IMPLIED”时,不能为该属性指定“默认值”;
4.当“元素对属性的约束”是“FIXED”时,必须为该属性指定“默认值”
属性类型:
属性类型 | 含义 |
CDATA | 值为字符串数据 |
(en1|en2|..) | 此值是枚举列表中的一个值 |
ID | 该属性值必须是有效地标识符,在XML文档时唯一的 |
IDREF | 值为另外一个元素的 id属性值 |
IDREFS | 值必须引用自多个已经有的ID属性值,多个ID属性值用空格隔开 |
NMTOKEN | 值为合法的 XML 名称 |
NMTOKENS | 值为多个合法的 XML 名称的列表 |
ENTITY | 值是一个外部实体,如图片支持 |
ENTITIES | 值是一个实体列表,多个实体之间以空格隔开 |
xml: | 值是一个预定义的 XML 值 |
NOTATION | 该属性值是在DTD中声明过的符号,这个是过期的,不要使用 |
字符类型:CDATA 是简单的纯文本字符类型,是最常用的类型,将简单的文本用做属性值。可以包括任何字符串,但不允许使用“<”,“>”,“&”,“””,“‘”。如果需要使用必须使用实体引用。属性值和元素内容都可以是文本类型,但是定义的方法不同
枚举类型:声明了属性的备选值列表,属性必须从该列表中选择一个值作为属性值。
ID、IDREF、 IDREFS类型:ID类型是一种较为严格的约束,它要求属性值必须是有效地XML标识名,而且在整个XML文件档中其值不能重复。
NMTOKEN和NMTOKENS类型:NMTOKEN是一个比ID类型更宽松的类型,它只要求该属性是个合法的XML标识。它也是字符串数据,但是约束比CDATA约束要严格,它要求出现的字符要少。
一旦声明某个属性的类型是entity或entities,就意味着该属性值只能是一个或多个未解析的实体,而不是已经解析的实体。对于未解析的实体而言,不能通过普通实体引用方式去引用,他们只能作为entity或entities类型的属性值。
定义实体:
实体引用就是用一个字符串代替另一个字符串。定义实体有如下作用:
1.提高代码的服用,方便修改,维护XML文档
2.使用某些特殊的符号,这些特殊的符号可能会使XML解析器混淆
3.减少字符输入量,如果某个字符串特别长,而且需要经常使用,则可以定义为实体
实体的概念:实体是包含了文档片段的虚拟存储单元,可用来存储XML声明、DTD、其他形式的文本及二进制数据等。简单来讲就是一段代码或数据的代称,这个代称即为实体的名字。
当需要在文档中引用某段代码或数据时,可以引用与这段代码或数据相对应的实体名称来代替实体的具体内容。具有正确性检查功能的XML处理器在提交文档给最终应用程序之前或在显示文档以前,将先把所有不同的实体引用替换为与其对应的具体内容,从而构成一个结构完整的文档。
实体的分类:
按照实体的具体内容来分类,实体可分为可解析与不可解析两类。可解析实体的具体内容为简单的字符、数字、文本块,而不可解析实体的具体内容则为图片、声音等二进制文件。
可解析:
不可解析:
语法 <!ENTITY 实体名 SYSTEM ''外部实体URI'' NDATA 实体格式>
按照逻辑存储来分类,实体可分为内部实体与外部实体两类。内部实体的内容是在文档内部设定的;而外部实体则是一个外部独立的物理存储对象,如某个外部文件。
内部实体定义 <!ENTITY 实体名称 "实体的值">
例子:
DTD 例子:
XML 例子:
注释: 一个实体由三部分构成: 一个和号 (&), 一个实体名称, 以及一个分号 (;)。
外部实体定义 <!ENTITY 实体名称 SYSTEM "URI/URL">
例子:
DTD 例子:
XML 例子:
按照使用的范围来分类,实体可分为一般实体与参数实体两类。一般实体都用来构成文档的具体内容,可出现在XML文档中,也可出现在DTD中;而参数实体只能出现在DTD中,不能出现在XML文档中。
参数实体与一般实体有如下不同:
1.在定义参数实体时,实体名称前必须加一个 "%"号
2.参数实体以"%"号开始,而不是一般实体引用的"&"
3.参数襟体的内容,不仅可以包括文本,还可以包括标记
4,参数实体只能应用于DTD,而不能在XML文档本体中引用
实体声明
在多个文档中都需调用的相同的内容,如:公司名称、版本声明等,为了避免重复输入这些内容,可以声明一个实体来表示这些内容,在文档中只需要引用这个实体,经过XML处理器对文档进行分析处理后,引用实体的位置会被实体的内容所替换(貌似和变量的效果是相同的)。
实体分两种:一般实体和参数实体。一般实体是在文档内容中使用的实体,而参数实体则是在DTD中使用的已分析的实体。这两种实体都是用ENTITY 关键字来声明。
1、 一般实体和参数实体
一般实体的声明语法为 : <!ENTITYE 实体名 “实体内容”> ; 引用实体的方式为:”&实体名;”。
此例子中声明了两个实体 names 和 copyrights,分别用来表示网站名称和版权声明信息。在声明实体 copyrights 时,我们通过字符引用的方式(©)来输入版权符号?。声明一个实体时,也可以使用另外的实体。这个例子在IE中的显示效果如图4-1 所示:
图 5-1
参数实体只能在DTD中使用,声明语法:<!ENTITY % 实体名 “实体内容”> %和ENTTY、实体名之间各有一个空格。引用实体的方式为:”%实体名;”
实例: test.dtd 中的代码:
test.xml 中的代码:
效果和图4-1相同(用Google浏览器报错,貌似是不支持)。
本例中的的DTD是放到一个单独的文件中,这是因为在内部DTD子集中,参数实体引用不能在标记声明内部出现(本例中dtd文件的最后一行,即%name 的用法在内部DTD中是非法的),可以在标记声明允许出现的地方出现。然而,对于外部DTD子集,则没有这个限制。
在内部DTD中,参数实体引用只能用于声明之外(即不能用在<!ENTITY >之中)。如下实例:
这个例子中,使用的是内部DTD子集,对参数实体的引用 (%cprt;) 出现在标记声明可以出现的位置,这是允许的。
本例中声明了一个参数实体cprt,它所表示的内容是一个元素声明,然后我们在声明之外,通过实体引用的方式(&cprt;)间接地对元素copyright进行了声明。
在DTD中,所有的参数实体必须在引用之前进行声明。这意味着内部DTD子集不能引用在外部DTD中 声明的参数实体,这是因为XML处理器将首先读取内部子集,也就是说,内部子集中的实体和属性表明的优先级要比在外部自己中的高。
2、内部实体和外部实体
内部实体在XML文档内部定义,实体的内容在声明中给出。内部实体都是已分析的实体,它们没有单独的物理存储对象。一般实体和参数实体,可以称为内部一般实体和内部参数实体。
外部实体在单独的(外部)件中定义,外部实体可以是已分析实体,也可以是未析实体。外部一般实体的声明如下:
<!ENTITY copyright SYSTEM http://hi.126.com/superfiresun/super.xml>
关键字SYSTEM表明这是一个私有的外部一般实体,后面的 URI 称为该实体的系统标识符,用于给出外部文件的位置。
假设 super.xml 文件的内容为:
<?xml version=”1.0” encoding=”gb2312”?> 为文本声明。文本声明类似于XML声明(不是XML声明),不过文本声明没有standalone属性,并且version属性也是可选的。外部已分析实体可以使用不同于UTF-8 的编码,使用文本声明来指明实体内容的编码方式。
每个外部已分析实体都应该以文本声明开始。文本声明只能在外部已分析实体的开头出现,不能出现在其他任何位置。在外部已分析实体中的文本声明不会作为替换文本的一部分而出现。
也可以使用PUBLIC 关键字来声明公共的外部一般实体,其声明形式和使用了关键字PUBLIC的外部DTD声明类似。如下:
“-//Textuality//TEXT Standard open-hatchboilerplate//EN” 称为该实体的公共标识符,后面的URI部分为该实体的系统标识符。
例:下面的例子声明了一个外部一般未分析实体。
与一般实体类似,参数实体的替换文本也可以位于外部文件中。其声明形式和一般实体类似。