Apache Xerces-J 介绍与选型指南

解析 Apache Xerces-J 的定位、与 JDK 内置解析器的关系差异、家族语言绑定对照与版本线辨析,并给出 Java XML 解析器选型建议,全部结论在 Ubuntu 22.04 + OpenJDK 17 上实测验证。

Apache XercesApache XercesJavaXMLApache2026/10/16

Apache Xerces-J 介绍与选型指南

目标:讲清 Apache Xerces-J 是什么、它与 JDK 内置 XML 解析器是什么关系、Xerces 家族各语言绑定怎么选、2.x 与 3.x 版本线如何区分,并给出 Java XML 解析器选型建议。文中所有探测命令与回显均已在 Ubuntu 22.04 + OpenJDK 17 环境实测通过。

一、环境信息

本文所有实测在以下环境中完成,读者复现时可对照自己的环境。

cat /etc/os-release | head -2

实测回显:

PRETTY_NAME="Ubuntu 22.04.5 LTS"
NAME="Ubuntu"
uname -m

实测回显:

x86_64
java -version

实测回显:

openjdk version "17.0.20.1" 2026-08-18
OpenJDK Runtime Environment (build 17.0.20.1+1-1-22.04-Ubuntu)
OpenJDK 64-Bit Server VM (build 17.0.20.1+1-1-22.04-Ubuntu, mixed mode, sharing)
mvn -version | head -3

实测回显:

Apache Maven 3.6.3
Maven home: /usr/share/maven
Java version: 17.0.20.1, vendor: Ubuntu, runtime: /usr/lib/jvm/java-17-openjdk-amd64
  • 操作系统:Ubuntu 22.04.5 LTS(x86_64)
  • JDK:OpenJDK 17.0.20.1
  • 构建工具:Apache Maven 3.6.3
  • Xerces-J 版本:2.12.2(Maven Central 当前最新稳定版,发布于 2022 年 1 月)
  • 演示目录:/root/xerces-lab

二、软件概述

Apache Xerces-J 是 Apache 软件基金会 Xerces 项目的 Java 语言实现,是一款 XML 解析器(Parser)参考级实现,提供符合标准的 XML 1.0/1.1 解析、DTD 校验、XML Schema 校验、命名空间处理、XInclude 等能力,并通过 JAXP、SAX、DOM 等标准 API 对外暴露。1999 年底 IBM 将其 XML4J 解析器源码捐赠给 Apache 软件基金会,成为 Xerces-J 的起点;此后二十余年它一直是 Java 世界最权威的 XML 解析器之一,JDK 内置的 XML 解析器本身就是它的一个分叉(详见第三章)。

💡 技术拓展:解析 XML 有三种主流处理模型,Xerces-J 三者都支持——

模型原理特点适用场景
SAX(推式流)解析器边读边把"事件"推给处理器回调内存占用极小、单向只读、编程模型偏底层大文件扫描、抽取性读取
DOM(树)一次性把整篇文档加载为内存对象树可随机访问、可回写、内存与文档大小成正比中小文档、需要改文档结构
StAX(拉式流,JSR-173)应用主动 pull() 逐事件读取流式 + 程序控制节奏,介于 SAX 与 DOM 之间高吞吐中间件、消息解析

Xerces-J 以 SAX/DOM 为主打,同时内置了 StAX 事件工厂实现;本文与大多数业务集成场景默认采用 JAXP 门面 + SAX/DOM 模型,理由是标准 API 可移植、实现可替换。

版本方面,Xerces-J 的官方站点为 xerces.apache.org,当前最新稳定版是 2.12.2。用下面命令可直接在官方下载目录核实(截至 2026 年 10 月该版本仍在列):

curl -s https://dlcdn.apache.org/xerces/j/binaries/ | grep -oE 'Xerces-J-bin\.[0-9.]+\.(tar\.gz|zip)'

实测回显:

