DTD是XML早期约束机制,现基本被XSD或Relax NG取代;仅适用于简单配置验证、老旧系统兼容或教学场景。

DTD 是什么,现在还该用吗
DTD(Document Type Definition)是 XML 最早的约束机制,用来声明元素、属性、嵌套规则和默认值。但它不支持命名空间、数据类型校验弱、语法独立于 XML 本身,现代项目基本被 XSD 或 Relax NG 取代。如果你只是要快速验证简单配置文件、配合老旧系统(比如某些 Java SAX 解析器或遗留文档工具),或者教学演示,写 DTD 仍可行;否则建议直接跳过,改用 XSD。
从一个 XML 示例反推 DTD 声明
假设你有如下 XML 文件 book.xml:
Design Patterns Gamma et al. 1994
要为它写 DTD,核心是还原三类声明:!ELEMENT(元素结构)、!ATTLIST(属性)、!ENTITY(可选,实体)。注意顺序:DTD 中 !ELEMENT 必须先于 !ATTLIST 引用该元素。
-
包含三个子元素且顺序固定 → 写成 -
id属性是必需的字符串 → - 每个子元素都是纯文本(#PCDATA),无子元素 →
(同理 author/year) - 如果
year只允许数字,DTD 无法校验,只能靠应用层处理
常见坑:括号语法、内容模型与特殊字符
DTD 的内容模型容易写错,尤其混合型或可选内容。例如:
SiteDynamic企业网站管理系统采用较为成熟的ASP+ACCESS编写,是迄今为止国内较先进的ASP语言企业网站管理系统。系统为企业级网站提供一个框架,能满足企业的基本应用,同时系统开放全部源码,用户可以根据自己的需求扩展出自己需求的模块,如:单页面、新闻、产品展示、下载、友情链接、电子商务、广告、会员、在线支付、人才招聘等。整套系统的设计构造,完全考虑大中小企业类网站的功能要求,网站的后台
- 允许
为空或含文本 → 必须写,不是EMPTY(那是完全不能有内容) - 子元素可重复 0 次或多次 → 用
*,如(author+)表示至少一个author,(author*)表示零个或多个 - 元素可选且顺序不固定 → DTD 不支持,只能用
(author|title|year)*(但会允许任意混排,无法保证“最多一个 title”) - 在 DTD 文件里写
或&会解析失败 → 必须用zuojiankuohaophpcn和&(和 XML 一样)
如何让解析器真正加载并校验 DTD
光有 .dtd 文件不够,XML 声明里的 DOCTYPE 必须指向它,且解析器需开启外部 DTD 加载和校验。例如 Python 的 xml.etree.ElementTree 默认不校验,要用 lxml:
from lxml import etree
parser = etree.XMLParser(dtd_validation=True)
tree = etree.parse("book.xml", parser)
Java 中需设置 SAXReader.setEntityResolver() 并启用 http://apache.org/xml/features/validation/dtd;浏览器则完全忽略外部 DTD(出于安全限制)。另外,若 DTD 放在本地,SYSTEM "book.dtd" 路径必须相对于 XML 文件位置,不是 Python 脚本位置。
真实项目里,DTD 的路径管理、网络加载阻塞、缺乏类型提示,会让维护成本远高于收益。除非协议强制要求,否则别把它当首选方案。









