DTD解析开销更小,因其语法简单、无命名空间和数据类型校验,仅需基础标签匹配与实体检查,且DTD非XML格式,可用轻量词法器处理,无需加载编译Schema模型。

DTD 验证通常更快,但代价是功能阉割和结构僵化
为什么 DTD 解析开销更小?
DTD 语法简单、无命名空间、无数据类型校验,解析器(如 JAXP 中的 DocumentBuilderFactory)只需做基础标签匹配和实体声明检查,不涉及 XML Schema 的类型推导、facet 校验或命名空间绑定等步骤。
- DTD 文件本身不是 XML,解析器用专用轻量词法器处理,跳过通用 XML 解析流程
- 不需加载和编译 Schema 模型(
SchemaFactory.newSchema()是个耗时操作) - 无
xs:complexType层级展开、无xs:import/xs:include依赖解析
XSD 验证慢在哪几个关键环节?
真正拖慢 XSD 验证的不是“校验动作本身”,而是前期准备和规则复杂度:
-
SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema")初始化较重,尤其首次调用会触发类加载和内部缓存构建 - 每次
schema.newValidator()都可能触发 Schema 编译(除非复用Schema实例) - 遇到
xs:pattern、xs:minLength、xs:enumeration等约束时,需对每个文本节点做正则匹配或枚举比对 - 多命名空间 +
xs:import的 XSD,加载时间呈线性增长,且容易因resolveResource回调未实现而卡住
实测对比:一个典型 Spring Bean XML 的验证耗时差异
以含 50 个 的 XML 文件为例(JDK 17 + Xerces 2.12.2):
DTD 模式(setValidating(true)):平均 8–12 ms XSD 模式(预编译 Schema + 复用 Validator):平均 25–40 ms XSD 模式(每次 newSchema + newValidator):平均 60–110 ms
注意:XSD 的“慢”可被显著缓解——只要把 Schema 实例缓存起来(例如 Spring 容器启动时一次性加载),后续验证几乎只花在内容校验上,差距缩小到 2× 以内。
别为了快选 DTD,除非你真不需要这些
如果你的场景需要以下任意一项,DTD 就不是“够用”,而是“根本不能用”:
- 元素内容必须是
xs:date或xs:decimal(DTD 只能标#PCDATA) - XML 带多个命名空间(如
p:,tx:,context:),DTD 无法声明和区分 - 要限制字符串长度、正则格式、枚举值(如
)ACTIVE|INACTIVE - 需要工具链支持(IDE 提示、XSLT 类型推断、代码生成如 JAXB)
性能差一点,但错一次就导致生产环境 Bean 创建失败,这种“快”反而最贵。XSD 的验证延迟,本质是把错误拦截在解析阶段,而不是等到运行时抛 ClassCastException。










