DTD 教程(完整版,从零开始)
DTD(Document Type Definition,文档类型定义)是 XML 1.0 的原始模式语言,用于约束 XML 文档的结构,确保 XML 文档合法性。虽然现在更常用 XML Schema(XSD)或 RelaxNG,但很多遗留系统、HTML()、SVG、RSS、DocBook 等仍然依赖 DTD,理解 DTD 仍然非常重要。
1. DTD 基本概念
- DTD 定义了:哪些元素可以出现、元素出现的顺序、哪些属性元素可以有、属性的类型、默认值、实体等。
- DTD 可以有两种形式:
- 内部 DTD(写在 XML 文件内部)
- 外部 DTD(独立的 .dtd 文件)
2. 基本语法
<!ELEMENT 元素名 内容模型>
<!ATTLIST 元素名 属性名 属性类型 默认值>
<!ENTITY 实体名 "实体内容">
<!NOTATION 记法名 系统标识符>
3. 元素声明()
| 内容模型 | 含义 | 示例 |
|---|---|---|
| (#PCDATA) | 只能包含文本 | |
| EMPTY | 空元素 | |
| ANY | 可以包含任何内容(不推荐) | |
| 子元素 | 明确指定子元素 | |
| , | 顺序出现(必须按顺序) | (name, age, email) |
| 选择其中一个 | ||
| ? | 出现 0 或 1 次 | name? |
| * | 出现 0 或多次 | phone* |
| + | 出现 1 或多次 | phone+ |
| () | 分组 | (name |
示例:
<!ELEMENT bookstore (book+)>
<!ELEMENT book (title, author+, price, publish_date?)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT price (#PCDATA)>
<!ELEMENT publish_date (#PCDATA)>
4. 属性声明()
常用属性类型:
| 类型 | 说明 | 示例 |
|---|---|---|
| CDATA | 字符串 | |
| 枚举值 | 只能是列出的值之一 | (hardcover |
| ID | 唯一标识符(文档内唯一) | ID |
| IDREF/IDREFS | 引用某个 ID | IDREF |
| NMTOKEN/NMTOKENS | 合法的 XML 名令牌 | |
| ENTITY | 引用外部非解析实体 |
默认值关键字:
- #REQUIRED:必须出现
- #IMPLIED:可选
- #FIXED “值”:固定值
- “默认值”:提供默认值
示例:
<!ATTLIST book
id ID #REQUIRED
category CDATA "默认分类"
edition NMTOKEN #IMPLIED
lang (zh|en|ja) "zh"
cover (hard|soft) #FIXED "hard">
5. 实体()
- 内部实体:
<!ENTITY copy "© 2025 某某公司">
<!ENTITY nbsp " ">
- 外部实体(解析实体,常用于包含大段文本):
<!ENTITY chapter1 SYSTEM "chap1.xml">
- 参数实体(只能在 DTD 内部使用,用 % 开头):
<!ENTITY % common.attrs "id ID #IMPLIED class CDATA #IMPLIED">
<!ATTLIST div %common.attrs;>
6. 完整例子
1. 内部 DTD 示例(books.xml)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE bookstore [
<!ELEMENT bookstore (book+)>
<!ELEMENT book (title, author+, price)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT price (#PCDATA)>
<!ATTLIST book id ID #REQUIRED
category (IT|文学|经管) "IT">
]>
<bookstore>
<book id="b001" category="IT">
<title>XML 入门到精通</title>
<author>张三</author>
<author>李四</author>
<price>89.00</price>
</book>
</bookstore>
2. 外部 DTD 示例
books.dtd 文件内容:
<!ELEMENT bookstore (book+)>
<!ELEMENT book (title, author+, price)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT price (#PCDATA)>
<!ATTLIST book
id ID #REQUIRED
category CDATA #IMPLIED>
对应的 XML:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE bookstore SYSTEM "books.dtd">
<bookstore>
<!-- 同上 -->
</bookstore>
如果是公共 DTD(比如 XHTML):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
7. DTD 的局限性(为什么现在少用)
- 不支持命名空间(namespace)
- 不支持数据类型(只能 CDATA、ID 等简单类型)
- 语法不是 XML 本身(不能用 XML 工具解析 DTD)
- 无法定义元素内容的长度、正则、数值范围等
- 因此被 XML Schema(XSD)取代
8. 快速记忆口诀
- 元素顺序用 ,
- 选择用 |
- 可选 ?,多次 *,至少一次 +
- 属性必填 #REQUIRED,可选 #IMPLIED,默认值直接写字符串,固定值 #FIXED
9. 练习建议
- 写一个学生信息 DTD(包含姓名、学号、性别、选修课程至少一门)
- 写一个简易博客 DTD(文章列表 → 文章 → 标题、作者、发布日期、正文、评论*)
- 把上面的例子改成外部 DTD
需要我给你更多练习题、答案解析,或者对比 DTD vs XSD 的详细表格,随时告诉我!祝你玩转 DTD!