Xerces-J-bin.2.12.2.tar.gz
Xerces-J-bin.2.12.2.zip

Maven Central 上的版本线也可以直接核实:

curl -s https://repo1.maven.org/maven2/xerces/xercesImpl/maven-metadata.xml | grep -E '<(latest|release)>'

实测回显:

    <latest>2.12.2</latest>
    <release>2.12.2</release>

版本清单从 2.0.0 一路演进到 2.12.2,最后更新时间为 2022-01-27(元数据 lastUpdated 标签为 20220127102933)。

三、与 JDK 内置解析器的关系与差异辨析

这是使用 Xerces-J 前必须弄清的问题:JDK 自带的 XML 解析器不是"另一款解析器",而是 Xerces 的改名内置分叉。JDK 把 Xerces 源码拷入内部包名 com.sun.org.apache.xerces.internal.*,随 java.xml 模块分发,作为 JAXP 的默认实现。下面逐条实测验证。

3.1 JDK 默认实现就是内置 Xerces

写一个探测程序,打印 JAXP 工厂返回的实际实现类:

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.SAXParserFactory;

public class SaxWho {
    public static void main(String[] args) throws Exception {
        SAXParserFactory sf = SAXParserFactory.newInstance();
        DocumentBuilderFactory df = DocumentBuilderFactory.newInstance();
        System.out.println("SAXParserFactory 实现类: " + sf.getClass().getName());
        System.out.println("DocumentBuilderFactory 实现类: " + df.getClass().getName());
    }
}

编译后在不带任何 Xerces jar 的环境下运行:

cd /root/xerces-lab
javac -encoding UTF-8 -d classes src/SaxWho.java
java -cp classes SaxWho

实测回显:

SAXParserFactory 实现类: com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl
DocumentBuilderFactory 实现类: com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl

实现类名中的 com.sun.org.apache.xerces.internal 直接说明:JDK 内置解析器就是 Xerces(改名内嵌版)。

3.2 xercesImpl.jar 一上 classpath 即可整体切换到独立版 Xerces

独立版 Xerces 的 xercesImpl-2.12.2.jar 内部通过 META-INF/services 机制注册了全套 JAXP 工厂实现。先看 jar 里注册了什么:

jar tf libs/xercesImpl-2.12.2.jar | grep services

实测回显:

META-INF/services/
META-INF/services/javax.xml.datatype.DatatypeFactory
META-INF/services/javax.xml.parsers.DocumentBuilderFactory
META-INF/services/javax.xml.parsers.SAXParserFactory
META-INF/services/javax.xml.stream.XMLEventFactory
META-INF/services/javax.xml.validation.SchemaFactory
META-INF/services/org.w3c.dom.DOMImplementationSourceList
META-INF/services/org.xml.sax.driver

因此只要把它放进 classpath,即使不设任何系统属性,JAXP 的 newInstance() 也会优先发现并采用独立版实现:

java -cp classes:libs/xercesImpl-2.12.2.jar SaxWho

实测回显:

SAXParserFactory 实现类: org.apache.xerces.jaxp.SAXParserFactoryImpl
DocumentBuilderFactory 实现类: org.apache.xerces.jaxp.DocumentBuilderFactoryImpl

也可以显式用系统属性强制指定(两种方式结果一致):

java -Djavax.xml.parsers.SAXParserFactory=org.apache.xerces.jaxp.SAXParserFactoryImpl -cp classes:libs/xercesImpl-2.12.2.jar SaxWho

实测回显:

SAXParserFactory 实现类: org.apache.xerces.jaxp.SAXParserFactoryImpl
DocumentBuilderFactory 实现类: org.apache.xerces.jaxp.DocumentBuilderFactoryImpl

