Apache Xalan 常用 CLI 命令与工具详解

沉淀 Xalan-J 2.7.3 命令行工具:Process 帮助全文、XSLTC Compile/Transform、XML+XSL 转 HTML/TEXT 实测、-PARAM 传参、版本查询与 Maven 构建,全部附真实回显。

Apache XalanApache Xalan2026/10/12

Apache Xalan 常用 CLI 命令与工具详解

目标:把 Apache Xalan-J 2.7.3 的命令行工具一次讲全——org.apache.xalan.xslt.Process、org.apache.xalan.xsltc.cmdline.Compile/Transform、org.apache.xalan.Version 与 Maven 构建命令。所有命令与回显均在 Ubuntu 22.04.5(OpenJDK 17.0.20.1)与 CentOS 8.5.2111(OpenJDK 17.0.1)实测通过,逐条照抄可复现。

一、命令总览

命令归属 jar用途
org.apache.xalan.xslt.Processxalan.jarXSLT 一次性转换(解释型或 -XSLTC 编译型)
org.apache.xalan.xsltc.cmdline.Compilexalan.jar把样式表预编译为 translet 字节码
org.apache.xalan.xsltc.cmdline.Transformxalan.jar用编译好的 translet 执行转换
org.apache.xalan.Versionxalan.jar打印 Xalan-J 版本
mvnMaven工程构建、依赖管理

以上命令都是 java -cp 直跑的工具类,无守护进程。

二、执行前准备

2.1 定位 jar 并设置 classpath

Maven 工程构建后,两个核心 jar 位于本地仓库:

export CP=/root/.m2/repository/xalan/xalan/2.7.3/xalan-2.7.3.jar:/root/.m2/repository/xalan/serializer/2.7.3/serializer-2.7.3.jar

⚠️ 实测:classpath 缺 serializer.jar 时任何转换都报 XSLT Error (java.lang.NoClassDefFoundError): org/apache/xml/serializer/SerializerTrace。

2.2 版本查询

java -cp $CP org.apache.xalan.Version

✅ 实测回显:

Xalan Java 2.7.3

Process 也支持未写进帮助的 -V 开关:

java -cp $CP org.apache.xalan.xslt.Process -V

✅ 实测回显(首行):

>>>>>> Xalan Version Xalan Java 2.7.3, <<<<<<<

三、Process 帮助文本(全文沉淀)

无参数运行 java -cp $CP org.apache.xalan.xslt.Process 输出两页帮助(第一页末尾 (press <return> to continue) 处需按回车继续)。全文如下:

Xalan-J command line Process class options:

                       -Common Options-

  [-XSLTC (use XSLTC for transformation)]
  [-IN inputXMLURL]
  [-XSL XSLTransformationURL]
  [-OUT outputFileName]
  [-E (Do not expand entity refs)]
  [-EDUMP {optional filename} (Do stackdump on error.)]
  [-XML (Use XML formatter and add XML header.)]
  [-TEXT (Use simple Text formatter.)]
  [-HTML (Use HTML formatter.)]
  [-PARAM name expression (Set a stylesheet parameter)]
  [-MEDIA mediaType (use media attribute to find stylesheet associated with a document.)]
  [-FLAVOR flavorName (Explicitly use s2s=SAX or d2d=DOM to do transform.)]
  [-DIAG (Print overall milliseconds transform took.)]
  [-URIRESOLVER full class name (URIResolver to be used to resolve URIs)]
  [-ENTITYRESOLVER full class name (EntityResolver to be used to resolve entities)]
