Apache Xalan-J 介绍与选型指南
"Apache Xalan-J 2.7.3 详解:XSLT 1.0 处理器定位、与 JDK 内置 Xalan 的关系辨析、xsltc 编译器等独立使用价值,以及与 Saxon 的选型对比,全部结论基于 Ubuntu 22.04 + JDK 17 真机实测。"
Apache Xalan-J 介绍与选型指南
目标:读完本文,你能够搞清楚 Apache Xalan-J 是什么、它与 JDK 内置 Xalan 是什么关系、独立部署 Xalan-J 能带来哪些 JDK 内置实现不具备的能力,并能在 Xalan-J、JDK 内置 Xalan 与 Saxon 之间做出有依据的选型。文中所有结论均来自 Ubuntu 22.04 服务器上 JDK 17 环境的真实运行结果,而非文档转述。
一、环境信息
| 项 | 值 |
|---|---|
| 操作系统 | Ubuntu 22.04.5 LTS(x86_64) |
| JDK | OpenJDK 17.0.20.1(Ubuntu 发行版) |
| 构建工具 | Apache Maven 3.6.3 |
| Xalan-J 版本 | 2.7.3(官方二进制包 xalan-j_2_7_3-bin.tar.gz) |
查看本机环境的真实命令与回显:
$ head -2 /etc/os-release
PRETTY_NAME="Ubuntu 22.04.5 LTS"
NAME="Ubuntu"
$ uname -m
x86_64
$ java -version 2>&1
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 2>&1 | head -4
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
Default locale: en_US, platform encoding: ANSI_X3.4-1968
💡 技术拓展:
platform encoding: ANSI_X3.4-1968是 POSIX locale 的别名。最小化安装的系统常缺 UTF-8 locale,会导致 Java 程序往控制台输出中文变成问号。解决办法是export LANG=C.UTF-8(C.UTF-8 是 Ubuntu 内置的 locale,无需额外安装语言包)。后文所有实测输出都已在该变量设置后采集。
Xalan-J 的最新稳定版本经两处交叉确认:
$ curl -s https://repo1.maven.org/maven2/xalan/xalan/maven-metadata.xml | grep -E "<latest>|<release>"
<latest>2.7.3</latest>
<release>2.7.3</release>
Maven Central 的 latest 与 release 均为 2.7.3(2023-03-25 构建,官方站点同版本发布说明)。本文全部实测基于该版本。
二、软件概述
Apache Xalan-J 是 Apache Xalan 项目的 Java 实现,是一个符合 XSLT 1.0 与 XPath 1.0 规范的处理器:读取 XML 文档与 XSLT 样式表,输出 HTML、XML 或纯文本。它同时提供两种运行形态:
| 形态 | 机制 | 入口 |
|---|---|---|
| 解释执行 | 运行时逐条解释样式表 | org.apache.xalan.xslt.Process(命令行)/ org.apache.xalan.processor.TransformerFactoryImpl(API) |
| 编译执行(XSLTC) | 把样式表编译成 Java 字节码 translet 再运行 | org.apache.xalan.xsltc.cmdline.Compile / Transform / org.apache.xalan.xsltc.trax.TransformerFactoryImpl |
两者都实现标准 JAXP(javax.xml.transform)接口,因此同一个 Java 程序不改一行代码即可在两种引擎间切换——切换的只是类路径上的工厂实现。
Xalan-J 2.7.3 官方二进制包解压后共四个 jar:
| jar | 大小(字节) | 作用 |
|---|---|---|
| xalan.jar | 3455761 | 双引擎本体(解释器 + XSLTC) |
| serializer.jar | 283536 | 序列化器(HTML/XML/Text 输出) |
| xercesImpl.jar | 1446149 | Xerces-J XML 解析器 |
| xml-apis.jar | 228394 | DOM/SAX/JAXP 标准 API |
三、核心架构
3.1 引擎信息实测
用样式表输出 system-property('xsl:vendor') 与 xsl:vendor-url,可以精确区分当前跑的是哪个引擎(engine-info.xsl 为打印这两个属性的样式表):
| 属性 | 独立 Xalan-J(解释器工厂) | JDK 17 内置引擎 |
|---|---|---|
| xsl:vendor | Apache Software Foundation | Apache Software Foundation (Xalan XSLTC) |
| xsl:vendor-url | http://xml.apache.org/xalan-j | http://xml.apache.org/xalan-j |
$ java -cp classes:$CP EngineInfo
TransformerFactory 实现类: org.apache.xalan.processor.TransformerFactoryImpl
xsl:version = 1.0
xsl:vendor = Apache Software Foundation
xsl:vendor-url = http://xml.apache.org/xalan-j
💡 技术拓展:
xsl:vendor是 XSLT 1.0 规范定义的系统属性,任何兼容处理器都必须支持。JDK 内置实现的 vendor 字符串里带 "(Xalan XSLTC)" 后缀,而独立 Xalan-J 的解释器工厂只报 "Apache Software Foundation"——这是区分两者的最可靠方法。
3.2 发行包 Manifest 自带启动坐标
$ unzip -p /root/xalan-j_2_7_3/xalan.jar META-INF/MANIFEST.MF | grep -E "Implementation-Version|Implementation-Vendor|Main-Class"
Main-Class: org.apache.xalan.xslt.Process
Implementation-Version: 2.7.3
Implementation-Vendor: Apache Software Foundation
Implementation-Version: 2.7.3
Implementation-Vendor: Apache Software Foundation
Implementation-Version: 2.7.3
Implementation-Vendor: Apache Software Foundation
Implementation-Version: 2.7.3
Implementation-Vendor: Apache Software Foundation
Implementation-Version: 2.7.3
Implementation-Vendor: Princeton University
Implementation-Version: 2.7.3
Implementation-Vendor: Apache Software Foundation
Implementation-Version: 2.7.3
Implementation-Vendor: Apache Software Foundation
$ unzip -p /root/xalan-j_2_7_3/xalan.jar META-INF/MANIFEST.MF | grep -A1 "Class-Path" | head -2
Class-Path: xercesImpl.jar xml-apis.jar serializer.jar
两个关键信息:Main-Class 是命令行入口(java -jar xalan.jar 直接可用);Class-Path 声明了三个兄弟 jar——把 xalan.jar 与发行包其余三个 jar 放在同一目录时,无需手动拼类路径(Manifest Class-Path 会按相对路径自动加载),这在手动 jar 集成时非常关键,详见《Apache Xalan-J 在 Ubuntu 22.04 集成使用指南》。
(Manifest 里的实现版本对出现多次,是因为清单文件按打包来源分了多个节段,各节段都标注了构建版本与来源方,其中 Princeton University 节段对应 XSLTC 的学术来源。)
四、关键能力实测
4.1 命令行一键变换
$ java -cp $CP org.apache.xalan.xslt.Process -IN hello.xml -XSL hello.xsl
<?xml version="1.0" encoding="UTF-8"?><message>Hello, Xalan-J! Your XSLT engine is Apache Software Foundation.</message>
4.2 XSLTC 编译执行
$ java -cp $CP org.apache.xalan.xslt.Process -XSLTC -IN hello.xml -XSL hello.xsl
<?xml version="1.0" encoding="UTF-8"?><message>Hello, Xalan-J! Your XSLT engine is Apache Software Foundation (Xalan XSLTC).</message>
$ java -cp $CP org.apache.xalan.xslt.Process -XSLTC -XO hello -XSL hello.xsl && ls -l hello.class
-rw-r--r-- 1 root root 3267 Oct 16 00:51 hello.class
$ java -cp $CP:. org.apache.xalan.xsltc.cmdline.Transform hello.xml hello
<?xml version="1.0" encoding="UTF-8"?><message>Hello, Xalan-J! Your XSLT engine is Apache Software Foundation (Xalan XSLTC).</message>
先编译成 translet(hello.class),再用 Transform 加载执行,输出一致。命令行工具的全部参数见《Apache Xalan-J 命令行工具详解》。
4.3 Java 扩展与 EXLT 扩展函数
独立 Xalan-J 默认放行 Java 扩展(样式表里直接调用 java.lang.Math 等类)与 EXLT 扩展(exslt:node-set 等):
$ java -cp classes:$CP Generic exslt-test.xsl employees.xml
<?xml version="1.0" encoding="UTF-8"?><report>
<java-ext>
<sqrt2>1.4142135623730951</sqrt2>
<round>3</round>
</java-ext>
<exslt>
<node-set-count>2</node-set-count>
<first-item>XSLT 1.0</first-item>
</exslt>
</report>
同一个样式表跑在 JDK 内置引擎上同样能出结果(输出缩进为 4 空格、由内置引擎的序列化器排版),说明两套引擎在扩展支持上的差异主要体现在默认安全策略上——见 4.5 的 -SECURE 实测。
4.4 trace 调试与诊断计时
$ java -cp $CP org.apache.xalan.xslt.Process -TT -IN hello.xml -XSL hello.xsl
null Line #0, Column #0: template match='/'
file:///root/xalan-lab/hello.xsl Line #4, Column #35: template match='/greeting'
<?xml version="1.0" encoding="UTF-8"?><message>Hello, Xalan-J! Your XSLT engine is Apache Software Foundation.</message>
$ java -cp $CP org.apache.xalan.xslt.Process -DIAG -IN employees.xml -XSL employees2html.xsl
--------- Transform of employees.xml via employees2html.xsl took 102 ms
$ java -cp $CP org.apache.xalan.xslt.Process -DIAG -XSLTC -IN hello.xml -XSL hello.xsl
--------- Transform of hello.xml via hello.xsl took 55 ms
(-TT 的 trace 行与变换结果混在同一输出流,行尾空格为监听器打印格式,均照实录转述。-DIAG 的耗时受机器状态影响,此处数字仅代表本机当次运行。)
4.5 安全处理开关对 Java 扩展的拦截
$ java -cp $CP org.apache.xalan.xslt.Process -SECURE -IN employees.xml -XSL exslt-test.xsl
<?xml version="1.0" encoding="UTF-8"?><report>
<java-ext>(Location of error unknown)Extension function: '{http://xml.apache.org/xalan/java/java.lang.Math}sqrt' can not be invoked when the XMLConstants.FEATURE_SECURE_PROCESSING feature is set to true.
-SECURE 开启后 Java 扩展函数调用被直接拒绝(退出码 0,但输出中断在 java-ext 节点)。这是不可信样式表场景的标准防线,详见《Apache Xalan-J 2.7.3 配置参数详解》5.4 节。
五、与 JDK 内置 Xalan 的关系辨析
JDK 自带的 com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl 正是从 Xalan-J XSLTC 引擎衍生并内置的版本。三者的关系:
$ java -cp classes HelloXalan # 类路径上没有 xalan.jar
TransformerFactory 实现类: com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl
<?xml version="1.0" encoding="UTF-8"?><message>Hello, Xalan-J! Your XSLT engine is Apache Software Foundation (Xalan XSLTC).</message>
$ java -cp classes:$CP HelloXalan # 把独立 Xalan-J 放进类路径
TransformerFactory 实现类: org.apache.xalan.processor.TransformerFactoryImpl
<?xml version="1.0" encoding="UTF-8"?><message>Hello, Xalan-J! Your XSLT engine is Apache Software Foundation.</message>
(HelloXalan 为调用 TransformerFactory.newInstance() 后打印实现类并执行一次 hello 变换的最小程序。)
实测结论:
- 不用任何依赖时,JDK 内置实现接管:
TransformerFactory.newInstance()落到com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl,功能完整,普通 XSLT 1.0 变换无需引入 Xalan-J。 - 类路径放上 xalan.jar 即整体切换:SPI 文件(
META-INF/services/javax.xml.transform.TransformerFactory)随 jar 生效,newInstance()改落org.apache.xalan.processor.TransformerFactoryImpl(解释器引擎),输出文本中的引擎标识随之变化。 - 独立 Xalan-J 的增量价值:
- 解释器引擎(JDK 内置只有 XSLTC 衍生品,没有解释器引擎);
- 可控的升级节奏(JDK 内置版本与 JDK 绑定,2.7.3 修复项需独立引入才能获得);
- 命令行工具与 XSLTC 预编译链路的完整发行包;
- 与 JDK 内置实现在输出属性、扩展函数策略上的行为差异(如
accessExternal*属性仅 JDK 内置支持,实测见《Apache Xalan-J 2.7.3 配置参数详解》)。
- 风险差异:在 JDK 17 上反射直接实例化 JDK 内部工厂类会被模块封装拒绝:
D. 反射实例化被 JDK 17 模块封装拒绝: java.lang.IllegalAccessException
原因: module java.xml does not export com.sun.org.apache.xalan.internal.xsltc.trax
绕行: java --add-exports java.xml/com.sun.org.apache.xalan.internal.xsltc.trax=ALL-UNNAMED ...
绕行后可正常探测 JDK 内置工厂的属性(真实回显节选):
setAttribute(http://javax.xml.XMLConstants/property/accessExternalStylesheet, file) 成功
setAttribute(http://javax.xml.XMLConstants/property/accessExternalDTD, all) 成功
setAttribute(http://www.oracle.com/xsl/jaxp/transform/feat/enable-extension-functions) 拒绝: TransformerFactory does not recognise attribute 'http://www.oracle.com/xsl/jaxp/transform/feat/enable-extension-functions'.
六、适用场景与限制
6.1 适合用独立 Xalan-J 的场景
- 需要解释器引擎的渐进式处理能力(大文档交互渲染,配合
features/incremental属性); - 需要锁定与 JDK 版本无关的 Xalan 行为基线(升级 JDK 不改变 XSLT 引擎版本);
- 需要命令行工具或 XSLTC 预编译产物(translet 类文件 / jar)分发;
- 需要默认放行 Java 扩展函数的遗留系统迁移(JDK 内置引擎对扩展的控制粒度更严)。
6.2 已实测确认的限制
- XSLT 1.0 边界:不支持 XSLT 2.0/3.0,正则、分组、日期时间等 2.0 特性一律不可用;
- Maven 单依赖不完整:仅引入
xalan:xalan:2.7.3运行时报NoClassDefFoundError: org/apache/xalan/transformer/TransformerImpl(实测,因解释器引擎核心类链接需要 serializer.jar 中的接口,详见《Apache Xalan-J 在 Ubuntu 22.04 集成使用指南》),必须成对引入xalan:serializer:2.7.3; - 脚本扩展依赖 BeanShell:需要额外引入
bsf/bsh依赖,未引入时报类缺失; indent-amount扩展键不生效:输出缩进粒度由样式表排版决定(实测见《Apache Xalan-J 2.7.3 配置参数详解》5.3 节)。
七、同类方案选型对比
| 维度 | Xalan-J 2.7.3 | Saxon-HE 13.1 | JDK 内置 Xalan |
|---|---|---|---|
| XSLT 版本 | 1.0 | 2.0/3.0(HE 开源) | 1.0(XSLTC 衍生) |
| 引擎形态 | 解释器 + 编译器双引擎 | 解释器 + 编译器双引擎 | 仅 XSLTC 编译引擎 |
| Java 扩展 | 默认放行,-SECURE/FEATURE_SECURE_PROCESSING 可关 | 受配置控制 | 受配置控制,accessExternal* 白名单更细 |
| 许可 | Apache License 2.0 | Mozilla MPL 2.0(HE 版) | JDK 随附 |
| 运行基线 | JDK 8+(本文实测 17) | JDK 11+(实测 13.1 需 17 亦可) | 随 JDK |
| 适用 | XSLT 1.0 遗留系统维护、需锁定行为 | 新项目、需要 2.0/3.0 | 不引依赖的最小场景 |
(Saxon-HE 的版本与许可信息以其官方发布页为准;本表仅作选型指引,未做 Saxon 的行为级实测。)
选型建议:新项目优先 Saxon(XSLT 2.0/3.0 能力)或直接用 JDK 内置(1.0 需求且不引依赖);维护既有 XSLT 1.0 资产、需要独立升级引擎版本或使用 XSLTC 预编译分发时,独立 Xalan-J 2.7.3 是正确选择。
八、参考链接
- Xalan-J 官方主页:https://xalan.apache.org/xalan-j/
- 版本发布说明:https://xalan.apache.org/xalan-j/download.html
- Maven Central 坐标:https://repo1.maven.org/maven2/xalan/xalan/
- Xalan-J 命令行工具参考:https://xalan.apache.org/xalan-j/commandline.html
- 《Apache Xalan-J 在 Ubuntu 22.04 集成使用指南》——安装与集成实测。
- 《Apache Xalan-J 2.7.3 配置参数详解》——参数矩阵实测。
- 《Apache Xalan-J 命令行工具详解》——Process/Compile/Transform 逐参数实测。