Apache Xalan-C++ 1.12 常用 CLI 命令与工具详解

Apache Xalan-C++ 1.12 命令行工具全解:Xalan 命令 10 个选项逐项实测(含 -t 计时分流、-m A/B 对照、-p 的 XPath 语义、退出码 0/254/255 体系),TestXSLT 诊断版二进制差异,TestXPath 自测工具,Conf/Performance 回归工具与 16 个官方样例运行实录。

Apache XalanApache XalanC/C++XSLTLinux命令行2026/10/16

Apache Xalan-C++ 1.12 常用 CLI 命令与工具详解

目标:把 Xalan-C++ 1.12 自带的所有命令行工具一次讲全——安装版 Xalan 命令的每个选项配实测回显、退出码体系、与构建树里 TestXSLT 诊断版二进制的差异,以及 TestXPath、MsgCreator、Conf/Performance 与 16 个官方样例的运行方式。全部命令与回显均在真实环境逐条实测。

一、环境信息

项目值
操作系统Ubuntu 22.04.5 LTS(x86_64)
Xalan-C++1.12.0(源码构建安装到 /usr/local,Xerces 3.2.3)
工具来源/usr/local/bin/Xalan(安装版)+ /root/xalan-c-1.12-build(构建树工具)
测试数据/root/xalanc-demo(hello.xml + hello.xsl 学生成绩单)
管理账号root(密码 q1w2e3r4)

二、工具总览:装完有什么

2.1 安装版 vs 构建树

make install 之后 /usr/local/bin 下只有一个 Xalan:

/usr/local/bin/Xalan

其余工具都留在构建树里(实测 /root/xalan-c-1.12-build 产物清单):

