Apache FOP
FOP (Formatting Objects Processor) is from the apache group. It is said to be the print formatter driven by XSL formatting objects (XSL-FO). FOP can be downloaded from http://xmlgraphics.apache.org/fop/
Its ability to convert XSL files (*.fo) to PDF certainly makes it worth mention. Basically FOP is great for template based PDF generation. Simple programs can fetch data from any data source and populate such a template, and generate PDF’s on the fly !
XSL-FO (Extensible Stylesheet Language Formatting Objects)
XSL-FO is a language for formatting XML data for output to screen, paper or other media
Required Jars
Steps to generate PDF
Step 1: Create the template(.xsl) for formatting the output in resource folder
Step 2: Convert the java object to XML
Step 3: call the transformer code to convert the xml source to pdf using the xsl template.
Example Code:
template.xsl
<?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" xmlns:barcode="org.krysalis.barcode4j.xalan.BarcodeExt" xmlns:common="http://exslt.org/common" xmlns:xalan="http://xml.apache.org" exclude-result-prefixes="barcode common xalan"> <xsl:template match=" EmployeeData"> <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> <fo:layout-master-set> <fo:simple-page-master master-name="simple" page-height="20cm" page-width="10.5cm" margin-left="0.2cm" margin-right="0.2cm"> <fo:region-body margin-top="0.5cm" /> </fo:simple-page-master> </fo:layout-master-set> <fo:page-sequence master-reference="simple"> <fo:flow flow-name="xsl-region-body"> <fo:block font-family="Arial" font-size="7pt" font-weight="normal"> <fo:table> <fo:table-column column-number="1" column-width="3cm" /> <fo:table-column column-number="2" column-width="2cm" /> <fo:table-column column-number="3" column-width="5cm" /> <fo:table-body height="10cm"> <xsl:for-each select="./employeeList/employee"> <fo:table-row border="solid 0.1mm black"> <fo:table-cell text-align="left"> <fo:block> <xsl:value-of select="name" /> </fo:block> </fo:table-cell> <fo:table-cell text-align="center"> <fo:block> <xsl:value-of select="employeeId" /> </fo:block> </fo:table-cell> <fo:table-cell text-align="left"> <fo:block> <xsl:value-of select="address" /> </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>
EmployeeData.java
import java.util.List; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; /** * */ /** * @author Debasmita.Sahoo * */ @XmlRootElement(name="EmployeeData") public class EmployeeData { public EmployeeData () { } private List employeeList; @XmlElementWrapper(name = "employeeList") @XmlElement(name = "employee") public List getEmployeeList() { return employeeList; } public void setEemployeeList (List employeeList) { this.employeeList = employeeList; } }
Employee.java
/** * @author Debasmita.Sahoo * */ public class Employee { private String name; private String employeeId; private String address; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmployeeId() { return employeeId; } public void setEmployeeId(String employeeId) { this.employeeId = employeeId; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } } import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.URL; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.transform.Result; import javax.xml.transform.Source; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.TransformerFactoryConfigurationError; import javax.xml.transform.dom.DOMResult; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.sax.SAXResult; 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; public class PDFHandler { public static final String EXTENSION = ".pdf"; public String PRESCRIPTION_URL = "template.xsl"; public String createPDFFile(ByteArrayOutputStream xmlSource, String templateFilePath) throws IOException { File file = File.createTempFile("" + System.currentTimeMillis(), EXTENSION); URL url = new File(templateFilePath + PRESCRIPTION_URL).toURI().toURL(); // creation of transform source StreamSource transformSource = new StreamSource(url.openStream()); // create an instance of fop factory FopFactory fopFactory = FopFactory.newInstance(); // a user agent is needed for transformation FOUserAgent foUserAgent = fopFactory.newFOUserAgent(); // to store output ByteArrayOutputStream pdfoutStream = new ByteArrayOutputStream(); StreamSource source = new StreamSource(new ByteArrayInputStream(xmlSource.toByteArray())); Transformer xslfoTransformer; try { TransformerFactory transfact = TransformerFactory.newInstance(); xslfoTransformer = transfact.newTransformer(transformSource); // Construct fop with desired output format Fop fop; try { fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, pdfoutStream); // Resulting SAX events (the generated FO) // must be piped through to FOP Result res = new SAXResult(fop.getDefaultHandler()); // Start XSLT transformation and FOP processing try { // everything will happen here.. xslfoTransformer.transform(source, res); // if you want to save PDF file use the following code OutputStream out = new java.io.FileOutputStream(file); out = new java.io.BufferedOutputStream(out); FileOutputStream str = new FileOutputStream(file); str.write(pdfoutStream.toByteArray()); str.close(); out.close(); } catch (TransformerException e) { e.printStackTrace(); } } catch (FOPException e) { e.printStackTrace(); } } catch (TransformerConfigurationException e) { e.printStackTrace(); } catch (TransformerFactoryConfigurationError e) { e.printStackTrace(); } return file.getPath(); } public ByteArrayOutputStream getXMLSource(EmployeeData data) throws Exception { JAXBContext context; ByteArrayOutputStream outStream = new ByteArrayOutputStream(); try { context = JAXBContext.newInstance(EmployeeData.class); Marshaller m = context.createMarshaller(); m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); m.marshal(data, outStream); } catch (JAXBException e) { e.printStackTrace(); } return outStream; } }
Call the PDF handler Code
TestPDF.java
import java.io.ByteArrayOutputStream; import java.util.ArrayList; /** * @author Debasmita.Sahoo * */ public class TestPDF { public static void main(String args[]){ System.out.println("Hi Testing"); ArrayList employeeList = new ArrayList(); String templateFilePath ="D:/Projects/Sample/pdftest/src/"; Employee e1= new Employee(); e1.setName("Debasmita1 Sahoo"); e1.setEmployeeId("10001"); e1.setAddress("Pune"); employeeList.add(e1); Employee e2= new Employee(); e2.setName("Debasmita2 Sahoo"); e2.setEmployeeId("10002"); e2.setAddress("Test"); employeeList.add(e2); Employee e3= new Employee(); e3.setName("Debasmita3 Sahoo"); e3.setEmployeeId("10003"); e3.setAddress("Mumbai"); employeeList.add(e3); EmployeeData data = new EmployeeData(); data.setEemployeeList(employeeList); PDFHandler handler = new PDFHandler(); try { ByteArrayOutputStream streamSource = handler.getXMLSource(data); handler.createPDFFile(streamSource,templateFilePath); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }