使用XSLFO和FOP在JSP应用中生成PDF文档

在开发基于JSP的Web应用时,经常需要根据用户的操作生成PDF文档。尽管有许多教程介绍了如何导出Excel或Word文档,但本文将介绍如何使用XSL Formatting Objects (XSLFO) 和 Apache Formatting Objects Processor (FOP) 来创建PDF文档。

XSLFO和FOP简介

XSLFO是一种用于格式化XML数据的标记语言。它允许开发者定义文档的布局和样式。而Apache FOP是一个Java应用程序,可以将格式化对象树渲染成指定的输出格式,如PDF。

工作原理

首先有一个包含数据的XML文件,然后使用XSLT将这个XML文件转换成包含格式化对象的XML。这个结果XML被反序列化为Java对象,FOP使用这些Java对象创建PDF文件。

示例:Hello World XSLFO

以下是一个简单的XML示例,其中包含了一个人的名字以及他的朋友们的联系信息。

<?xml version="1.0" encoding="iso-8859-1"?> <root> <name>shyam</name> <friend> <name>Abc</name> <phNo>90909090909</phNo> </friend> <friend> <name>Xyz</name> <phNo>32323232323</phNo> </friend> </root>

将上述XML保存为Hello.xml。

接下来是一个XSLFO样式表的示例,它首先从上面的XML中获取名字,然后渲染一个包含朋友详细信息的表格。

<?xml version="1.0" encoding="iso-8859-1"?> <xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" exclude-result-prefixes="fo"> <xsl:template match="root"> <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> <fo:layout-master-set> <fo:simple-page-master master-name="my-page"> <fo:region-body margin="1in"/> </fo:simple-page-master> </fo:layout-master-set> <fo:page-sequence master-reference="my-page"> <fo:flow flow-name="xsl-region-body"> <fo:block> Hello, <xsl:value-of select="name"/>! </fo:block> <fo:block> <fo:table> <fo:table-body> <fo:table-row> <fo:table-cell border="solid 1px black" text-align="center" font-weight="bold"> <fo:block>No.</fo:block> </fo:table-cell> <fo:table-cell border="solid 1px black" text-align="center" font-weight="bold"> <fo:block>Name</fo:block> </fo:table-cell> <fo:table-cell border="solid 1px black" text-align="center" font-weight="bold"> <fo:block>Phone Number</fo:block> </fo:table-cell> </fo:table-row> <xsl:for-each select="./friend"> <fo:table-row> <fo:table-cell border="solid 1px black" text-align="center"> <fo:block> <xsl:value-of select="position()"/> </fo:block> </fo:table-cell> <fo:table-cell border="solid 1px black" text-align="center"> <fo:block> <xsl:value-of select="name"/> </fo:block> </fo:table-cell> <fo:table-cell border="solid 1px black" text-align="center"> <fo:block> <xsl:value-of select="phNo"/> </fo:block> </fo:table-cell> </fo:table-row> </xsl:for-each> </fo:table-body> </fo:table> </fo:block> </fo:flow> </fo:page-sequence> </fo:root> </xsl:template> </xsl:stylesheet>

将上述样式表保存为HelloWorld.xsl。

Java代码实现

以下是生成PDF的Java代码示例。

import java.io.File; import javax.xml.transform.stream.StreamSource; import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.Fop; import org.apache.fop.apps.FopFactory; import org.apache.fop.apps.MimeConstants; import java.io.ByteArrayOutputStream; import javax.xml.transform.Transformer; import javax.xml.transform.Result; public class PDFGenerator { public static void main(String[] args) { try { File xsltfile = new File("HelloWorld.xsl"); StreamSource source = new StreamSource(new File("Hello.xml")); StreamSource transformSource = new StreamSource(xsltfile); FopFactory fopFactory = FopFactory.newInstance(); FOUserAgent foUserAgent = fopFactory.newFOUserAgent(); ByteArrayOutputStream outStream = new ByteArrayOutputStream(); Transformer xslfoTransformer = getTransformer(transformSource); Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, outStream); Result res = new SAXResult(fop.getDefaultHandler()); xslfoTransformer.transform(source, res); byte[] pdfBytes = outStream.toByteArray(); // 此处省略了将PDF字节写入输出流的代码 } catch (Exception e) { e.printStackTrace(); } } private static Transformer getTransformer(StreamSource streamSource) throws TransformerConfigurationException { net.sf.saxon.TransformerFactoryImpl impl = new net.sf.saxon.TransformerFactoryImpl(); return impl.newTransformer(streamSource); } }

在上述代码中,首先读取XSLT样式表和XML数据文件,然后使用TransformerFactory创建一个Transformer对象。接着,使用FOPFactory创建一个Fop对象,该对象负责将格式化对象树渲染成PDF。最后,通过Transformer的transform方法将XML数据和XSLT样式表转换为PDF。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485