Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you create a PDF from XML in Java?

At the moment, I'm creating an XML file in Java and displaying it in a JSP page by transforming it with XSL/XSLT. Now I need to take that XML file and display the same information in a PDF. Is there a way I can do this by using some kind of XSL file?

I've seen the iText Java-PDF library, but I can't find any way to use it with XML and a stylesheet.

Any assistance would be much appreciated. Thanks in advance!

like image 542
Philip Morton Avatar asked Oct 17 '08 15:10

Philip Morton


People also ask

Can you make a PDF an XML file?

Four steps for converting your PDF to XML.Use the Select tool to mark the content you want to save. Right-click the highlighted text. Choose Export Selection As. Select XML, and slick Save.

How do I create an XML PDF using Apache FOP?

To produce a PDF file from a XML file, first step is that we need an XSLT stylesheet that converts the XML to XSL-FO. Created XSL-FO file is also an XML file which contains formatted objects. The second step will be done by FOP when it reads the generated XSL-FO document and formats it to a PDF document.


1 Answers

A - Explanation

You should use Apache FOP framework to generate pdf output. Simply you provide data in xml format and render the page with an xsl-fo file and specify the parameters like margin, page layout in this xsl-fo file.

I'll provide a simple demo, I use maven build tool to gather the needed jar files. Please notify that at the end of the page, there is an svg graphics embedded in pdf. I also want to demonstrate that you can embed svg graphics inside pdf.

B - Sample XML input data

<?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="application/xml"?> <users-data>     <header-section>         <data-type id="019">User Bill Data</data-type>         <process-date>Thursday December 9 2016 00:04:29</process-date>     </header-section>     <user-bill-data>         <full-name>John Doe</full-name>         <postal-code>34239</postal-code>         <national-id>123AD329248</national-id>         <price>17.84</price>     </user-bill-data>     <user-bill-data>         <full-name>Michael Doe</full-name>         <postal-code>54823</postal-code>         <national-id>942KFDSCW322</national-id>         <price>34.50</price>     </user-bill-data>     <user-bill-data>         <full-name>Jane Brown</full-name>         <postal-code>66742</postal-code>         <national-id>ABDD324KKD8</national-id>         <price>69.36</price>     </user-bill-data> </users-data> 

C - The XSL-FO Template

<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" version="1.0">     <xsl:output encoding="UTF-8" indent="yes" method="xml" standalone="no" omit-xml-declaration="no"/>     <xsl:template match="users-data">         <fo:root language="EN">             <fo:layout-master-set>                 <fo:simple-page-master master-name="A4-portrail" page-height="297mm" page-width="210mm" margin-top="5mm" margin-bottom="5mm" margin-left="5mm" margin-right="5mm">                     <fo:region-body margin-top="25mm" margin-bottom="20mm"/>                     <fo:region-before region-name="xsl-region-before" extent="25mm" display-align="before" precedence="true"/>                 </fo:simple-page-master>             </fo:layout-master-set>             <fo:page-sequence master-reference="A4-portrail">                 <fo:static-content flow-name="xsl-region-before">                     <fo:table table-layout="fixed" width="100%" font-size="10pt" border-color="black" border-width="0.4mm" border-style="solid">                         <fo:table-column column-width="proportional-column-width(20)"/>                         <fo:table-column column-width="proportional-column-width(45)"/>                         <fo:table-column column-width="proportional-column-width(20)"/>                         <fo:table-body>                             <fo:table-row>                                 <fo:table-cell text-align="left" display-align="center" padding-left="2mm">                                     <fo:block>                                         Bill Id:<xsl:value-of select="header-section/data-type/@id"/>                                         , Date: <xsl:value-of select="header-section/process-date"/>                                     </fo:block>                                 </fo:table-cell>                                 <fo:table-cell text-align="center" display-align="center">                                     <fo:block font-size="150%">                                         <fo:basic-link external-destination="http://www.example.com">XXX COMPANY</fo:basic-link>                                     </fo:block>                                     <fo:block space-before="3mm"/>                                 </fo:table-cell>                                 <fo:table-cell text-align="right" display-align="center" padding-right="2mm">                                     <fo:block>                                         <xsl:value-of select="data-type"/>                                     </fo:block>                                     <fo:block display-align="before" space-before="6mm">Page <fo:page-number/> of <fo:page-number-citation ref-id="end-of-document"/>                                     </fo:block>                                 </fo:table-cell>                             </fo:table-row>                         </fo:table-body>                     </fo:table>                 </fo:static-content>                 <fo:flow flow-name="xsl-region-body" border-collapse="collapse" reference-orientation="0">                     <fo:block>MONTHLY BILL REPORT</fo:block>                     <fo:table table-layout="fixed" width="100%" font-size="10pt" border-color="black" border-width="0.35mm" border-style="solid" text-align="center" display-align="center" space-after="5mm">                         <fo:table-column column-width="proportional-column-width(20)"/>                         <fo:table-column column-width="proportional-column-width(30)"/>                         <fo:table-column column-width="proportional-column-width(25)"/>                         <fo:table-column column-width="proportional-column-width(50)"/>                         <fo:table-body font-size="95%">                             <fo:table-row height="8mm">                                 <fo:table-cell>                                     <fo:block>Full Name</fo:block>                                 </fo:table-cell>                                 <fo:table-cell>                                     <fo:block>Postal Code</fo:block>                                 </fo:table-cell>                                 <fo:table-cell>                                     <fo:block>National ID</fo:block>                                 </fo:table-cell>                                 <fo:table-cell>                                     <fo:block>Payment</fo:block>                                 </fo:table-cell>                             </fo:table-row>                             <xsl:for-each select="user-bill-data">                                 <fo:table-row>                                     <fo:table-cell>                                         <fo:block>                                             <xsl:value-of select="full-name"/>                                         </fo:block>                                     </fo:table-cell>                                     <fo:table-cell>                                         <fo:block>                                             <xsl:value-of select="postal-code"/>                                         </fo:block>                                     </fo:table-cell>                                     <fo:table-cell>                                         <fo:block>                                             <xsl:value-of select="national-id"/>                                         </fo:block>                                     </fo:table-cell>                                     <fo:table-cell>                                         <fo:block>                                             <xsl:value-of select="price"/>                                         </fo:block>                                     </fo:table-cell>                                 </fo:table-row>                             </xsl:for-each>                         </fo:table-body>                     </fo:table>                     <fo:block id="end-of-document">                         <fo:instream-foreign-object>                             <svg width="200mm" height="150mm" version="1.1" xmlns="http://www.w3.org/2000/svg">                                 <path d="M153 334 C153 334 151 334 151 334 C151 339 153 344 156 344 C164 344 171 339 171 334 C171 322 164 314 156 314 C142 314 131 322 131 334 C131 350 142 364 156 364 C175 364 191 350 191 334 C191 311 175 294 156 294 C131 294 111 311 111 334 C111 361 131 384 156 384 C186 384 211 361 211 334 C211 300 186 274 156 274" style="fill:yellow;stroke:red;stroke-width:2"/>                             </svg>                         </fo:instream-foreign-object>                     </fo:block>                 </fo:flow>             </fo:page-sequence>         </fo:root>     </xsl:template> </xsl:stylesheet> 

