xml转pdf必须先用xslt转换为合法xhtml,再由flying saucer渲染;需显式注册中文字体、设置utf-8编码、正确传入baseurl,并避免触发布局bug的css。

XML转PDF必须先转成XHTML,Flying Saucer不直接解析任意XML
Flying Saucer(即 core-renderer)本质是 XHTML/CSS 渲染引擎,它根本不认识纯 XML 的结构或语义。如果你直接把一个带自定义标签的 book.xml 丢给它,会立刻报 org.xhtmlrenderer.util.XRRuntimeException: Failed to load document 或更模糊的解析失败——因为它默认按 XHTML DTD 去校验,而你的 XML 没有 根、没有 、甚至可能连命名空间都没声明。
所以真实路径只有一条:XML →(XSLT 转换)→ XHTML →(Flying Saucer 渲染)→ PDF。
- 必须写 XSLT(哪怕只有 5 行),把原始 XML 元素映射为合法 XHTML 标签,比如
<title></title>→<h1></h1>,<para></para>→<p></p> - XSLT 文件里要显式声明
xmlns="http://www.w3.org/1999/xhtml",否则 Flying Saucer 仍会拒绝渲染 - 别试图用 DOM 手动拼 HTML 字符串再喂给
ITextRenderer—— 编码、实体转义、DOCTYPE 声明漏一处就白忙
用 ITextRenderer 渲染前,必须设置字体和编码,否则中文全变方块
Flying Saucer 默认不嵌入中文字体,也不识别 XML 声明里的 encoding="UTF-8"。即使 XSLT 输出了正确的 UTF-8 XHTML,PDF 里中文照样是空心方框或问号。
- 必须调用
renderer.getFontResolver().addFont("simhei.ttf", "SimHei", true)显式注册中文字体文件(注意路径要是绝对路径或 classpath 资源) - 必须在 XHTML 的
里加<meta charset="UTF-8">,且确保 XSLT 输出时该 meta 标签真实存在 - 如果用
ITextRenderer.setDocumentFromString(),传入的字符串必须是 UTF-8 编码的 byte[],不能是 String 直接 toString() 后塞进去
ITextRenderer 的 setDocument() 和 setDocumentFromString() 行为差异很大
这两个方法看着像只是输入方式不同,但底层处理逻辑完全不同:前者走 SAX 解析器,后者走 DOM 构建。对同一份 XHTML,结果可能一个成功一个崩溃。
立即学习“Java免费学习笔记(深入)”;
-
setDocument(new File("output.xhtml")):要求文件物理存在,且路径可读;若 XHTML 里有相对 CSS 路径(如href="style.css"),Flying Saucer 会从该 XHTML 所在目录去加载 -
setDocumentFromString(htmlContent, baseUrl):baseUrl参数不是可选的!必须传一个以file:///或classpath:/开头的有效 base URL,否则 CSS、图片路径全失效 - 如果 XHTML 里用了
<base href="...">,它会被忽略——Flying Saucer 只认构造时传入的baseUrl
生成 PDF 时内存溢出或空白页,大概率是 CSS 触发了 Flying Saucer 的布局 bug
某些看似无害的 CSS 会让 Flying Saucer 在分页计算阶段死循环或 OOM,尤其涉及 position: absolute、display: table-cell 或未闭合的 @media print 块。
- 先用浏览器打开生成的 XHTML,确认它能正常显示且没报 CSS 解析错误
- 临时删掉所有自定义 CSS,只留最简样式(如
body { font-size: 12px; }),看 PDF 是否能出来;能出来就逐段加回 CSS 定位问题 - 避免在 XHTML 中使用
<style>@page { size: A4; margin: 1cm; }</style>—— Flying Saucer 对@page支持极弱,应改用 Java 侧调用renderer.setPageSize(PageSize.A4)
真正卡住的地方往往不是 XML 结构,而是 XSLT 输出的 XHTML 是否“足够像浏览器能吃的 HTML”,以及 CSS 是否触发了 Flying Saucer 那些年久失修的渲染分支。