💡 说明:JDK 17 的 JAXP 工厂查找顺序为「系统属性 → jaxp.properties → classpath 上 META-INF/services 服务发现 → 内置默认实现」。所以"把 xercesImpl.jar 放上 classpath"和"设系统属性"是两种等效的切换手段;工程上更推荐系统属性或显式 new org.apache.xerces.jaxp.SAXParserFactoryImpl(),避免 classpath 上多一个 jar 就悄悄改变全局行为的隐式切换。

3.3 版本可观测性差异:内置分叉读不到版本号

独立版 Xerces 提供 org.apache.xerces.impl.Version.getVersion() 读取版本:

public class VersionProbe {
    public static void main(String[] args) throws Exception {
        try {
            Class<?> c = Class.forName("com.sun.org.apache.xerces.internal.impl.Version");
            try {
                Object v = c.getMethod("getVersion").invoke(null);
                System.out.println("JDK 内置 Xerces 版本: " + v);
            } catch (Exception e) {
                System.out.println("JDK 内置 Version.getVersion() 反射调用失败: " + e);
            }
        } catch (ClassNotFoundException e) {
            System.out.println("未找到 JDK 内置 Version 类");
        }
        try {
            Class<?> c2 = Class.forName("org.apache.xerces.impl.Version");
            Object v2 = c2.getMethod("getVersion").invoke(null);
            System.out.println("独立版 Xerces 版本: " + v2);
        } catch (ClassNotFoundException e) {
            System.out.println("classpath 上未找到 org.apache.xerces.impl.Version(未引入 xercesImpl.jar)");
        }
    }
}

纯 JDK 环境运行:

java -cp classes VersionProbe

实测回显:

未找到 JDK 内置 Version 类
classpath 上未找到 org.apache.xerces.impl.Version(未引入 xercesImpl.jar)

引入 xercesImpl-2.12.2.jar 后运行:

java -cp classes:libs/xercesImpl-2.12.2.jar VersionProbe

实测回显:

未找到 JDK 内置 Version 类
独立版 Xerces 版本: Xerces-J 2.12.2

可以确认两件事:其一,JDK 17 的 java.xml 模块里确实打入了内置 Xerces(用 jimage 工具统计 com/sun/org/apache/xerces 前缀类共 801 个:jimage list $JAVA_HOME/lib/modules | grep -c "com/sun/org/apache/xerces" 实测输出 801);其二,内置分叉不保留 Version 版本类,即使加 --add-exports java.xml/com.sun.org.apache.xerces.internal.impl=ALL-UNNAMED 放开模块封装,Class.forName("com.sun.org.apache.xerces.internal.impl.Version") 仍抛 ClassNotFoundException——该类在 JDK 构建时被移除,而不是被模块封装挡住。这导致生产上无法在运行时直接读出"JDK 内置的到底是哪个 Xerces 版本",是二者最实际的差异之一。

3.4 内置分叉与独立版差异总表

维度JDK 内置分叉独立版 Xerces-J
包名com.sun.org.apache.xerces.internal.*org.apache.xerces.*
版本随 JDK 更新,版本由 JDK 发布节奏决定,运行时不可读版本号随 Apache 官方发布,Version.getVersion() 可读(实测 Xerces-J 2.12.2)
更新节奏跟随 JDK 半年节奏,含 OpenJDK 社区的修复与改动Apache Xerces 项目自定,2.12.2 为 2022 年 1 月发布
可替换性不可以单独升级(跟 JDK 绑定)换 jar 即可升级/降级
配置入口同样支持 JAXP feature/property同样支持,且新参数先在独立版出现
模块封装位于 java.xml 模块内部,反射需 --add-exports普通 classpath jar,无封装限制

关键差异解读:内置分叉胜在"零依赖、开箱即用",但版本不可控、不可单独升级;独立版胜在版本显式、可替换、问题可复现(报错堆栈带 org.apache.xerces 包名,社区文档对得上)。对解析行为有一致性要求(如校验报错文案、Schema 处理特性)的团队,应显式引入独立版并把实现"钉住"。

四、Xerces 家族与语言绑定对照

