Apache FOP 2.11 常用 CLI 命令与工具详解
逐项实测 fop 命令行全部输入输出模式、XML+XSL 管道与 -param、PDF 加密与 PDF/A-1b、批量渲染与内存压测,含 -out list NPE 等 10 个实测 FAQ
Apache FOP 2.11 常用 CLI 命令与工具详解
一、命令行概览
fop 是单入口命令行工具,本文环境:Ubuntu 22.04.5 / OpenJDK 11.0.32.1 / Apache FOP 2.11(安装于 /opt/fop,全局软链 /usr/local/bin/fop)。fop -h 输出的用法总纲:
USAGE
fop [options] [-fo|-xml] infile [-xsl file] [-awt|-pdf|-mif|-rtf|-tiff|-png|-pcl|-ps|-txt|-at [mime]|-print] <outfile>
命令由三段构成:输入模式(-fo / -xml / -atin / -ifin / -imagein / 位置参数)、可选的 -xsl 与 -param、输出模式(-pdf / -ps / ... / -out)。另有一组脚本级选项(--help/-h、--noconfig、--execdebug)在 FOP 选项之前由启动脚本处理。
所有实测命令均在 /work 目录下执行,配置文件 /work/conf/fop-cjk5.xconf 注册了文泉驿正黑与 Droid Sans Fallback 两个 CJK 字体(注册方法见配置篇第三章)。
二、输入模式
2.1 直接渲染 XSL-FO:-fo 与位置参数
cd /opt/fop/fop
./fop examples/fo/basic/simple.fo /work/out/simple.pdf
./fop -fo examples/fo/basic/simple.fo -pdf /work/out/simple.pdf
两种写法等价(-h 的 Examples 段原文:fop -fo foo.fo -pdf foo.pdf (does the same as the previous line))。无扩展名歧义时推荐显式 -fo/-pdf,脚本里不易踩坑。
2.2 stdin 与 stdout 管道
输入输出都支持 -(stdin/stdout):
cat /work/out/news.fo | ./fop -c /work/conf/fop-cjk5.xconf -fo - -pdf - > /work/out/pipe.pdf
实测输出:
-rw-r--r-- 1 root root 12842 Oct 14 14:06 /work/out/pipe.pdf
日志走 stderr,管道重定向 stdout 即可拿到干净的 PDF 二进制。
2.3 XML + XSLT 转换渲染:-xml 与 -xsl
最常见的生产模式——XML 数据 + 样式表直接出 PDF:
export LANG=C.UTF-8
./fop -c /work/conf/fop-cjk5.xconf \
-xml /work/src/news.xml -xsl /work/src/news.xsl \
-param title-prefix "季度报告:" \
-pdf /work/out/news.pdf
实测输出(stderr):
INFO: Rendered page #1.
产物 13,606 字节,pdftotext 可提取到 季度报告:FOP 转换管道演示,说明 -param 传参生效。
2.4 -param 传递样式表参数
-param name value <value> to use for parameter <name> in xslt stylesheet
(repeat '-param name value' for each parameter)
每个 -param 传一个参数,多个参数重复书写。XSL 侧用 <xsl:param name="title-prefix"/> 接收。注意 -param 的值是字符串,含空格时整体加引号。
2.5 -foout:只转换不渲染
排查样式表问题的利器——把 XML+XSL 的中间 XSL-FO 结果存盘:
./fop -c /work/conf/fop-cjk5.xconf -xml /work/src/news.xml -xsl /work/src/news.xsl \
-param title-prefix "季度报告:" -foout /work/out/news.fo
实测输出:
-rw-r--r-- 1 root root 910 Oct 14 14:05 /work/out/news.fo
-foout 仅在 -xml + -xsl 组合下可用,产物是标准 XSL-FO 文件,可直接喂给 -fo 继续渲染,把「样式表错误」与「渲染错误」解耦排查。
2.6 -if / -ifin:两阶段渲染(中间格式)
-if 输出布局完成后的中间格式 XML(intermediate format),-ifin 从中间格式继续渲染最终格式。适合「布局计算贵、多格式输出」的批产场景:
./fop -c /work/conf/fop-cjk5.xconf /work/out/news.fo -if /work/out/news.if.xml
./fop -ifin /work/out/news.if.xml -pdf /work/out/news-ifin.pdf
实测输出:
INFO: Rendered page #1.
-rw-r--r-- 1 root root 5463 Oct 14 14:05 /work/out/news-ifin.pdf
-at(area tree XML)与 -at [mime]/-if [mime] 带可选 mime 时会在输出 XML 中记录目标格式信息,-s 可让 area tree 只保留到块级区域,减小文件。-atin 从 area tree 输入。
2.7 -imagein 与 -catalog
-imagein 把图像文件直接作为输入渲染成目标格式;-catalog 启用 XML catalog 解析器解析 DOCTYPE 外部实体(离线环境处理带 DTD 的 XML 时有用)。
三、输出模式
3.1 支持格式总表(实测)
| 参数 | 格式 | 实测产物大小 | 备注 |
|---|---|---|---|
| 13,606 B(1 页 A4 中文) | 主力格式 | ||
| -ps | PostScript | 11,563 B | 打印 |
| -pcl | PCL | 9,173 B | HP 打印机 |
| -rtf | RTF | 1,571 B | 可编辑文档,仅支持 FO 子集 |
| -txt | 纯文本 | 374 B | 丢排版只留文本流 |
| -png | PNG | 14,312 B(72dpi) | 逐页输出 news1.png/…;-dpi 300 时 98,728 B |
| -tiff | TIFF | 2,010,936 B | 默认无压缩,配置 CCITT T.6 后 12,214 B |
| -afp | AFP | — | 大型机打印,需按配置篇配 AFP 字体 |
| -mif | MIF | — | FrameMaker 交换格式 |
| -at / -if | 中间 XML | 3,689 B / 1,577 B | 两阶段渲染 |
| 直接送打印机 | — | 无头服务器不可用 | |
| -awt | 屏幕预览 | — | 需要 X 环境 |
PNG/TIFF 是多页输出:一页一个文件,自动加序号后缀(news1.png、news2.png…)。
3.2 -out:按 MIME 指定输出
-out mime outfile input will be rendered using the given MIME type
(Tip: "-out list" prints the list of supported MIME types and exits)
理论上 fop foo.fo -out application/pdf out.pdf 与 -pdf 等价。实测 2.11 的 -out list 有 bug,直接抛空指针:
./fop -out list
实测输出:
SEVERE: Exception
java.lang.NullPointerException
at org.apache.fop.cli.CommandLineOptions.parseCustomOutputOption(CommandLineOptions.java:707)
写脚本时避免依赖 -out,直接用 -pdf/-ps 等具名参数。
3.3 PDF 版本与档案规范:-pdfprofile / -pdfa1b
./fop -c /work/conf/fop-cjk5.xconf /work/out/news.fo -pdfa1b /work/out/news-a1b.pdf
实测输出(stderr 含字重替换告警):
WARNING: Font "WQYZenHei,normal,700" not found. Substituting with "WQYZenHei,normal,400".
INFO: Rendered page #1.
pdfinfo /work/out/news-a1b.pdf | grep -iE "pdf version|tagged"
实测输出:
Tagged: no
PDF version: 1.4
-pdfa1b 是 -pdf outfile -pdfprofile PDF/A-1b 的简写;-a 开启无障碍特性(Tagged PDF)。注意 PDF/A 要求全部字体嵌入,混用未注册字体会产生替换告警,存档前应用 pdffonts 核查。
PDF/X 系列别碰:实测 -pdfprofile "PDF/X-3:2003" 失败:
WARNING: Note: PDF/X-3:2003 support is work-in-progress and not fully implemented, yet!
SEVERE: Exception
org.apache.fop.pdf.PDFConformanceException: PDF/X-3:2003 requires that the DestOutputProfile be an Output Device Profile. sRGB does not match that requirement.
需要 CMYK ICC 输出意图配置才能满足 PDF/X,2.11 官方也明示 work-in-progress,生产存档选 PDF/A-1b。
3.4 PDF 加密与权限
8 个权限开关 + 2 个口令:
| 参数 | 含义 |
|---|---|
| -o [password] | owner 口令(权限管理者) |
| -u [password] | user 口令(打开文档) |
| -noprint | 禁打印 |
| -nocopy | 禁复制 |
| -noedit | 禁编辑 |
| -noannotations | 禁批注 |
| -nofillinforms | 禁填表单 |
| -noaccesscontent | 禁提取文本/图形(无障碍读取) |
| -noassembledoc | 禁拆装页面 |
| -noprinthq | 禁高质量打印 |
实测加密渲染:
./fop -c /work/conf/fop-cjk5.xconf /work/out/news.fo \
-o owner123 -u user123 -noprint -nocopy -pdf /work/out/news-enc.pdf
验证(poppler-utils):
pdfinfo /work/out/news-enc.pdf
实测输出:
Command Line Error: Incorrect password
带 user 口令可正常提取文本:
pdftotext -upw user123 /work/out/news-enc.pdf - | head -2
实测输出:
季度报告:FOP 转换管道演示
日期:2026-10-14
四、校验、日志与退出码
4.1 严格校验与 -r
FOP 默认严格校验 XSL-FO 元素顺序。构造一个 layout-master-set 缺失顺序的坏文件实测:
SEVERE: javax.xml.transform.TransformerException: file:/work/src/bad.fo:4:6:
For "fo:root", "fo:layout-master-set" must be declared before "fo:page-sequence"! (See position 4:6)
SEVERE: Exception
org.apache.fop.apps.FOPException: ... org.apache.fop.fo.ValidationException: ...
产物不生成(退出码非 0)。加 -r(relaxed validation)也无法跳过这类元素顺序错误——-r 只放宽部分属性级检查。报错行号格式 file:4:6 是「文件:行:列」,定位很直接。
4.2 日志分级
全部日志走 stderr,java.util.logging 格式:
| 级别 | 实测示例 | 含义 |
|---|---|---|
| INFO | INFO: Rendered page #1. / INFO: This is a TrueType collection file with 3 fonts | 页面进度、字体集合清单 |
| WARNING | WARNING: Glyph "文" (0x6587) not available in font "Times-Roman". / WARNING: Font "WQYZenHei,normal,700" not found. Substituting... | 缺字、triplet 替换、连字符替换 |
| SEVERE | SEVERE: Failed to read font file ... | 致命错误,渲染中止 |
批量脚本里通常 2>/dev/null 丢弃 INFO,或 2>render.log 留档告警。
4.3 退出码
成功为 0;任何 SEVERE(转换异常、字体加载失败、校验失败)为非 0。批量渲染脚本按退出码判断成败即可,无需解析输出。
五、性能与批量渲染
5.1 JVM 启动开销
实测单次 fop 命令的固定开销约 1.1 秒(JVM 启动 + 类加载 + 字体解析),极小文档的总时长基本等于这个常数。
5.2 批量渲染脚本
#!/bin/bash
set -u
CONF=/work/conf/fop-cjk5.xconf
mkdir -p /work/batch/out
for f in /work/batch/*.fo; do
n=$(basename "$f" .fo)
if fop -c "$CONF" "$f" -pdf "/work/batch/out/$n.pdf" 2>/dev/null; then
echo "OK $n"
else
echo "FAIL $n"
fi
done
实测 3 个文件:
OK a
OK b
OK c
real 0m3.443s
平均 1.1 秒/文件,瓶颈在 JVM 启动。文件量大时的两条优化路径:其一,用 2.6 的两阶段渲染把布局计算与多格式输出分离;其二,改用 FOP 的 Java 嵌入 API(examples/embedding/ 有官方示例)在单 JVM 内循环渲染,省掉每文件的启动成本。
5.3 内存控制实测
生成 300 页 A4 纯文本文档(每页一个标题块 + 一段正文)压测:
| 命令 | 耗时 | 峰值 RSS | 产物 |
|---|---|---|---|
| fop big.fo -pdf big.pdf | 1.95s | 235,796 KB | 161,335 B |
| fop -conserve big.fo -pdf ... | 1.90s | 234,624 KB | 161,335 B |
| FOP_OPTS="-Xmx64m" fop ... | 1.85s | 193,068 KB | 161,335 B |
简单文本页的 area tree 很小,64MB 堆即可完成;-conserve(序列化 area tree 到磁盘)在这种负载下收益不明显,其真正目标是含大图片/巨型表格、area tree 放不进内存的文档。日志尾部 INFO: Rendered page #300. 可用于确认完整渲染。
5.4 位图 dpi 控制
fop -c "$CONF" -dpi 300 /work/out/news.fo -png /work/out/news300.png
实测:72 dpi PNG 14,312 字节 → 300 dpi 98,728 字节。-dpi 实际改写 target-resolution,只影响位图与 SVG 光栅化,对 PDF 矢量输出无意义。
六、字体缓存与配置文件管理
| 命令 | 作用 | 实测 |
|---|---|---|
| -cache 路径 | 指定字体缓存位置 | 无家目录 CI 必备 |
| -flush | 清空字体缓存 | 缓存文件 /root/.fop/fop-fonts.cache(2,105 字节) |
| -c cfg.xml | 加载用户配置 | 多个渲染器配置集中在同一文件 |
| -x | 转储解析后的配置 | 排查配置合并结果 |
| -l lang | 用户消息语言 | 2.11 仅支持 en/de 等少数语言,国内环境保持默认 |
七、脚本机制与集成
--execdebug 打印启动脚本最终 exec 的命令行(完整 -classpath 串 + 主类 org.apache.fop.cli.Main),是排查「jar 找不到 / JVM 参数没生效」的官方手段:
FOP_OPTS="-Xmx64m" fop --execdebug -version 2>&1 | grep -o '\-Xmx64m'
实测输出:
-Xmx64m
启动脚本会依次加载 /etc/fop.conf、$HOME/.fop/fop.conf、$HOME/.foprc(--noconfig 抑制),适合按用户注入 JVM 参数。无头服务器上禁用 -awt/-print;cron/systemd timer 环境记得 export LANG=C.UTF-8 并用绝对路径的 -c。
八、常见问题
8.1 fop -out list 抛 NullPointerException
2.11 的已知 CLI bug(CommandLineOptions.parseCustomOutputOption)。改用具名输出参数(3.2)。
8.2 -pdfprofile PDF/X-3:2003 报 sRGB does not match
PDF/X 需要 CMYK ICC 输出意图,2.11 未完整支持,改用 -pdfa1b(3.3)。
8.3 命令行 -param 传中文变问号
POSIX locale 的 argv 解码问题,export LANG=C.UTF-8(安装篇 6.4)。文件内容不受影响,只有命令行参数受影响。
8.4 报 Name does not exist in the TrueType collection
TTC 缺 sub-font 或子字体名错(内部名带 Bold/Regular 后缀),见配置篇 3.3。
8.5 报 'loca' table not found
CFF 轮廓字体(fonts-noto-cjk)不受支持,换 TrueType 轮廓字体(配置篇 3.4)。
8.6 加了 -r 还是校验失败
-r 只放宽属性检查,元素顺序错误(如 layout-master-set 必须在 page-sequence 之前)依旧致命(4.1)。
8.7 stdout 重定向的 PDF 打不开
把 stderr 一起重定向了。日志走 stderr,务必 1>out.pdf 2>log 分开,或确认没有在管道里混入 INFO 行。
8.8 大文件渲染 OOM
FOP_OPTS="-Xmx1g" 加堆 + -conserve;仍不足则用 -if 两阶段拆分(5.3)。
8.9 PNG 只出了一张或多页没序号
PNG/TIFF 一页一文件,自动以 news1.png/news2.png 编号;检查文件名通配时不要把序号写死。
8.10 渲染结果与昨天的字体不一致
字体缓存陈旧,-flush 后重试;CI 环境把 -cache 指到固定路径保证可重复(六)。
九、参考链接
| 资源 | 地址 |
|---|---|
| Running(CLI)官方文档 | https://xmlgraphics.apache.org/fop/2.11/running.html |
| Ant 任务与嵌入 API | https://xmlgraphics.apache.org/fop/2.11/embedding.html |
| Intermediate format 说明 | https://xmlgraphics.apache.org/fop/2.11/intermediate.html |
| PDF 加密/规范说明 | https://xmlgraphics.apache.org/fop/2.11/pdfencryption.html |
| 官方 CLI 示例 | 发行包内 examples/embedding/ |