工具构建树路径是否随安装用途
Xalan(由构建产出并安装)是生产用 XSLT 转换命令
TestXSLTsrc/xalanc/TestXSLT/TestXSLT否诊断版转换命令(选项更多)
TestXPathsrc/xalanc/TestXPath/TestXPath否XPath 求值自测
MsgCreatorsrc/xalanc/Utils/MsgCreator/MsgCreator否构建期消息编译器
ConfTests/Conf否回归测试驱动(需外部测试数据)
PerformanceTests/Performance否性能基准(需外部测试数据)
16 个样例samples/*否API 用法示范

2.2 重要发现:Xalan 与 TestXSLT 是两个二进制

实测比对(md5sum):

299434775bfa05ef0b05098276f5a400  /usr/local/bin/Xalan
d690f4db1b53b769ab27528c50046278  /root/xalan-c-1.12-build/src/xalanc/TestXSLT/TestXSLT

两者 md5 不同、选项集不同。容易踩的坑:源码 TestXSLT.cpp 里写的 -in/-xsl/-out/-param 等长选项,安装版 Xalan 不接受(实测全部回 usage、exit=255):

$ Xalan -in hello.xml -xsl hello.xsl -out /tmp/in_out.html
Xalan version 1.12.0.
Xerces version 3.2.3.
Usage: Xalan [options] source stylesheet
Options:
  ...(10 项用法列表)
exit=255

而 TestXSLT 接受(实测 -in hello.xml -xsl hello.xsl -out /tmp/tt_out.html exit=0,输出正确 HTML)。需要诊断级选项时用构建树里的 TestXSLT,日常脚本用 Xalan。

三、Xalan 命令详解

3.1 基本信息与帮助全文

Xalan -?

实测全文(-? 与 -h 等价):

Xalan version 1.12.0.
Xerces version 3.2.3.
Usage: Xalan [options] source stylesheet
Options:
  -a                    Use xml-stylesheet PI, not the 'stylesheet' argument
  -e encoding           Force the specified encoding for the output.
  -i integer            Indent the specified amount.
  -m                    Omit the META tag in HTML output.
  -o filename           Write output to the specified file.
  -p name expression    Sets a stylesheet parameter.
  -t                    Display timing information.
  -u                    Disable escaping of URLs in HTML output.
  -?                    Display this message.
  -v                    Validates source documents.
  -                     A dash as the 'source' argument reads from stdin.
                        ('-' cannot be used for both arguments.)

命令形态:Xalan [options] <源XML> <样式表>。不带 -o 时结果打标准输出。前两行版本横幅可当作最轻量的"装没装好"探针。

3.2 逐参数实测

以下测试数据 hello.xml(3 名学生)与 hello.xsl(method="html",及格线参数 $passLine 默认 80)见《Apache Xalan-C++ 在 Ubuntu 22.04 集成使用指南》第四节。

3.2.1 无选项:结果到标准输出

Xalan hello.xml hello.xsl

实测输出:

<html>
<body>
<h2>Score Report</h2>
<table border="1">
<tr>
<th>ID</th><th>Name</th><th>Score</th><th>Result</th>
</tr>
<tr>
<td>2026001</td><td>Alice</td><td>92</td><td>PASS</td>
</tr>
<tr>
<td>2026002</td><td>Bob</td><td>85</td><td>PASS</td>
</tr>
<tr>
<td>2026003</td><td>Charlie</td><td>78</td><td>FAIL</td>
</tr>
</table>
</body>
</html>

3.2.2 -o:输出到文件

Xalan -o /root/xalanc-demo/report.html hello.xml hello.xsl
echo "exit=$?"

实测 exit=0,report.html 内容与标准输出版本一致(同上表结构)。-o 可以指向 /dev/null 做"只验语法"式干跑。

3.2.3 -t:计时信息(走标准错误)

Xalan -t -o /dev/null hello.xml hello.xsl 1>stdout.txt 2>stderr.txt
echo "exit=$?"; echo "--stderr--"; cat stderr.txt; echo "--stdout--"; cat stdout.txt

实测:

exit=0
--stderr--
Source tree parsing time: 0.228 milliseconds.
Stylesheet compilation time: 0.337 milliseconds.
Transformation time: 0.121 milliseconds.
--stdout--
(空)

💡 技术拓展:-t 的三段耗时(源树解析/样式表编译/变换执行)对性能排查很有用——如果"样式表编译时间"占比高,应该像 CompileStylesheet 样例那样预编译样式表复用(一次编译对多份 XML);如果"源树解析时间"占比高,瓶颈在 XML 大小而非样式复杂度。

3.2.4 -p:设置样式表参数(XPath 语义)

数值参数(无引号直接生效):

Xalan -p passLine 70 hello.xml hello.xsl | grep -E "Charlie|Result"

实测(78 分越过新及格线 70,FAIL 翻 PASS):

<th>ID</th><th>Name</th><th>Score</th><th>Result</th>
<td>2026003</td><td>Charlie</td><td>78</td><td>PASS</td>

字符串参数必须带 XPath 字符串引号。裸字符串实测报错(样式表引用了 $title):

$ Xalan -p title "Q1 Score" -o /dev/null hello.xml api/param_demo.xsl
XPath error: Extra illegal token.
expression = 'Q1 Score' Remaining tokens are:  ( 'Score') (Occurred in an unknown entity, at an unknown location.)
XPathParserException: Extra illegal token.
expression = 'Q1 Score' Remaining tokens are:  ( 'Score') (Occurred in an unknown entity, at an unknown location.)
exit=255

正确写法(单引号包住字面量,实测输出 title 属性正确注入):

$ Xalan -p title "'Q1 Score'" -o /tmp/pd_cli.xml hello.xml api/param_demo.xsl
exit=0
<?xml version="1.0" encoding="UTF-8"?>
<report title="Q1 Score" threshold="80">
<passed count="2"/>
</report>

💡 技术拓展:C1《Apache Xalan-C++ 1.12 配置参数详解》用 API 路径验证了同一语义(裸串 result=-1、引号串 result=0),并发现顶层参数惰性求值——样式表不引用该参数时,裸字符串错误不会触发。CLI 与 API 共享同一套 XPath 求值器,行为完全一致。

3.2.5 -i:指定缩进空格数

对照实测(cat -A 显示空白符,$ 为行尾):

$ Xalan hello.xml hello.xsl            (默认,无缩进)
<html>$
<body>$
<h2>Score Report</h2>$

$ Xalan -i 2 hello.xml hello.xsl       (-i 2)
<html>$
  <body>$
    <h2>Score Report</h2>$
    <table border="1">$

-i 只影响 HTML/XML 的缩进排版,不改变内容。-i 0 与默认相同。

3.2.6 -e:强制输出编码

UTF-16 实测(xmlout.xsl 输出 <report count="3"/>):

$ Xalan -e UTF-16 -o /tmp/u16.xml hello.xml xmlout.xsl
exit=0
$ od -c /tmp/u16.xml | head -4
0000000 377 376   <  \0   ?  \0   x  \0   m  \0   l  \0      \0   v  \0
0000020   e  \0   r  \0   s  \0   i  \0   o  \0   n  \0   =  \0   "  \0
0000040   1  \0   .  \0   0  \0   "  \0      \0   e  \0   n  \0   c  \0
0000060   o  \0   d  \0   i  \0   n  \0   g  \0   =  \0   "  \0   U  \0

377 376(0xFF 0xFE)是 UTF-16LE 的 BOM,后续每个字符占双字节,且文件内声明同步变为 encoding="UTF-16",强制编码确实生效。对照默认 XML 输出:

$ Xalan hello.xml xmlout.xsl
<?xml version="1.0" encoding="UTF-8"?><report count="3"/>

如实记录:-e GBK 场景实测未产生可用输出(输出文件为空),GBK 支持取决于转码后端(本环境为 ICU);需要 GBK 时建议先验证,不要默认可用。

3.2.7 -m:省略 HTML 输出的 META 标签(A/B 对照)

用官方 XalanTransform 样例数据(foo.xml + foo.xsl,含 head):

$ Xalan foo.xml foo.xsl | head -4            (默认)
<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>s1 foo</title>

$ Xalan -m foo.xml foo.xsl | head -4         (加 -m)
<html>
<head>
<title>s1 foo</title>
</head>

META 行确实被省略。两者 exit 均为 0。

3.2.8 -u:禁用 HTML 输出的 URL 转义

实测命令被正常接受(exit=0),输出与默认一致。该选项只在 HTML 结果含 URL 类属性(href/src)且其中带特殊字符时才有可见差异;演示数据无 URL 属性,属预期。

3.2.9 -a:改用 xml-stylesheet 处理指令定位样式表

准备 pi.xml(内嵌 <?xml-stylesheet type="text/xsl" href="hello.xsl"?>),实测:

Xalan -a pi.xml

输出与 Xalan pi.xml hello.xsl 等效的 HTML(exit=0),命令行上不再写样式表参数。-a 生效时第二个位置参数被忽略。

3.2.10 -v:开启源文档校验

Xalan -v -o /dev/null hello.xml hello.xsl

实测 exit=0(hello.xml 本身合法,校验不报问题)。-v 打开 DTD 校验语义;无 DTD 的文档行为不变。

3.2.11 -(连字符):stdin 作为源文档

cat hello.xml | Xalan - hello.xsl | head -3

实测输出正常 HTML(exit=0)。注意帮助文本的红字约束:'-' 不能同时用于两个参数(样式表没有 stdin 写法)。

3.2.12 -?:帮助(exit=255)

$ Xalan -?
...(帮助全文)
exit=255

帮助与"未知选项"共用同一 usage 输出,退出码都是 255(实测 Xalan --bogus hello.xml hello.xsl 同样打印 usage、exit=255)。

3.3 退出码体系(实测汇总)

退出码场景实测触发命令与 stderr 样例
0转换成功Xalan hello.xml hello.xsl
254转换失败(解析/加载错误)样式表不存在:XML warning: Fatal Error: unable to determine file base pathname (Occurred in an unknown entity, at line 0, column 0.) + SAXParseException: unable to determine file base pathname (...)
254源 XML 非法Fatal Error: expected end of tag 'b' (Occurred in entity 'bad.xml', at line 1, column 9.) + SAXParseException: ...
255用法错误/帮助/-p 的 XPath 表达式错误未知选项、-?、裸字符串参数的 XPath error: Extra illegal token

脚本化使用建议:Xalan ... || { case $? in 254) ...文档问题...;; 255) ...调用方式问题...;; esac; }——254 提示去修数据,255 提示去修命令。

3.4 构建树里的 TestXSLT(诊断版补充)

TestXSLT 的 -h(实测全文节选)暴露了它比 Xalan 多出的能力:

TestXSLT options:
Options are case-sensitive.

 [-? Shows this message.]  [-h Shows this message.]
 [-in <source URL> (If not specified, stdin is used.)]
 [-xsl <stylesheet URL>]  [-out <output file>]
 [-v  Show version information only.]
 [-qc  Quiet pattern conflicts warnings.]
 [-q  Use quiet mode.]
 [-indent n  Controls how many spaces to indent. (default is 0)]
 [-validate  Controls whether validation occurs...]
 [-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.]
 [-xml  Use XML formatter.]  [-text  Use Text formatter.]  [-html  Use HTML formatter.]
 [-dom  Use DOM formatter...]  [-xst  Use source tree formatter...]
 [-param name expression  Sets a stylesheet parameter.]
 [-xd  Use Xerces DOM instead of Xalan source tree.]
 [-de  Disable built-in extension functions.]
 [-noindent  Turns off HTML indenting.]  [-nh  Don't generate the XML declaration.]

实测 -in/-xsl/-out 组合转换成功(exit=0)。TestXSLT 的 -v 是"只显示版本"(输出 Xalan version 1.12.0 / Xerces version 3.2.3 后退出),与 Xalan 的 -v(校验开关)同名不同义,混用时务必分清操作的是哪个二进制。

四、TestXPath:XPath 自测工具

4.1 运行方式

构建树产物,不接收参数,运行即执行内置表达式自测:

/root/xalan-c-1.12-build/src/xalanc/TestXPath/TestXPath

实测输出(节选):

Execution of XPath 9 + 7 - 6 * 42 + 36 div 3 + 100 - 2 * 6 succeeded.
The result was -136
Execution of XPath 9 + 7 - 6 + 3 + 24 - 32 - 89 + 123 - 12256 + 89957 succeeded.
The result was 77740
Execution of XPath 0 + 0 succeeded.
The result was 0
Execution of XPath 1 div 2 succeeded.
The result was 0.5
Execution of XPath 1 * 0.25 succeeded.
The result was 0.25
Execution of XPath 3 * 3 * 3 succeeded.
The result was 27

定位是"跑一遍 XPath 求值器自检",不是通用求值器——想对任意表达式求值,走 SimpleXPathAPI 样例或写十几行 XObjectFactory 代码(TestXPath.cpp 源码演示了完整用法:#include <xalanc/XPath/XObjectFactoryDefault.hpp> 等,实测源码 1300+ 行)。

五、MsgCreator:构建期消息编译器

构建树 src/xalanc/Utils/MsgCreator/MsgCreator(实测产物存在)。它不面向用户:构建 Xalan 时先编译 MsgCreator,由它扫描源码消息 ID 生成 XalanMsgLib(libxalanMsg)的源码。安装版不携带、日常零交互。只有在自行新增本地化 locale(重编 NLS 消息目录)时才会接触它。

六、Conf 与 Performance:回归与性能工具

两者都构建于 Tests/ 目录,需要外部的 xalan-test 测试数据(官方 XSLT 测试集,源码包不附带)。裸跑实测:

$ Conf
Using Xalan version 1.12.0
Using Xerces version 3.2.3

conf dir [-sub -out -gold -source (XST | XPL | DOM)]

dir        (base directory for testcases)
-sub dir   (specific directory)
-out dir   (base directory for output)
-gold dir  (base directory for gold files)
-source type   (parsed source; XalanSourceTree(d), XercesParserLiasion, XercesDOM)
exit=0

指向不存在目录时的行为:

Given base directory "tests/" does not exist

Performance 裸跑打印用法:

Usage: perf [options] -test [test directory ] -result [result directory ] -baseline [baseline directory] -report [report directory ] configfile

结论:没有 xalan-test 数据集时这两件工具只是"会说话的空壳";日常功能验证用 ctest(下节)已足够。

七、16 个官方样例运行实录

7.1 样例清单与运行要求

构建树 samples/ 下 16 个可执行(清单实测),必须在各自信源目录里运行(工作目录需要配套 foo.xml/birds.xsl 等数据文件)。ctest 已自动化这一过程(21 项含 4 项 TraceListen、2 项 SimpleXPathAPI)。

7.2 代表性运行输出(全部实测转录)

XalanTransform(最小变换,结果到标准输出):

<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>s1 foo</title>
</head>
<body bgcolor="#ffffff" text="#000000">
<table width="100%" border="0" cellspacing="0" cellpadding="4">
<tr>
<td bgcolor="#006699"><font color="#ffffff" size="+1"><b>Foo</b></font></td>
</tr>
</table>
    <p>Hello</p>
  <br>
</body>
</html>

UseStylesheetParam(三类参数注入,命令含 4 个参数对):

$ UseStylesheetParam foo.xml foo.xslt foo.out \
    -s stringA "'This is a test string value'" \
    -n numberA 123.012345 \
    -d parmA parmA.xml -d parmB parmB.xml
--- foo.out ---
<?xml version="1.0" encoding="UTF-8"?><OUTPUT><NumberParam>123.012345</NumberParam><root>
 <Item>Item-1</Item>
 <Item>Item-2</Item>
 <Item>Item-3</Item>
</root><ParameterA><xparm>
 <Item>First A Item</Item>
 <Item>Second A Item</Item>
</xparm></ParameterA><ParameterB><xparm>
 <Item>First B Item</Item>
 <Item>Second B Item</Item>
</xparm></ParameterB><StringA>This is a test string value</StringA></OUTPUT>

-s/-n/-d 分别对应字符串(带 XPath 引号)、数值、XML 文档节点集三种参数类型,与 API 的三个 setStylesheetParam 重载一一对应。

TraceListen(四种跟踪模式,birds 数据集):

-tt(模板调用)节选:

line 18446744073709551615, column 18446744073709551615.: xsl:template  match='/'  
line 5, column 29.: xsl:template  match='Class'  
line 11, column 29.: xsl:template  match='Order'  
line 27, column 31.: xsl:template  match='Species'  

(18446744073709551615 即 2^64-1,未关联行号的内置规则显示为最大值,正常现象。)-tg(生成事件)节选:

STARTDOCUMENT
STARTELEMENT: BirdInfo
CHARACTERS: 
Order is:  
CHARACTERS: TINAMIFORMES

-ts(选择事件)与 -ttc(模板子节点)同样有独立输出格式;-ttc 能看到每个 xsl:value-of/xsl:apply-templates 的行列号,排查"哪条规则输出了什么"时最有用。

SerializeNodeSet(XPath 节点集序列化):

$ SerializeNodeSet foo.xml /doc "name[@first='David']"
<name last="Marston" first="David">Mr. Marston</name><name last="Bertoni" first="David">Mr. Bertoni</name>exit=0

SimpleXPathAPI(两组测试):

The string value of the result is:
Marston        (-1 组:/foo:doc foo:name/@last)

The string value of the result is:
Emily          (-2 组:/ //foo:name[position()="4"]/@first)

ThreadSafe(三线程并发):

Clock before starting threads: 7006

Starting Thread: 124158280840768
Starting Thread: 124158272448064
Starting Thread: 124158128158272
exit=0

SimpleXPathCAPI(纯 C 接入):

The result of the expression was 'true'.
exit=0

StreamTransform / SimpleTransform / CompileStylesheet / DocumentBuilder / EntityResolver / ExternalFunction / ParsedSourceWrappers / TransformToXercesDOM / XalanTransformerCallback:实测全部 exit=0 正常完成(TransformToXercesDOM 输出 Xerces DOM 序列化树;CompileStylesheet 演示一份样式表对 foo1-foo10 十份 XML 的复用变换)。

八、ctest:一键全量自检

cd /root/xalan-c-1.12-build && ctest

实测结论:21/21 通过,0 失败,总耗时 0.26 秒。升级 Xerces 版本、改编译器或换发行版后,先跑 ctest 再上业务,是最便宜的健康检查。

九、注意事项与常见问题

Q1:Xalan 提示 usage 且 exit=255? 选项拼错或用了 TestXSLT 专属选项(-in/-xsl/-out 等)。Xalan 只认 3.1 节列表里的 10 个短选项。

Q2:-p 传字符串报 XPath error? 给字面量加 XPath 引号:-p title "'Q1 Score'"。裸文本是非法 XPath 表达式。

Q3:exit=254 但看不出哪错? 看 stderr 的 SAXParseException 行,带实体文件名与行列号(实测 at line 1, column 9 精确定位到坏标签)。

Q4:TestXPath 能当表达式计算器吗? 不能,它跑内置自测集。任意表达式求值用 SimpleXPathAPI 思路自写或借 XalanCLI -p + 丢弃输出干跑。

Q5:Conf/Performance 报 base directory does not exist? 缺外部 xalan-test 测试集,需要单独下载并按 -dir 指向它。

Q6:样例二进制在哪、怎么跑? /root/xalan-c-1.12-build/samples/<名>/<名>,必须 cd 到对应源码目录再执行(数据文件在工作目录)。

十、参考链接

  1. Xalan-C++ 官方主页:https://xalan.apache.org/xalan-c/
  2. 样例源码仓库:https://github.com/apache/xalan-c
  3. xalan-test 测试集(Conf/Performance 依赖):https://github.com/apache/xalan-test
  4. W3C XSLT 1.0 规范:https://www.w3.org/TR/1999/REC-xslt-19991116
  5. 本专栏相关文档:《Apache Xalan-C++ 在 Ubuntu 22.04 集成使用指南》《Apache Xalan-C++ 1.12 配置参数详解》《Apache Xalan-C++ 介绍与选型指南》