XML Catalog 是标准化的外部实体重定向机制,用于将 XML 中引用的 DTD、Schema 等映射到本地路径,解决网络依赖、版本迁移和多环境配置问题,通过 public/system/rewriteSystem 等标签声明式配置,需配合支持 Catalog 的解析器 resolver 使用。

XML Catalog 是一种标准化的外部实体重定向机制,用于把 XML 文档中引用的 DTD、Schema、实体等远程或抽象资源,映射到本地可访问的文件路径或内部资源,从而实现集中式、可维护、离线可用的解析控制。
它不修改原始 XML 文件,而是在解析阶段“拦截并替换”系统标识符(systemId)、公共标识符(publicId)或命名空间 URI,让解析器从指定位置加载资源,而不是发起网络请求或报错失败。
XML Catalog 的核心作用是解决三类常见问题
-
网络依赖风险:避免解析时因
http://www.w3.org/.../xhtml1.dtd等远程 DTD 加载失败导致解析中断 -
版本迁移困难:比如旧项目引用
schema-v1.xsd,新环境想统一用schema-latest.xsd,只需改 Catalog 文件 -
多环境配置不一致:开发、测试、生产使用不同路径(如
file:///opt/schemas/vsC:\schemas\),Catalog 可按环境切换
Catalog 文件怎么写?关键标签说明
一个最小可用的 catalog.xml 长这样:
-
:匹配..>中的公共 ID -
:精确匹配SYSTEM "http://example.com/config.xsd"这类系统标识符 -
:前缀匹配,适合批量重写(如所有http://example.com/old/xxx.xsd→schemas/old/xxx.xsd)
注意:
uri值支持相对路径(相对于 catalog 文件位置)、绝对file://路径,甚至jar:file:/lib/schemas.jar!/xsd/等格式。
怎么让解析器真正用上 Catalog?
不同语言/框架接入方式略有差异,但逻辑一致:在创建解析器实例后,注入一个支持 Catalog 的 resolver。
以 .NET 为例:
var doc = new XmlDocument();
doc.XmlResolver = new XmlCatalogResolver("catalog.xml"); // 自定义或使用开源库
doc.Load("input.xml");Java(JAXP + Apache Xerces)常用方式:
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setFeature("http://apache.org/xml/features/validation/dynamic", true);
XMLReader reader = factory.newSAXParser().getXMLReader();
reader.setProperty(
"http://apache.org/xml/properties/internal/entity-resolver",
new CatalogResolver("catalog.xml")
);提示:不是所有默认解析器原生支持 Catalog。.NET 原生
XmlUrlResolver不支持,需借助 XmlResolver 等开源实现;Java 推荐用 Xerces 或启用org.apache.xml.resolver.tools.CatalogResolver。
它和普通自定义 XmlResolver 有什么区别?
| 对比项 | 普通自定义 XmlResolver | XML Catalog Resolver |
|---|---|---|
| 配置方式 | 写代码硬编码逻辑(如 if (uri.Contains("dtd")) return File.OpenRead(...)) |
声明式 XML 配置,无需改代码 |
| 可维护性 | 修改映射要重新编译 | 换个 catalog.xml 即可生效 |
| 标准兼容性 | 各自实现,难复用 | OASIS 国际标准,工具链广泛支持(Oxygen、XMLSpy、Protege、Maven 插件等) |
| 功能粒度 | 通常只处理 systemId | 支持 public、system、rewriteSystem、delegatePublic 等多种匹配策略 |
不复杂但容易忽略:Catalog 本身只是配置,真正起作用靠解析器是否识别并执行它。选对 resolver 实现、配对正确的解析器特性(如开启验证、禁用网络回退),才能让重定向稳定生效。










