声明:
本文部分DTD实例取自W3C教程。
CSDN不支持DTD高亮,使用的XML高亮。
DTD(文档类型定义)的作用是定义 XML 文档的合法构建模块。
它使用一系列的合法元素来定义文档结构。
// 内部声明
DOCTYPE 根元素 [元素声明]>
// 外部声明(本地和公共计算机)
// 本地计算机
<!ENTITY 实体名称 PUBLIC "publicID" "URI"> // 公共计算机
采用ELEMENT
标签对元素进行声明。元素可以包含文本(PCDATA)、子元素或为空(EMPTY)。
类别1:<!ELEMENT 元素名称 类别关键字>
或
类别2:<!ELEMENT 元素名称 (元素内容)> // 元素的内容可以是文本或元素
空元素属于类别1,EMPTY属于类型关键字。
<!ELEMENT 元素名称 EMPTY>
<!ELEMENT br EMPTY>
// 对应了HTML当中的<br />标签
属于类别1,ANY属于类别关键字。
<!ELEMENT 元素名称 ANY>
<!ELEMENT note ANY>
属于类别2,完整的PCDATA标签对应位置为元素内容,标签对当中可包含文本。
【内容】
<!ELEMENT 元素名称 (#PCDATA)>
<!ELEMENT from (#PCDATA)>
带有一个或多个子元素的元素,通过圆括号当中的子元素名称进行声明:
<!ELEMENT 元素名称 (子元素名称 1)>
<!ELEMENT 元素名称 (子元素名称 1,子元素名称 2,.....)>
多个子元素由按照逗号分割开的序列进行声明。其子元素必须按照相同的顺序出现在文档当中。
完整声明当中,子元素也必须声明。
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
下面按照子序列的形式进行细分,
<!ELEMENT 元素名称 (子元素名称)>
按照此种方法声明后,该元素在文档中必须出现一次且只出现一次。
<!ELEMENT 元素名称 (子元素名称+)>
按照此种方法声明后,该元素在文档中至少出现一次。
<!ELEMENT 元素名称 (子元素名称*)>
按照此种方法声明的子元素,可以出现零次或多次。
<!ELEMENT 元素名称 (子元素名称?)>
按照此种方法声明的子元素,可以出现零次或一次。
**(A|B)**即为此结构。
<!ELEMENT note (to,from,header,(message|body))>
分析:此元素必须包含的子元素有to,from,header,以及message|body当中一个。
<!ELEMENT note (#PCDATA|to|from|header|message)*>
可以出现多种类型的元素,且可以出现零次或多次。
属性可以提供有关元素的额外信息。
以名称/值的形式成对出现。
<!ATTLIST 元素名称 属性名称 属性类型 默认值>
类型 | 描述 |
---|---|
CDATA | 值为字符数据 (character data) |
(en1|en2|…) | 此值是枚举列表中的一个值 |
ID | 值为唯一的 id |
IDREF | 值为另外一个元素的 id |
IDREFS | 值为其他 id 的列表 |
NMTOKEN | 值为合法的 XML 名称 |
NMTOKENS | 值为合法的 XML 名称的列表 |
ENTITY | 值是一个实体 |
ENTITIES | 值是一个实体列表 |
NOTATION | 此值是符号的名称 |
xml: | 值是一个预定义的 XML 值 |
值 | 解释 |
---|---|
值 | 属性的默认值 |
#REQUIRED | 属性值是必需的 |
#IMPLIED | 属性不是必需的 |
#FIXED value | 属性值是固定的 |
一般的使用方法
<!ELEMENT square EMPTY>
<!ATTLIST square width CDATA "0">
<square width="100" /> 合法
“square” 被定义为带有 CDATA 类型的 “width” 属性的空元素。如果宽度没有被设定,其默认值为0。
#REQUIRED
<!ATTLIST 元素名称 属性名称 属性类型 #REQUIRED>
<Math num="1234" /> 合法
<Math /> 非法
#IMPLIED
<!ATTLIST 元素名称 属性名称 属性类型 #IMPLIED>
<Math num="1234" /> 合法
<Math /> 合法
#FIXED value
<!ATTLIST 元素名称 属性名称 属性类型 #FIXED "value">
<Company name="Microsoft" /> 合法
<Company name="Google" /> 非法
将属性值设定为固定的合法值之一。
<!ATTLIST 元素名称 属性名称 (en1|en2|..) 默认值>
<!ATTLIST payment type (check|cash) "cash">
<payment type="check" />
<payment type="cash" />
<!ATTLIST Student
age CDATA #IMPLIED
name CDATA #IMPLIED
class CDATA #REQUIRED
credit CDATA #REQUIRED>
实体用于定义引用不同文本和特殊字符的快捷方式的变量。
实体是用来定义普通文本的变量,实体引用是实体的引用。
实体可以在内部或外部进行声明。
当文档被 XML 解析器解析时,实体就会被展开。
有一些预留字符涉及到了DTD结构中的关键字符,他的出现会影响实体的正常解析,且容易造成注入攻击,因此需要预定义。
实体引用 | 字符 |
---|---|
< | < |
> | > |
& | & |
" | " |
' | ’ |
要注意的是,
<!ENTITY 实体名称 "实体的值">
外部实体可以支持多种协议,如HTTP、FILE等协议。如file://
可以在本地读取有权限读取的任意文件。
// 本地计算机
<!ENTITY 实体名称 PUBLIC "public_ID" "URI"> // 公共计算机
一个实体由三部分构成: 一个和号 (&), 一个实体名称, 以及一个分号 (。
<author>&writer;©right;author>
%file;
(参数实体)是在DTD中被引用的,而&file;
是在xml文档中被引用的。
仅在DTD文档当中使用的解析实体称为参数实体。
常用于针对DTD文档进行使用,方便我们容易的修改或维护DTD文档的结构,降低DTD文档的重复度。
声明关键字和实体,在解析时对文本进行替换以产生作用。
// 一个参数实体的声明格式
<!ENTITY % 参数实体名称 替换文本>
<!ENTITY % peopleParameters "age CDATA #IMPLIED weight CDATA #IMPLIED height CDATA #REQUIRED">
// 使用案例,将想引入的 %参数实体名称; 按此格式进行引用,可在解析式完成文本替换。
<!ATTLIST InsuredPerson %peopleParameters; carrier CDATA #REQUIRED >、
// 其替换结果等效于
<!ATTLIST InsuredPerson
age CDATA #IMPLIED
weight CDATA #IMPLIED
height CDATA #REQUIRED
carrier CDATA #REQUIRED>
与一般实体类似,参数实体的置换文本也可位于外部文件中。
此类声明中进行替换的替换形式只能用于DTD外部子集。
在内部子集中,参数实体引用只能位于其他声明当中:此类实体引用的值需要符合语法,否则将影响DTD格式的正规性。
PCDATA 的意思是被解析的字符数据(parsed character data)。
可把字符数据想象为 XML 元素的开始标签与结束标签之间的文本。
PCDATA 是会被解析器解析的文本。这些文本将被解析器检查实体以及标记。
文本中的标签会被当作标记来处理,而实体会被展开。
不过,被解析的字符数据不应当包含任何 &、< 或者 > 字符;需要使用 &、< 以及 > 实体来分别替换它们。
CDATA 的意思是字符数据(character data)。
*CDATA 是不会被解析器解析的文本。*在这些文本中的标签不会被当作标记来对待,其中的实体也不会被展开。
我们知道,在使用中,出现XML的预留字符(指&、<、>、"、’)时,需要使用转义字符进行替换。
除了这种方法之外,我们还可以采用CDATA来包含包含这些字符的文字段,以避免解析造成的错误。
其相对于转义字符存在优势
特别的,
]]>
不可包含空格]]>
作为CDATA标签的保留字符串,不可在标签内部出现。