Apache Xalan 配置参数详解
详解 Apache Xalan-J 2.7.3 配置:Process 命令行参数逐项与实测回显、Transformer 输出属性、XSLTC 编译器选项、JAXP 系统属性切换与 JVM 堆设置,附常见问题与官方参考链接。
Apache Xalan 配置参数详解
目标:系统梳理 Apache Xalan-J 2.7.3 的全部配置入口——命令行
org.apache.xalan.xslt.Process参数、XSLTC 独立编译器选项、Transformer/JAXP 编程接口属性、JAXP 系统属性与 JVM 参数。文中标注"实测"的条目均已在 Ubuntu 22.04.5 + OpenJDK 17.0.20.1 与 CentOS 8.5.2111 + OpenJDK 17.0.1 双环境验证,回显为真实输出。
一、配置总览与实测环境
Xalan-J 没有服务进程与全局配置文件,配置分布在四个层面:
| 层面 | 入口 | 典型用途 |
|---|---|---|
| 命令行 | org.apache.xalan.xslt.Process 参数、org.apache.xalan.xsltc.cmdline.Compile 选项 | 一次性转换、CI 脚本 |
| 编程接口 | Transformer.setOutputProperty、TransformerFactory.setAttribute/setFeature/setErrorListener | 应用内嵌转换 |
| JVM/系统属性 | -Djavax.xml.transform.TransformerFactory、-Xms/-Xmx、MAVEN_OPTS | 工厂切换、内存 |
| 服务声明 | xalan.jar 内 META-INF/services/javax.xml.transform.TransformerFactory | classpath 默认工厂 |
实测环境:
| 项目 | 环境 A | 环境 B |
|---|---|---|
| 操作系统 | Ubuntu 22.04.5 LTS | CentOS Linux 8.5.2111 |
| JDK | OpenJDK 17.0.20.1 | OpenJDK 17.0.1 |
| Maven | 3.6.3 | 3.5.4 |
| Xalan-J | xalan:xalan:2.7.3 + serializer:2.7.3 | 同左 |
二、Process 命令行参数逐项详解
执行 java -cp <xalan.jar>:<serializer.jar> org.apache.xalan.xslt.Process(无参数)输出分两页帮助(第二页需按回车),完整文本沉淀见《Apache Xalan 常用 CLI 命令与工具详解》第四节。参数分三组:通用、解释型专用、XSLTC 专用。
2.1 通用输入输出参数
| 参数 | 说明 |
|---|---|
-IN inputXMLURL | 输入 XML 文档的 URL 或路径 |
-XSL XSLTransformationURL | 样式表 URL;省略时按 -MEDIA 或文档内 xml-stylesheet 处理指令查找关联样式表 |
-OUT outputFileName | 输出文件;目录必须预先存在,实测目录缺失直接报 XSLT Error (java.io.FileNotFoundException): out/cli.html (No such file or directory) |
-XML | 强制使用 XML 输出器并写 XML 声明 |
-HTML | 强制使用 HTML 输出器 |
-TEXT | 强制使用纯文本输出器 |
-E | 不展开实体引用 |
-EDUMP {可选文件名} | 出错时转储堆栈;实测给文件名时生成转储文件,内容为错误收尾路径的异常堆栈 |
三个格式化开关实测对比(同一样式表 xsl:output method="html"):
- 默认/
-HTML:输出<META http-equiv="Content-Type" content="text/html; charset=UTF-8">,无 XML 声明; -XML:实测输出以<?xml version="1.0" encoding="UTF-8"?><html>开头;-TEXT:配合method="text"样式表输出纯文本行,实测:
Java 核心技术 | 张三 | 99.50 MySQL 调优实战 | 李四 | 79.00 Java 并发编程 | 王五 | 89.90 TCP/IP 详解 | 赵六 | 128.00
2.2 参数传递与诊断
| 参数 | 说明 |
|---|---|
-PARAM name expression | 设置样式表顶层 xsl:param。值按 XPath 表达式处理,实测直接传单词(如 Java)按字符串生效;传中文在 UTF-8 locale 下正常(需 LANG=C.UTF-8,实测 POSIX locale 下乱码并导致匹配数错误) |
-MEDIA mediaType | 按 xml-stylesheet 处理指令的 media 属性选择关联样式表 |
-FLAVOR flavorName | 显式指定执行模型:s2s(SAX2SAX 流式)或 d2d(DOM2DOM);实测 -FLAVOR d2d 与默认结果一致 |
-DIAG | 打印总耗时;实测回显 --------- Transform of data/books.xml via data/books.xsl took 203 ms |
-PARAM 实测示例:
java -cp $CP org.apache.xalan.xslt.Process -IN data/books.xml -XSL data/books.xsl \
-PARAM keyword Java -OUT out/cli-java.html
grep -o "共 [0-9]* 本匹配" out/cli-java.html
✅ 实测回显:
共 2 本匹配
2.3 解析器与安全扩展
| 参数 | 说明 |
|---|---|
-URIRESOLVER 全类名 | 指定实现 javax.xml.transform.URIResolver 的类,解析 document()/xsl:import 等 URI |
-ENTITYRESOLVER 全类名 | 指定实现 org.xml.sax.EntityResolver 的类,接管实体解析 |
-CONTENTHANDLER 全类名 | 指定自定义 ContentHandler 接收序列化输出 |
-SECURE | 开启 secure processing:限制扩展函数、document() 访问等,防外部资源滥用 |
2.4 解释型引擎专用参数(不带 -XSLTC 时生效)
| 参数 | 说明 |
|---|---|
-QC | 安静模式,抑制模板匹配冲突告警 |
-TT | 跟踪模板被调用的事件 |
-TG | 跟踪每个生成(generation)事件 |
-TS | 跟踪每次节点选择(selection)事件 |
-TTC | 跟踪模板子节点处理事件 |
-TCLASS 类名 | 指定自定义 TraceListener 扩展类 |
-L | 为源文档行号跟踪(错误定位更精确) |
-INCREMENTAL | 开启增量 DTM 构造(http://xml.apache.org/xalan/features/incremental),适合提前输出场景 |
-NOOPTIMIMIZE | 关闭样式表优化(http://xml.apache.org/xalan/features/optimize=false),排查优化器问题时用 |
-RL 深度 | 限制样式表递归深度,防止失控递归耗尽内存 |
2.5 XSLTC 引擎专用参数
先加 -XSLTC 切换编译型引擎,再配以下参数:
| 参数 | 说明 |
|---|---|
-XSLTC | 本次转换改用 XSLTC 引擎(先编译为 translet 再执行);实测 -XSLTC -IN ... -XSL ... -OUT ... 输出与解释型一致 |
-XO [transletName] | 指定生成的 translet 类名 |
-XD 目录 | translet 输出目录 |
-XJ jarfile | 把 translet 类打包进指定 jar |
-XP 包名 | 为所有生成的 translet 类加包名前缀 |
-XN | 开启模板内联(template inlining) |
-XX | 额外调试信息输出 |
-XT | 若可行则直接用已有 translet 转换 |
三、Transformer 编程接口属性
3.1 输出属性(OutputKeys)
通过 transformer.setOutputProperty(key, value) 设置,与 XSLT xsl:output 等价:
| 属性常量 | 取值示例 | 说明 |
|---|---|---|
OutputKeys.METHOD | xml / html / text | 输出方法 |
OutputKeys.ENCODING | UTF-8 | 输出编码 |
OutputKeys.INDENT | yes / no | 是否缩进 |
OutputKeys.OMIT_XML_DECLARATION | yes / no | 是否省略 XML 声明 |
OutputKeys.VERSION | 1.0 | 输出版本 |
OutputKeys.STANDALONE | yes / no | standalone 声明 |
OutputKeys.DOCTYPE_PUBLIC / DOCTYPE_SYSTEM | 公共/系统标识 | 生成 DOCTYPE |
OutputKeys.CDATA_SECTION_ELEMENTS | 元素名列表 | 指定元素文本按 CDATA 输出 |
OutputKeys.MEDIA_TYPE | text/html | 输出 MIME 类型 |
实测片段(见《Apache Xalan 快速入门与集成示例》):
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
实测输出(HTML 头部):
<html> <head> <META http-equiv="Content-Type" content="text/html; charset=UTF-8">
3.2 参数与引擎特征
// 外部参数:对应样式表顶层 xsl:param
transformer.setParameter("keyword", "Java");
// 工厂特征:安全处理(等价命令行 -SECURE)
factory.setFeature(javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING, true);
// 解释型引擎特征(setAttribute,URI 即特性名)
factory.setAttribute("http://xml.apache.org/xalan/features/incremental", Boolean.TRUE);
factory.setAttribute("http://xml.apache.org/xalan/features/optimize", Boolean.FALSE);
3.3 错误监听
TransformerFactory.setErrorListener 管样式表编译期错误,Transformer.setErrorListener 管转换期错误。实测自定义监听器对不合法样式表输出:
[样式表致命错误] org.xml.sax.SAXParseException; systemId: file:/opt/xalan-demo/data/books-bad.xsl; lineNumber: 6; columnNumber: 5; The element type "xsl:if" must be terminated by the matching end-tag "</xsl:if>". 捕获 TransformerException: javax.xml.transform.TransformerException: org.xml.sax.SAXParseException; ... EXIT=1
四、XSLTC 独立编译器选项
工具类:org.apache.xalan.xsltc.cmdline.Compile(实测自报 XSLTC version 1.4)。无参数运行输出用法:
SYNOPSIS java org.apache.xalan.xsltc.cmdline.Compile [-o <output>] [-d <directory>] [-j <jarfile>] [-p <package>] [-n] [-x] [-u] [-v] [-h] { <stylesheet> | -i }
| 选项 | 说明 |
|---|---|
-o <output> | 生成的 translet 类名(编译多个样式表时忽略) |
-d <directory> | translet 输出目录(目录须已存在) |
-j <jarfile> | 把 translet 类打包为 jar |
-p <package> | translet 类的包名前缀 |
-n | 启用模板内联(官方说明默认行为平均更优) |
-x | 额外调试输出 |
-u | 把样式表参数当 URL 解析 |
-i | 从 stdin 读样式表 |
-v | 打印编译器版本(实测 XSLTC version 1.4) |
-h | 帮助 |
编译与运行实测:
java -cp $CP org.apache.xalan.xsltc.cmdline.Compile -o BooksTranslet -d out/translet data/books.xsl
ls out/translet/
✅ 实测回显:
BooksTranslet$0.class BooksTranslet$1.class BooksTranslet$2.class BooksTranslet.class
运行编译好的 translet(注意实测 2.7.3 的参数顺序为 XML 在前、translet 类名在后):
java -cp "out/translet:$CP" org.apache.xalan.xsltc.cmdline.Transform data/books.xml BooksTranslet
✅ 实测回显(stdout,截取头部):
<html> <head> <META http-equiv="Content-Type" content="text/html; charset=UTF-8">
五、JAXP 系统属性与 JVM 参数
5.1 工厂选择属性 javax.xml.transform.TransformerFactory
四种场景实测回显(TransformerFactory.newInstance().getClass().getName()):
| 场景 | 实测结果 |
|---|---|
| classpath 无 xalan.jar | com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl(JDK 内置) |
| classpath 有 xalan.jar(默认) | org.apache.xalan.processor.TransformerFactoryImpl(解释型,来自 jar 内服务文件) |
-Djavax.xml.transform.TransformerFactory=org.apache.xalan.xsltc.trax.TransformerFactoryImpl | org.apache.xalan.xsltc.trax.TransformerFactoryImpl(XSLTC 编译型) |
-Djavax.xml.transform.TransformerFactory=org.apache.xalan.processor.TransformerFactoryImpl | org.apache.xalan.processor.TransformerFactoryImpl(解释型,显式) |
优先级:JVM 系统属性 > $JAVA_HOME/conf/jaxp.properties(JDK 9+,JDK 8 位于 $JAVA_HOME/lib/jaxp.properties)> classpath 服务声明 > JDK 平台默认。OpenJDK 17 下实测以上四种组合全部正常工作,无需 --add-opens。
5.2 JVM 堆参数(-Xms/-Xmx)
mvn构建进程:MAVEN_OPTS(可放环境变量、/etc/profile.d/maven.sh或~/.mavenrc);- 命令行 java 进程(Process/XSLTC):直接写
java -Xms256m -Xmx512m ...,不读取MAVEN_OPTS/JAVA_OPTS(这两个变量只被 mvn、Tomcat 等包装脚本消费); - 应用内嵌:在应用启动脚本里给
java命令加-Xms256m -Xmx512m。
XSLTC 编译大样式表、转换大文档建议 256~512MB:
MAVEN_OPTS="-Xms256m -Xmx512m" mvn -B clean package
java -Xms256m -Xmx512m -cp $CP org.apache.xalan.xslt.Process -XSLTC -IN data/big.xml -XSL data/books.xsl -OUT out/big.html
实测验证回显(进程保持存活期间抓取):
ps -ef | grep [j]ava
✅ Ubuntu 22.04 实测(Maven 构建进程,截取关键段):
java -Xms256m -Xmx512m -classpath /usr/share/maven/boot/plexus-classworlds-2.x.jar -Dclassworlds.conf=/usr/share/maven/bin/m2.conf -Dmaven.home=/usr/share/maven -Dlibrary.jansi.path=/usr/share/maven/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/opt/xalan-demo org.codehaus.plexus.classworlds.launcher.Launcher -B clean package
jps -v
✅ 实测(Ubuntu:
6757 MemoryDemo -Xms256m -Xmx512m;CentOS 8:1149 MemoryDemo -Xms256m -Xmx512m)6757 MemoryDemo -Xms256m -Xmx512m
程序内核验:Runtime.getRuntime().maxMemory() 实测打印 JVM 最大堆(maxMemory): 512 MB。
六、常见问题
Q1: 加了 -Djavax.xml.transform.TransformerFactory 却仍拿到 JDK 内置实现?
答:确认 -D 在 java 命令与主类之间(不是命令尾部);确认运行环境是同一个 JVM;JAXP 属性优先级最高,若仍无效说明 classpath 与 -cp 不一致。
Q2: -PARAM 传中文乱码、匹配数错误?
答:系统 locale 不是 UTF-8。export LANG=C.UTF-8 后重跑;Java 程序 stdout 中文变问号同理。实测该问题在 Ubuntu 22.04 与 CentOS 8.5 缺省 locale 下均会出现。
Q3: -OUT 报 FileNotFoundException 但文件明明可写?
答:是父目录不存在。Process 不会自动建目录,先 mkdir -p out。
Q4: cmdline.Compile 生成的 translet 运行时报 Cannot find class '<XML 路径>'?
答:实测 2.7.3 的 cmdline.Transform 生效参数顺序是 XML 文档在前、translet 类名在后;另外它失败时退出码仍为 0,脚本需检查输出内容而非退出码。
Q5: -EDUMP 生成的转储里是 NPE 而不是样式表错误?
答:实测样式表 XML 不合法时,Process 先在 stderr 打印 [Fatal Error] ... SAXParseException(真正原因,看它);-EDUMP 文件记录的是错误收尾路径的二次 RuntimeException("format" is null),仅供辅助。
Q6: 只想换输出编码,命令行怎么传?
答:命令行编码由样式表 <xsl:output encoding="UTF-8"/> 决定;编程接口用 setOutputProperty(OutputKeys.ENCODING, "UTF-8")。XML 源/样式表自身的解析编码由其 XML 声明决定,与系统 locale 无关(实测 POSIX locale 下读 UTF-8 的 XML/XSL 输出中文正常)。
七、参考链接
- Apache Xalan 官网:https://xalan.apache.org/
- Xalan-J 文档主页:https://xalan.apache.org/xalan-j/
- Xalan-J 命令行工具文档:https://xalan.apache.org/xalan-j/commandline.html
- JAXP 文档(Oracle,TransformerFactory 查找规则):https://docs.oracle.com/javase/8/docs/api/javax/xml/transform/TransformerFactory.html
- Maven Central:xalan:xalan:2.7.3:https://central.sonatype.com/artifact/xalan/xalan/2.7.3
- GitHub 源码仓库(apache/xalan-java):https://github.com/apache/xalan-java