D - Project Directory Structure

enter image description here

E - Pom file

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">     <modelVersion>4.0.0</modelVersion>     <groupId>com.levent.fopdemo</groupId>     <artifactId>apache-fop-demo</artifactId>     <packaging>jar</packaging>     <version>1.0-SNAPSHOT</version>     <name>apache-fop-demo</name>     <url>http://maven.apache.org</url>      <properties>         <fop.version>2.1</fop.version>     </properties>      <dependencies>               <!-- https://mvnrepository.com/artifact/org.apache.xmlgraphics/fop -->         <dependency>             <groupId>org.apache.xmlgraphics</groupId>             <artifactId>fop</artifactId>             <version>${fop.version}</version>         </dependency>     </dependencies>      <build>         <finalName>Apache Fop Demo</finalName>          <plugins>             <plugin>                 <groupId>org.apache.maven.plugins</groupId>                 <artifactId>maven-compiler-plugin</artifactId>                 <version>3.5.1</version>                 <configuration>                     <source>1.8</source>                     <target>1.8</target>                 </configuration>             </plugin>         </plugins>     </build> </project> 

F - Demo Code: PdfGenerationDemo.java

package com.levent.fopdemo;  import java.io.File; import java.io.IOException; import java.io.OutputStream;  import javax.xml.transform.Result; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; 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 PdfGenerationDemo  {     public static final String RESOURCES_DIR;     public static final String OUTPUT_DIR;      static {         RESOURCES_DIR = "src//main//resources//";         OUTPUT_DIR = "src//main//resources//output//";     }      public static void main( String[] args )     {         try {             convertToPDF();         } catch (FOPException | IOException | TransformerException e) {             e.printStackTrace();         }     }      public static void convertToPDF() throws IOException, FOPException, TransformerException {         // the XSL FO file         File xsltFile = new File(RESOURCES_DIR + "//template.xsl");         // the XML file which provides the input         StreamSource xmlSource = new StreamSource(new File(RESOURCES_DIR + "//data.xml"));         // create an instance of fop factory         FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI());         // a user agent is needed for transformation         FOUserAgent foUserAgent = fopFactory.newFOUserAgent();         // Setup output         OutputStream out;         out = new java.io.FileOutputStream(OUTPUT_DIR + "//output.pdf");          try {             // Construct fop with desired output format             Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out);              // Setup XSLT             TransformerFactory factory = TransformerFactory.newInstance();             Transformer transformer = factory.newTransformer(new StreamSource(xsltFile));              // Resulting SAX events (the generated FO) must be piped through to             // FOP             Result res = new SAXResult(fop.getDefaultHandler());              // Start XSLT transformation and FOP processing             // That's where the XML is first transformed to XSL-FO and then             // PDF is created             transformer.transform(xmlSource, res);         } finally {             out.close();         }     } } 

G - Sample Output: output.pdf

enter image description here

like image 133
Levent Divilioglu Avatar answered Sep 21 '22 13:09

Levent Divilioglu