文档类型定义(DTD)可定义合法的XML文档构建模块
它使用一系列合法的元素来定义文档的结构
优点
通过 DTD,每一个 XML 文件均可携带一个有关其自身格式的描述。
通过 DTD,独立的团体可一致地使用某个标准的 DTD 来交换数据。
而您的应用程序也可使用某个标准的 DTD 来验证从外部接收到的数据。
您还可以使用 DTD 来验证您自身的数据。
声明
DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用
内部声明
假如 DTD 被包含在 XML 源文件中,它应当通过下面的语法包装在一个 DOCTYPE 声明中:
| 1 | <!DOCTYPE root-element [element-declarations]> | 
例如
| 1 | <?xml version="1.0"?> | 
以上 DTD 解释如下:
- !DOCTYPE note (第二行)定义此文档是 note 类型的文档。
- !ELEMENT note (第三行)定义 note 元素有四个元素:”to、from、heading,、body”
- !ELEMENT to (第四行)定义 to 元素为 “#PCDATA” 类型
- !ELEMENT from (第五行)定义 from 元素为 “#PCDATA” 类型
- !ELEMENT heading (第六行)定义 heading 元素为 “#PCDATA” 类型
- !ELEMENT body (第七行)定义 body 元素为 “#PCDATA” 类型
外部声明
假如 DTD 位于 XML 源文件的外部,那么它应通过下面的语法被封装在一个 DOCTYPE 定义中:
| 1 | <!DOCTYPE root-element SYSTEM "filename"> | 
例如
| 1 | <?xml version="1.0"?> | 
note.dtd
| 1 | <!ELEMENT note (to,from,heading,body)> | 
XML构建模块
XML 和 HTML文档主要的构建模块是元素标签
所有的 XML 文档(以及 HTML 文档)均由以下简单的构建模块构成:
- 元素 - 元素是 XML 以及 HTML 文档的主要构建模块。 - HTML 元素的例子是 “body” 和 “table”。XML 元素的例子是 “note” 和 “message” 。元素可包含文本、其他元素或者是空的。空的 HTML 元素的例子是 “hr”、”br” 以及 “img” - 例如: - 1 
 2- <body>some text</body> 
 <message>some text</message>
