使用Apache FOP将JSON转PDF时遇文档为空异常求助
我来帮你一步步拆解这个问题,org.apache.fop.fo.ValidationException: Document is empty这个错误本质是FOP没有拿到有效的XSL-FO文档内容,大概率出在JSON转XML或者**XML转XSL-FO(XSLT转换)**这两个环节,咱们从几个关键方向排查:
第一步:验证JSON转XML的输出是否有效
Apache FOP本身不处理JSON,你肯定是先把JSON转成了XML再交给XSLT处理对吧?先确认这一步的输出:
在代码里添加日志,把转换后的XML内容打出来,比如:// 假设你有一个convertJsonToXml方法处理JSON转XML String convertedXml = convertJsonToXml(obj); logger.info("JSON转换后的XML内容:\n" + convertedXml);检查这个XML是不是空的,有没有符合预期的节点结构——如果XML本身就为空或者结构不对,后续XSLT根本没法生成有效FO。
第二步:单独测试XSLT样式表的输出
这是最常见的问题根源:XSLT没有匹配到XML的节点,导致输出了空的XSL-FO内容。
你可以把第一步得到的XML内容,用XSLT工具(本地的XSLT处理器,比如Saxon,或者离线测试工具)单独跑一遍你的样式表,看看输出的FO内容:- 有没有
<fo:root>这个根节点?这是FOP要求的必填结构 - 输出内容是不是完全为空,或者只有空白字符?如果是,那说明你的XSLT模板没有正确匹配XML的节点(比如模板的
match路径写错了,或者XML的命名空间和XSLT里的不一致)
- 有没有
第三步:检查代码中XSLT转换的细节
看看你代码里的XSLT转换逻辑有没有问题:- 是不是
Transformer的配置有问题,比如没有正确加载XSLT文件? - 转换后的FO内容是不是被意外清空了?比如用
StreamResult的时候,有没有正确获取输出内容,会不会出现流提前关闭的情况?
可以在转换后直接检查FO内容是否为空,比如:
StringWriter foWriter = new StringWriter(); transformer.transform(xmlSource, new StreamResult(foWriter)); String foContent = foWriter.toString(); if (foContent.trim().isEmpty()) { throw new RuntimeException("XSLT转换后生成了空的FO内容,请检查样式表"); }- 是不是
第四步:排查是否有隐藏异常被忽略
你的方法声明里异常有截断(TransformerFactoryConfigurationEr...),会不会在转换过程中已经出现了异常,但被吞掉或者没有暴露出来?
建议在代码里添加完整的异常捕获,打印详细的栈信息,比如:try { // 你的JSON转XML、XSLT转FO、FOP生成PDF的逻辑 } catch (Exception e) { logger.error("转换过程出现异常", e); throw e; }有时候一些隐性的异常(比如XML解析错误、XSLT语法错误)会导致转换中断,最终只留下FOP的空文档错误。
核心思路就是:把整个转换流程拆分成JSON→XML、XML→XSL-FO、XSL-FO→PDF三个独立步骤,逐个验证每个步骤的输出是否符合预期,就能快速定位到问题所在。
内容的提问来源于stack exchange,提问作者Karthikeyan