(press <return> to continue)
  [-CONTENTHANDLER full class name (ContentHandler to be used to serialize output)]
  [-SECURE (set the secure processing feature to true.)]

                       -Options for Xalan-

  [-QC (Quiet Pattern Conflicts Warnings)]
  [-TT (Trace the templates as they are being called.)]
  [-TG (Trace each generation event.)]
  [-TS (Trace each selection event.)]
  [-TTC (Trace the template children as they are being processed.)]
  [-TCLASS (TraceListener class for trace extensions.)]
  [-L use line numbers for source document]
  [-INCREMENTAL (request incremental DTM construction by setting http://xml.apache.org/xalan/features/incremental true.)]
  [-NOOPTIMIMIZE (request no stylesheet optimization processing by setting http://xml.apache.org/xalan/features/optimize false.)]
  [-RL recursionlimit (assert numeric limit on stylesheet recursion depth.)]

                       -Options for XSLTC-

  [-XO [transletName] (assign the name to the generated translet)]
(press <return> to continue)
  [-XD destinationDirectory (specify a destination directory for translet)]
  [-XJ jarfile (packages translet classes into a jar file of name <jarfile>)]
  [-XP package (specifies a package name prefix for all generated translet classes)]
  [-XN (enables template inlining)]
  [-XX (turns on additional debugging message output)]
  [-XT (use translet to transform if possible)]

参数语义逐项解读见《Apache Xalan 配置参数详解》。

四、Process 转换命令实测

以下示例输入为 data/books.xml(4 条图书记录)与 data/books.xsl(含变量、for-each 循环、choose 条件、format-number 排版、顶层参数 keyword),完整文件见《Apache Xalan 快速入门与集成示例》第三节。

4.1 XML+XSL 转 HTML

cd /opt/xalan-demo && mkdir -p out
java -cp $CP org.apache.xalan.xslt.Process -IN data/books.xml -XSL data/books.xsl -OUT out/cli.html
head -16 out/cli.html

✅ 实测回显:

<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>图书清单</title>
</head>
<body>
<h1>图书清单(关键字:编程)</h1>
<p>共 1 本匹配,
          全部图书总价:396.40 元</p>
<table cellpadding="4" border="1">
<tr>
<th>书名</th><th>作者</th><th>分类</th><th>价格</th>
</tr>
<tr>
<td>Java 并发编程</td><td>王五</td><td><b>编程类</b></td><td align="right">89.90</td>
</tr>

4.2 XML+XSL 转 TEXT

样式表声明 <xsl:output method="text"/>,命令行加 -TEXT:

java -cp $CP org.apache.xalan.xslt.Process -IN data/books.xml -XSL data/books-text.xsl -TEXT -OUT out/cli.txt
cat out/cli.txt

✅ 实测回显:

Java 核心技术 | 张三 | 99.50
MySQL 调优实战 | 李四 | 79.00
Java 并发编程 | 王五 | 89.90
TCP/IP 详解 | 赵六 | 128.00

4.3 -PARAM 传参 + -DIAG 计时

java -cp $CP org.apache.xalan.xslt.Process -IN data/books.xml -XSL data/books.xsl -PARAM keyword Java -OUT out/cli-java.html -DIAG
grep -o "<h1>.*</h1>" out/cli-java.html
grep -o "共 [0-9]* 本匹配" out/cli-java.html

✅ 实测回显(Ubuntu 22.04,耗时随机器不同):



--------- Transform of data/books.xml via data/books.xsl took 203 ms
<h1>图书清单(关键字:Java)</h1>
共 2 本匹配

⚠️ 实测:POSIX 缺省 locale 下传中文参数(如 -PARAM keyword 数据库)会乱码并导致匹配数为 0,先 export LANG=C.UTF-8。

4.4 指定执行模型与输出器

# DOM2DOM 执行模型
java -cp $CP org.apache.xalan.xslt.Process -IN data/books.xml -XSL data/books.xsl -FLAVOR d2d -OUT out/cli-d2d.html

# 强制 XML 输出器(补 XML 声明)
java -cp $CP org.apache.xalan.xslt.Process -IN data/books.xml -XSL data/books.xsl -XML -OUT out/cli-xml.xml
head -4 out/cli-xml.xml

# 不展开实体引用
java -cp $CP org.apache.xalan.xslt.Process -IN data/books.xml -XSL data/books.xsl -E -OUT out/cli-e.html

✅ 实测回显(cli-xml.xml 头部):

<?xml version="1.0" encoding="UTF-8"?><html>
<head>
<title>图书清单</title>
</head>

4.5 XSLTC 编译型引擎一次转换

java -cp $CP org.apache.xalan.xslt.Process -XSLTC -IN data/books.xml -XSL data/books.xsl -OUT out/cli-xsltc.html
head -7 out/cli-xsltc.html

✅ 实测回显(与解释型输出一致):

<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>图书清单</title>
</head>
<body>
<h1>图书清单(关键字:编程)</h1>

4.6 出错场景与 -EDUMP

构造不合法样式表(未闭合的 xsl:if)后执行:

java -cp $CP org.apache.xalan.xslt.Process -IN data/books.xml -XSL data/books-bad.xsl -OUT out/bad.html -EDUMP out/bad.dmp
ls -l out/bad.dmp

✅ 实测回显(stderr 头部):

[Fatal Error] books-bad.xsl:6:5: The element type "xsl:if" must be terminated by the matching end-tag "</xsl:if>".
file:///opt/xalan-demo/data/books-bad.xsl; Line #6; Column #5; 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>".

⚠️ 实测:随后还会抛 RuntimeException: Cannot invoke "org.apache.xalan.templates.OutputProperties.getProperties()" because "format" is null——这是错误收尾路径的二次异常;定位样式表问题以第一条 SAXParseException 为准,-EDUMP 文件记录的是该二次异常堆栈。

五、XSLTC 独立编译与运行

5.1 Compile 帮助全文

java -cp $CP 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 }

OPTIONS
  -o <output>    assigns the name <output> to the generated
                 translet.  By default the translet name is
                 derived from the <stylesheet> name.  This option
                 is ignored if compiling multiple stylesheets.
  -d <directory> specifies a destination directory for translet
  -j <jarfile>   packages translet classes into a jar file of the
                 name specified as <jarfile>
  -p <package>   specifies a package name prefix for all generated
                 translet classes.
  -n             enables template inlining (default behavior better
                 on average).
  -x             turns on additional debugging message output
  -u             interprets <stylesheet> arguments as URLs
  -i             forces compiler to read stylesheet from stdin
  -v             prints the version of the compiler
  -h             prints this usage statement

5.2 编译 translet

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

5.3 运行 translet 转换

java -cp "out/translet:$CP" org.apache.xalan.xsltc.cmdline.Transform data/books.xml BooksTranslet > out/translet-run.html
head -3 out/translet-run.html

✅ 实测回显:

<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">

⚠️ 实测两个坑:(1) 该命令生效的参数顺序是 XML 文档在前、translet 类名在后——按传统顺序 Transform BooksTranslet data/books.xml 执行会报 Translet errors:Cannot find class 'data/books.xml'.;(2) 转换失败时退出码仍为 0,脚本判断须检查输出。

六、java -jar 直跑 Process

xalan-2.7.3.jar 的 MANIFEST 含 Main-Class: org.apache.xalan.xslt.Process 与 Class-Path: xercesImpl.jar xml-apis.jar serializer.jar,可直接 java -jar:

mkdir -p lib
cp /root/.m2/repository/xalan/xalan/2.7.3/xalan-2.7.3.jar lib/
cp /root/.m2/repository/xalan/serializer/2.7.3/serializer-2.7.3.jar lib/serializer.jar
java -jar lib/xalan-2.7.3.jar -IN data/books.xml -XSL data/books.xsl -OUT out/jar.html
head -3 out/jar.html

✅ 实测回显:

<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">

⚠️ 实测:MANIFEST 的 Class-Path 按精确文件名找依赖,目录里放 serializer-2.7.3.jar 无效(报 NoClassDefFoundError: org/apache/xml/serializer/SerializerTrace),必须命名为 serializer.jar 与 xalan.jar 同目录。

七、Maven 构建命令

cd /opt/xalan-demo
mvn -B clean package          # 编译打包
mvn -B dependency:tree        # 查看依赖树

✅ 实测回显(dependency:tree 关键行):

[INFO] com.example:xalan-demo:jar:1.0.0
[INFO] +- xalan:xalan:jar:2.7.3:compile
[INFO] \- xalan:serializer:jar:2.7.3:compile
[INFO] BUILD SUCCESS

💡 实测结论:xalan:xalan:2.7.3 的 pom 极简(384 字节),不会传递引入 serializer,两个依赖必须都显式声明。

控制构建 JVM 堆(XSLTC 编译大样式表场景建议 256~512MB):

MAVEN_OPTS="-Xms256m -Xmx512m" mvn -B clean package

实测验证(构建进程存活期间抓取):

ps -ef | grep [j]ava

✅ 实测回显(Ubuntu 22.04,截取关键段):

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

✅ 实测回显(CentOS 8,截取关键段):

java -Xms256m -Xmx512m -classpath /usr/share/java/plexus-classworlds.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

八、JVM 堆与性能验证命令

命令行工具进程直接带堆参数(不读取 MAVEN_OPTS/JAVA_OPTS):

java -Xms256m -Xmx512m -cp $CP org.apache.xalan.xslt.Process -XSLTC -IN data/big.xml -XSL data/books.xsl -OUT out/big.html

进程存活期间用 jps -v 验证(配合一个转换后休眠 20 秒的验证程序 MemoryDemo,源码见《Apache Xalan 快速入门与集成示例》第七节):

jps -v

✅ 实测回显(Ubuntu 22.04):

6757 MemoryDemo -Xms256m -Xmx512m

✅ 实测回显(CentOS 8):

1149 MemoryDemo -Xms256m -Xmx512m

程序内核验 Runtime.getRuntime().maxMemory() 实测输出 JVM 最大堆(maxMemory): 512 MB;-DIAG 输出的毫秒数可用于转换耗时基线对比。

九、常见问题

Q1: Process 无参数运行卡住不动?

答:帮助输出分页,第一页末尾 (press <return> to continue) 在等回车。脚本中采集全文用 printf '\n\n' | java -cp $CP org.apache.xalan.xslt.Process。

Q2: 命令行带中文参数乱码?

答:export LANG=C.UTF-8 后重跑;涉及文件名/参数含中文的脚本都建议在开头固化该设置。

Q3: java -jar lib/xalan-2.7.3.jar 报 NoClassDefFoundError: org/apache/xml/serializer/SerializerTrace?

答:MANIFEST Class-Path 找不到同名依赖。把 serializer 的 jar 改名为 serializer.jar 放到 xalan.jar 同目录(实测验证通过)。

Q4: XSLTC 编译出的 translet 能跨机器分发吗?

答:能。translet 是标准字节码,用 -j out.jar 打包后拷贝到目标机器,java -cp "out.jar:<xalan/serializer jar>" org.apache.xalan.xsltc.cmdline.Transform <xml> <translet类名> 即可运行;目标机也需有 xalan+serializer 运行时。

Q5: 转换大文件时进程被 OOM 杀掉?

答:给该 java 进程加 -Xms256m -Xmx512m(按数据量调大),并用 jps -v 确认参数确实生效(实测命令见第八节)。

Q6: 如何只查版本不执行转换?

答:java -cp $CP org.apache.xalan.Version(干净输出)或 java -cp $CP org.apache.xalan.xslt.Process -V(带装饰输出)。

十、参考链接