- 属性 - 属性可提供有关元素的额外信息。 - 属性总是被置于某元素的开始标签中。属性总是以名称/值的形式成对出现的。下面的 “img” 元素拥有关于源文件的额外信息: - 1 - <img src="computer.gif" /> - 元素的名称是 “img”。属性的名称是 “src”。属性的值是 “computer.gif”。由于元素本身为空,它被一个 “ /“ 关闭 
- 实体 - 实体是用来定义普通文本的变量。实体引用是对实体的引用。 - 大多数同学都了解这个 HTML 实体引用:” (破坏实体);”。这个”无折行空格”实体在 HTML 中被用于在某个文档中插入一个额外的空格。 - 当文档被 XML 解析器解析时,实体就会被展开。 - 例如: - <(破坏实体);的对应字符为< - >(破坏实体);的对应字符为> - &(破坏实体);的对应字符为& - "(破坏实体);的对应字符为” - &apos(破坏实体);的对应字符为’ 
- PCDATA - PCDATA 的意思是被解析的字符数据(parsed character data)。 - 可把字符数据想象为 XML 元素的开始标签与结束标签之间的文本。 - PCDATA 是会被解析器解析的文本。这些文本将被解析器检查实体以及标记。 - 文本中的标签会被当作标记来处理,而实体会被展开。 - 不过,被解析的字符数据不应当包含任何 &、< 或者 > 字符;需要使用 &(破坏实体);、<(破坏实体); 以及 >(破坏实体); 实体来分别替换它们。 
- CDATA - CDATA 的意思是字符数据(character data)。 - CDATA 是不会被解析器解析的文本。在这些文本中的标签不会被当作标记来对待,其中的实体也不会被展开 
DTD元素
在一个 DTD 中,元素通过元素声明来进行声明
元素声明使用下面的语法:
| 1 | <!ELEMENT element-name category> | 
空元素通过类别关键词EMPTY进行声明
| 1 | <!ELEMENT element-name EMPTY> | 
只有 PCDATA 的元素通过圆括号中的 #PCDATA 进行声明:
| 1 | <!ELEMENT element-name (#PCDATA)> | 
通过类别关键词 ANY 声明的元素,可包含任何可解析数据的组合:
| 1 | <!ELEMENT element-name ANY> | 
带有一个或多个子元素的元素通过圆括号中的子元素名进行声明:
| 1 | <!ELEMENT element-name (child1)> | 
当子元素按照由逗号分隔开的序列进行声明时,这些子元素必须按照相同的顺序出现在文档中。在一个完整的声明中,子元素也必须被声明,同时子元素也可拥有子元素。”note” 元素的完整声明是:
| 1 | <!ELEMENT note (to,from,heading,body)> | 
声明只出现一次的元素
| 1 | <!ELEMENT element-name (child-name)> | 
上面的例子声明了:message 子元素必须出现一次,并且必须只在 “note” 元素中出现一次
声明最少出现一次的元素
| 1 | <!ELEMENT element-name (child-name+)> | 
上面的例子中的加号(+)声明了:message 子元素必须在 “note” 元素内出现至少一次
声明出现零次或一次的元素
| 1 | <!ELEMENT element-name (child-name?)> | 
上面的例子中的问号(?)声明了:子元素 message 可在 “note” 元素内出现零次或一次
声明出现零次或多次的元素
| 1 | <!ELEMENT element-name (child-name*)> | 
上面的例子中的星号(*)声明了:子元素 message 可在 “note” 元素内出现零次或多次
声明“非···/即···”类型的内容
| 1 | 实例: | 
声明混合型的内容
| 1 | 实例: | 
上面的例子声明了:”note” 元素可包含出现零次或多次的 PCDATA、”to”、”from”、”header” 或者 “message”
DTD属性
在 DTD 中,属性通过 ATTLIST 声明来进行声明
示例:
| 1 | <!ATTLIST element-name attribute-name attribute-type attribute-value> | 
属性的类型
| 类型 | 描述 | ||
|---|---|---|---|
| CDATA | 值为字符数据 (character data) | ||
| (en1\ | en2\ | ..) | 此值是枚举列表中的一个值 | 
| ID | 值为唯一的 id | ||
| IDREF | 值为另外一个元素的 id | ||
| IDREFS | 值为其他 id 的列表 | ||
| NMTOKEN | 值为合法的 XML 名称 | ||
| NMTOKENS | 值为合法的 XML 名称的列表 | ||
| ENTITY | 值是一个实体 | ||
| ENTITIES | 值是一个实体列表 | ||
| NOTATION | 此值是符号的名称 | ||
| xml: | 值是一个预定义的 XML 值 | 
默认属性值可用以下值
| 值 | 解释 | 
|---|---|
| 值 | 属性的默认值 | 
| #REQUIRED | 属性值是必需的 | 
| #IMPLIED | 属性不是必需的 | 
| #FIXED value | 属性值是固定的 | 
例如:
| 1 | DTD: | 
在上面的例子中,”square” 被定义为带有 CDATA 类型的 “width” 属性的空元素。如果宽度没有被设定,其默认值为0
#REQUIRED
语法
| 1 | <!ATTLIST element-name attribute-name attribute-type #REQUIRED>· | 
示例:1
2
3
4
5
6
7
8DTD:
<!ATTLIST person number CDATA #REQUIRED>
合法的 XML:
<person number="5677" />
非法的 XML:
<person />
#IMPLED
语法
| 1 | <!ATTLIST element-name attribute-name attribute-type #IMPLIED> | 
示例:
| 1 | DTD: | 
#FIXED
语法
| 1 | <!ATTLIST element-name attribute-name attribute-type #FIXED "value"> | 
实例
| 1 | DTD: | 
列举属性值
语法
| 1 | <!ATTLIST element-name attribute-name (en1|en2|..) default-value> | 
实例
| 1 | DTD: | 
如果您希望属性值为一系列固定的合法值之一,请使用列举属性值。(男|女)
元素&属性
xml中数据可以存储在子元素或属性中
例:
| 1 | <person sex="female"> | 
| 1 | <person> | 
没有特别规定何时使用属性,以及何时使用子元素。
一些属性具有以下问题:
- 属性不能包含多个值(子元素可以)
- 属性不容易扩展(为以后需求的变化)
- 属性无法描述结构(子元素可以)
- 属性更难以操纵程序代码
- 属性值是不容易测试,针对DTD
如果您使用属性作为数据容器,最终的XML文档将难以阅读和维护。 尝试使用元素来描述数据。只有在提供的数据是不相关信息时我们才建议使用属性。
例外:唯一标识符ID
| 1 | <messages> | 
以上实例的XML文件中,ID是只是一个计数器,或一个唯一的标识符,来识别不同的音符,而不是作为数据的一部分。
在这里我想说的是,元数据(关于数据的数据)应当存储为属性,而数据本身应当存储为元素。
实体
实体是用于定义引用普通文本或特殊字符的快捷方式的变量。
- 实体引用是对实体的引用。
- 实体可在内部或外部进行声明。
内部声明
语法
| 1 | <!ENTITY entity-name "entity-value"> | 
注意: 一个实体由三部分构成: 一个和号 (&), 一个实体名称, 以及一个分号 (;)。
外部声明
语法
| 1 | <!ENTITY entity-name SYSTEM "URI/URL"> | 
验证
当您试图打开某个 XML 文档时,XML 解析器有可能会产生错误。通过访问 parseError 对象,就可以取回引起错误的确切代码、文本甚至所在的行。