在Java项目里实现XML文件到PDF的转换,Flying Saucer是常用的解决方案,它依赖iText渲染引擎,能够将符合XHTML标准的XML内容输出为格式规范的PDF文档,适配多数报表生成、数据导出的业务场景。
环境依赖准备
使用Flying Saucer需要引入两个核心依赖,分别是Flying Saucer的核心包和iText的适配包,Maven项目可以在pom.xml中添加如下依赖:
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf</artifactId>
<version>9.1.22</version>
</dependency>
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf-itext5</artifactId>
<version>9.1.22</version>
</dependency>
XML转PDF的核心逻辑
Flying Saucer本身不直接处理任意格式的XML,需要先将原始XML转换为XHTML格式,因为Flying Saucer的渲染规则是基于XHTML标准设计的。转换过程通常分为两步:
- 第一步:使用XSLT将原始XML转换为符合XHTML规范的中间文件
- 第二步:使用Flying Saucer读取XHTML内容,渲染生成PDF文件
XML转XHTML的实现
我们可以通过Java内置的javax.xml.transform包完成XSLT转换,首先需要准备一个XSLT样式文件,定义XML到XHTML的映射规则,示例如下:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" encoding="UTF-8"/>
<xsl:template match="/">
<html>
<head>
<title>XML转换结果</title>
<style>
body { font-family: SimSun; }
.title { font-size: 20px; font-weight: bold; }
</style>
</head>
<body>
<div class="title">
<xsl:value-of select="root/title"/>
</div>
<div>
内容:<xsl:value-of select="root/content"/>
</div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
对应的原始XML文件示例:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<title>测试文档</title>
<content>这是一份XML转换PDF的测试内容</content>
</root>
使用Java代码实现XSLT转换的逻辑如下:
import javax.xml.transform.*;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import java.io.File;
import java.io.FileOutputStream;
public class XmlToXhtmlUtil {
public static void transformXmlToXhtml(String xmlPath, String xsltPath, String outputXhtmlPath) throws Exception {
// 创建转换器工厂
TransformerFactory factory = TransformerFactory.newInstance();
// 加载XSLT样式文件
Source xsltSource = new StreamSource(new File(xsltPath));
Transformer transformer = factory.newTransformer(xsltSource);
// 加载原始XML文件
Source xmlSource = new StreamSource(new File(xmlPath));
// 输出转换后的XHTML文件
Result xhtmlResult = new StreamResult(new FileOutputStream(outputXhtmlPath));
// 执行转换
transformer.transform(xmlSource, xhtmlResult);
}
}
使用Flying Saucer生成PDF
得到XHTML文件后,就可以调用Flying Saucer的API生成PDF,核心代码如下:
import org.xhtmlrenderer.pdf.ITextRenderer;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class PdfGenerator {
public static void generatePdfFromXhtml(String xhtmlPath, String outputPdfPath) throws Exception {
// 创建iText渲染器
ITextRenderer renderer = new ITextRenderer();
// 设置XHTML文件路径,注意如果是本地文件需要加file协议前缀
String url = new File(xhtmlPath).toURI().toURL().toString();
renderer.setDocument(url);
// 执行布局渲染
renderer.layout();
// 输出PDF文件
try (OutputStream os = new FileOutputStream(outputPdfPath)) {
renderer.createPDF(os);
}
}
}
完整调用示例
将两个步骤组合起来,完整的转换流程代码如下:
public class XmlToPdfDemo {
public static void main(String[] args) {
String xmlPath = "D:/test.xml";
String xsltPath = "D:/transform.xslt";
String xhtmlPath = "D:/temp.xhtml";
String pdfPath = "D:/output.pdf";
try {
// 第一步:XML转XHTML
XmlToXhtmlUtil.transformXmlToXhtml(xmlPath, xsltPath, xhtmlPath);
// 第二步:XHTML转PDF
PdfGenerator.generatePdfFromXhtml(xhtmlPath, pdfPath);
System.out.println("转换完成,PDF文件路径:" + pdfPath);
} catch (Exception e) {
e.printStackTrace();
}
}
}
常见问题与解决方法
中文显示乱码
Flying Saucer默认不支持中文字体,需要在XHTML的样式中指定中文字体,同时将字体文件加载到渲染器中,修改生成PDF的代码:
import org.xhtmlrenderer.pdf.ITextRenderer;
import org.xhtmlrenderer.resource.FSEntityResolver;
import com.lowagie.text.pdf.BaseFont;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class PdfGenerator {
public static void generatePdfFromXhtml(String xhtmlPath, String outputPdfPath) throws Exception {
ITextRenderer renderer = new ITextRenderer();
// 加载中文字体,这里以宋体为例,字体文件路径根据实际位置调整
String fontPath = "D:/simsun.ttc";
renderer.getFontResolver().addFont(fontPath, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
String url = new File(xhtmlPath).toURI().toURL().toString();
renderer.setDocument(url);
renderer.layout();
try (OutputStream os = new FileOutputStream(outputPdfPath)) {
renderer.createPDF(os);
}
}
}
XHTML格式校验失败
Flying Saucer对XHTML的格式要求比较严格,标签必须闭合、属性值需要加引号,如果转换时报格式错误,可以先使用XML校验工具检查XHTML文件是否符合规范,也可以调整XSLT样式文件,确保输出的XHTML标签正确。
注意事项
- 原始XML如果结构复杂,需要对应调整XSLT样式文件,确保转换后的XHTML包含所有需要展示的内容
- 生成PDF时如果需要添加页眉页脚、页码,可以在XHTML的样式中使用CSS的@page规则定义
- 依赖版本尽量保持一致,避免不同版本之间的兼容性问题导致转换失败
XML_to_PDFJavaFlying_SaucerXHTML修改时间:2026-07-05 21:00:37