乐途乐途
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
  • 学习路径
  • XML 基础语法

    • XML 概述
    • XML 文档结构
    • XML 元素
    • XML 属性
    • XML 语法规则
    • XML 命名空间
    • XML 注释与处理指令
  • DTD 与文档验证

    • DTD 概述
    • DTD 元素声明
    • DTD 属性声明
    • DTD 实体声明
    • DTD 元素与属性对比
    • DTD 完整示例
  • XML Schema 定义

    • XML Schema 概述
    • XSD 简单类型
    • XSD 复杂类型
    • XSD 命名空间与引用
  • XPath 节点定位

    • XPath 概述
    • XPath 路径表达式
    • XPath 谓词与函数
  • XSLT 转换

    • XSLT 概述
    • XSLT 模板与匹配
    • XSLT 控制结构
    • XSLT 输出控制
  • XML 解析技术

    • XML 解析概述
    • DOM 解析
    • SAX 解析
    • StAX 解析
    • XML 与 Java — JAXP
  • XML 在 Java 中的应用

    • Spring XML 配置
    • MyBatis XML 映射
    • pom.xml 与 Maven
    • web.xml 配置详解
  • 现代数据格式对比

    • XML 与 JSON 对比
    • XML 与 YAML 对比
  • XML 显示与浏览器集成

    • XML 在浏览器中的显示
    • XMLHttpRequest 与 AJAX
    • 服务器端 XML 处理
  • XML 进阶查询与链接

    • XQuery 查询语言
    • XLink 超链接
    • XML 验证工具使用
  • XML Web 服务(选读)

    • XML Web 服务概述
    • SOAP 协议详解
    • WSDL 服务描述
    • RSS 内容聚合
    • RDF 资源描述框架

DTD 元素声明

本章定位 :掌握 DTD 中的元素声明语法——四种内容模型(EMPTY、ANY、#PCDATA、子元素)、出现次数修饰符(+ / * / ?)和选择符(|)的精确语义。

定义与作用

DTD 的 <!ELEMENT> 声明定义了 XML 文档中每个元素的 合法内容模型——即该元素内部可以出现什么(纯文本、子元素、混合或为空)。这是 DTD 验证的核心部分。

DTD 元素声明的本质是用形式化语法描述文档结构。解析器读取 DTD 后,就会按照声明逐一验证每个元素实例是否符合定义。

核心原理:内容模型的验证流程

图解释 :DTD 验证器读取元素声明后,根据内容模型类型进入不同的验证分支。子元素模型最复杂——验证器需要按顺序逐个子元素检查,并根据出现次数修饰符判断是否接受。

语法/结构要点

四种内容模型

模型声明语法允许的内容示例
EMPTY<!ELEMENT br EMPTY>不能有任何内容<br/>
ANY<!ELEMENT data ANY>任何可解析内容不推荐
#PCDATA<!ELEMENT title (#PCDATA)>纯文本<title>XML</title>
子元素<!ELEMENT book (title, author, year)>按序排列的子元素见下方示例

出现次数修饰符

修饰符含义示例匹配
无修饰恰好出现 1 次(title)1 个 title
+出现 1 次或多次(author+)至少 1 个 author
*出现 0 次或多次(note*)0 个或多个 note
?出现 0 次或 1 次(discount?)0 或 1 个 discount

选择符 | 和括号组合

<!-- book 包含 1 个 title,然后是 1 个或多个 (author 或 editor) -->
<!ELEMENT book (title, (author | editor)+)>

<!-- person 包含 name,然后可选 phone 或 email -->
<!ELEMENT person (name, (phone | email)?)>

完整示例:白歌设计飞翔科技图书 DTD

场景说明

飞翔科技架构师 白歌 正在设计公司图书管理系统的 XML Schema。她先用 DTD 建立原型,然后再考虑迁移到更强大的 XSD。她需要为图书目录设计元素声明。

操作前:口头约定,无规范

团队开发时各人按自己的理解写 XML,导致 3 个人写出了 3 种结构变体。这直接导致解析代码需要处理大量 if-else。

操作后:白歌写的完整元素声明 DTD

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE bookstore [
  <!ELEMENT bookstore (book+)>

  <!-- book:title 必填,author 至少1个,year 必填,price 必填,
       review 可选多个,award 可选多个 -->
  <!ELEMENT book (title, author+, year, price, review*, award*)>

  <!-- 简单文本元素 -->
  <!ELEMENT title (#PCDATA)>
  <!ELEMENT author (#PCDATA)>
  <!ELEMENT year (#PCDATA)>
  <!ELEMENT price (#PCDATA)>

  <!-- review 包含 text 和 rating(选其一) -->
  <!ELEMENT review (text | rating)>
  <!ELEMENT text (#PCDATA)>
  <!ELEMENT rating (#PCDATA)>

  <!-- award 纯文本 + 空元素可选 -->
  <!ELEMENT award (#PCDATA)>
]>
<bookstore>
  <book>
    <title>Learning XML</title>
    <author>Erik T. Ray</author>
    <year>2003</year>
    <price>39.95</price>
    <review><text>Excellent introduction to XML.</text></review>
    <review><rating>5</rating></review>
    <award>Best Tech Book 2003</award>
  </book>
</bookstore>

操作结果

现在所有开发者必须遵循这段 DTD 定义的规则:

  • 只有 review 元素可以包含 text 或 rating(但不能同时包含两者)
  • author 至少 1 个,review 可以 0 或多个
  • 元素出现顺序固定:title → author → year → price → review → award

如果有新人加入团队,白歌只需要让他看 DTD 文件,结构规则一目了然。

易错场景

错误一:混淆 + 和 *

<!-- 要求至少 1 个 author —— 如果 XML 中没有 author,验证失败 -->
<!ELEMENT book (title, author+, year)>

<!-- 允许 0 个 author —— author 完全是可选的 -->
<!ELEMENT book (title, author*, year)>

错误二:忘记括号

<!-- ❌ 语法错误 -->
<!ELEMENT book title, author>

<!-- ✅ 子元素列表必须加括号 -->
<!ELEMENT book (title, author)>

错误三:ANY 的陷阱

<!-- ❌ ANY 意味着任何内容都能通过验证,完全失去约束力 -->
<!ELEMENT data ANY>

ANY 在原型阶段可能有用,但生产环境不应使用——它让 DTD 形同虚设。

面试考点

考点参考答案要点
DTD 中有哪几种内容模型?四种:EMPTY(空元素)、ANY(任意内容)、#PCDATA(纯文本)、子元素列表(复合元素)
+、*、? 的语义分别是什么?+ 表示至少 1 次(1 到 n),* 表示 0 到 n 次,? 表示 0 或 1 次。无修饰符表示恰好 1 次
为什么生产环境不推荐 ANY?ANY 允许任意内容,不提供任何结构约束,等于没有验证。它只在开发初期快速原型时有用
上一页
DTD 概述
下一页
DTD 属性声明