Xerces 是一个多语言解析器家族,各绑定由同一项目组按语言分别维护:

成员语言当前版本线发布形态说明
Xerces-JJava2.x(最新 2.12.2)xercesImpl.jar + xml-apis.jar本文主角,JDK 内置解析器的上游
Xerces-C++C++3.x(最新 3.3.0)平台二进制/源码包API 设计与 Xerces-J 同源,命名靠齐
Xerces-PerlPerl基于 Xerces-C 2.x 的 XML-Xerces 绑定CPAN 模块Perl 的 XML-Xerces 模块,绑定的是 C++ 版

关键差异解读:三个成员互相独立发布、版本号互不同步。选型时先确定语言,再查对应成员自己的版本线,不要拿 Xerces-C++ 的 3.x 去套 Xerces-J。

4.1 版本线辨析:2.x vs 3.x

初学者常被"Xerces 3.x"误导,这里用官方下载目录实测澄清:

curl -s https://dlcdn.apache.org/xerces/ | sed 's/<[^>]*>/ /g' | grep -oE '[a-z-]+/' | sort -u

实测回显:

c/
j/
p/
xml-commons/
  • Xerces-J 的版本线只有 1.x(1999–2002,遗留)与 2.x(2001 至今,最新 2.12.2)两条,从未发布过 3.x;
  • "Xerces 3.x"专指 Xerces-C++(Apache 归档中可查到 xerces-c-3.2.4、3.2.5、3.3.0 等版本文件,实测命令:curl -s https://archive.apache.org/dist/xerces/c/3/sources/ | grep -oE 'xerces-c-[0-9.]+\.tar\.gz' | sort -V | tail -3,回显如上三个文件名);
  • Xerces-J 1.4.4 是 1.x 线的最后一个版本,其源码已迁入 xerces_j_1 分支,官方页面明确"自 Xerces 2.x 开始,1.x 代码位于分支上"。

💡 技术拓展:选版本时还有一条容易踩的线——Maven 坐标。Xerces-J 在 Maven Central 的历史遗留坐标是 xerces:xercesImpl,官网文档与新坐标草案里的 org.apache.xerces:xercesImpl 在 Central 上并不存在(实测 curl -sI https://repo1.maven.org/maven2/org/apache/xerces/xercesImpl/maven-metadata.xml 返回 404)。依赖引入必须用遗留坐标,详见《Apache Xerces-J 在 Ubuntu 22.04 集成使用指南》。

五、核心架构与发行组件

Xerces-J 的架构分三层:底层是扫描器(Scanner,词法/句法扫描),其上是校验器(Validator,DTD/Schema 校验),最外层通过适配器把内部事件流适配成 SAX/DOM/JAXP 标准接口。连接底层与上层的内部总线是 XNI(Xerces Native Interface)——一套比 SAX 更细粒度的解析器内部接口,官方 samples 里的 xni.DocumentTracer 可以直接观察这层事件(用法见《Apache Xerces-J 2.12.2 命令行工具详解》)。

官方二进制发行包(Xerces-J-bin.2.12.2.tar.gz,实测 5648672 字节,sha256 为 1ad48949b2c7f0df91668f058d6ec773871adb5527b0b5c73dc2160ab5d162e2)解压后包含以下核心 jar:

jar作用Maven Central 坐标实测结论
xercesImpl.jar解析器实现本体(含 META-INF/services 注册)xerces:xercesImpl:2.12.2 存在(实测 HTTP 200)
xml-apis.jarJAXP/SAX/DOM 标准接口(老 JDK 需要)xml-apis:xml-apis:1.4.01 存在(实测 HTTP 200);JDK 9+ 由 java.xml 模块提供,通常不再需要
resolver.jarOASIS XML Catalog 解析器xml-resolver:xml-resolver:1.2 存在(实测 HTTP 200)
serializer.jarXSLT/DOM 序列化输出器Central 上无 xerces:serializer 坐标(实测 HTTP 404),只能用发行包内的 jar 或换用 Xalan

关键差异解读:日常集成只需 xercesImpl.jar 一个 jar(JDK 17 下);xml-apis 属于老 JDK 时代的兼容件,坐标核对以实测为准,避免照抄过时文档引入 404 依赖。

六、功能特性

以下特性均以 2.12.2 实测可用为准(验证方式在《Apache Xerces-J 2.12.2 配置参数详解》逐项展开):

  • XML 1.0(第四版)与 XML 1.1 解析,UTF-8/UTF-16 等编码自动识别;
  • 命名空间处理与命名空间前缀保留(namespaces、namespace-prefixes 两个 feature 可开关,实测切换后 qName/localName/uri 回调值不同);
  • DTD 校验(validation feature,实测对违例文档报 Element type "mail" must be declared. 类错误);
  • XML Schema 1.0 校验(http://apache.org/xml/features/validation/schema,实测输出 cvc-* 标准诊断码);
  • Schema 全检查模式(schema-full-checking,实测能捕获默认模式放过的 UPA 唯一粒子归属违例);
  • XInclude 处理、PSVI(Post-Schema-Validation-Infoset)输出、StAX 事件工厂(jar 内含 org.apache.xerces.stax 实现);
  • 安全特性:disallow-doctype-decl 禁 DOCTYPE、load-external-dtd 控制外部 DTD 加载、实体展开限制(SecurityManager),可组合用于 XXE 防护。

七、适用场景与限制

适合独立引入 Xerces-J 的场景:

  1. 需要显式钉住解析器版本:同一个解析行为要跨多台服务器、多个应用保持一致(升级 JDK 不连带改变解析行为);
  2. 需要细致的校验与安全控制:XML Schema 严格校验、XXE 防护参数组合、错误处理器定制;
  3. 需要诊断与可观测:报错堆栈、命令行工具(dom.Counter 等)都基于 org.apache.xerces 包名,社区资料检索友好;
  4. 需要XNI/PSVI 级别的底层能力:构建语法缓存、自定义解析配置(如 CSVConfiguration 示例那类)。

限制与注意:

  1. 版本演进缓慢:2.12.2 之后无新版本,Schema 1.1 支持不完整(1.1 特性依赖 Xerces-J 的实验性模块,不建议生产使用);
  2. 与 JDK 内置实现功能高度重叠:若没有上述显式需求,直接用 JDK 内置解析器即可,不必为"解析"本身多带一个 jar;
  3. 引入后默认会"接管"JAXP 工厂(META-INF/services 机制),升级 jar 时要回归测试依赖它的解析行为。

八、同类选型对比

Java 世界可用的 XML 解析实现不止 Xerces 一家,横向对比:

实现定位优势劣势适用
JDK 内置 Xerces(com.sun 分叉)JDK 默认 JAXP 实现零依赖版本不可控、不可读版本号一般业务解析
Apache Xerces-J 2.12.2独立参考实现版本钉死、参数最全、官方工具链需自行管理 jar/依赖校验敏感、合规场景
Woodstox / Aalto高性能 StAX 实现流式吞吐高SAX/DOM 校验生态弱于 Xerces高吞吐消息处理
dom4j / JDOM高层易用 DOM 封装API 友好、XPath 便捷底层仍依赖 Xerces 等做实际解析XML 读写小工具
VTD-XML非提取式解析内存与速度极致非标准 API,学习成本高超大文件专用场景

关键差异解读:dom4j/JDOM 是"易用层",Woodstox/Aalto 是"性能层",Xerces-J 是"标准与校验层",三者常在一个工程里同时存在(dom4j 底下往往就是 Xerces)。如果只是解析,用 JDK 内置;如果要对解析行为负责(版本、校验、安全参数),选 Xerces-J 独立版;如果是海量流式报文,考虑 Woodstox/Aalto。

九、参考链接