What is Apache FOP

Apache™ FOP (Formatting Objects Processor) is a print formatter driven by XSL formatting objects (XSL-FO) and an output independent formatter. It is a Java application that reads a formatting object (FO) tree and renders the resulting pages to a specified output.
FOP uses the standard XSL-FO file format as input, lays the content out into pages, then renders it to the requested output.
Read more about it here – https://xmlgraphics.apache.org/fop/

Steps for creating a PDF from XML

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.

How to get Apache FOP

Get the FOP download from here.
https://xmlgraphics.apache.org/fop/download.html

I have used fop-2.0 for this example code.
Needed jars (found in the lib and build directory in the fop download) –

  • Commons-io
  • Commons-logging
  • Xml-apis
  • Xmlgraphics-commons
  • Fop
  • Batik-all
  • Avalon-framework

Example code

XML I used for creating PDF

          <?          xml version          =          "1.0"          ?>          <employees>          <companyname>          ABC Inc.          </companyname>          <employee>          <id>          101          </id>          <name>          Ram          </name>          <designation>          Manager          </designation>          </employee>          <employee>          <id>          102          </id>          <name>          Prabhu          </name>          <designation>          Executive          </designation>          </employee>          <employee>          <id>          103          </id>          <name>          John          </name>          <designation>          Executive          </designation>          </employee>          </employees>        

XSLUsed

          <?          xml version          =          "1.0"                      encoding          =          "UTF-8"          ?>          <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          =          "employees"          >          <fo:root          xmlns:fo          =          "http://www.w3.org/1999/XSL/Format"          >          <fo:layout-master-set>          <fo:simple-page-master          master-name          =          "simpleA4"          page-height          =          "29.7cm"          page-width          =          "21cm"          margin-top          =          "2cm"          margin-bottom          =          "2cm"          margin-left          =          "2cm"          margin-right          =          "2cm"          >          <fo:region-body/>          </fo:simple-page-master>          </fo:layout-master-set>          <fo:page-sequence          master-reference          =          "simpleA4"          >          <fo:flow          flow-name          =          "xsl-region-body"          >          <fo:block          font-size          =          "16pt"          font-weight          =          "bold"          space-after          =          "5mm"          >          Company Name:                    <xsl:value-of          select          =          "companyname"          />          </fo:block>          <fo:block          font-size          =          "10pt"          >          <fo:table          table-layout          =          "fixed"          width          =          "100%"          border-collapse          =          "separate"          >          <fo:table-column          column-width          =          "4cm"          />          <fo:table-column          column-width          =          "4cm"          />          <fo:table-column          column-width          =          "5cm"          />          <fo:table-body>          <xsl:apply-templates          select          =          "employee"          />          </fo:table-body>          </fo:table>          </fo:block>          </fo:flow>          </fo:page-sequence>          </fo:root>          </xsl:template>          <xsl:template          match          =          "employee"          >          <fo:table-row>          <xsl:if          test          =          "designation = 'Manager'"          >          <xsl:attribute          name          =          "font-weight"          >          bold          </xsl:attribute>          </xsl:if>          <fo:table-cell>          <fo:block>          <xsl:value-of          select          =          "id"          />          </fo:block>          </fo:table-cell>          <fo:table-cell>          <fo:block>          <xsl:value-of          select          =          "name"          />          </fo:block>          </fo:table-cell>          <fo:table-cell>          <fo:block>          <xsl:value-of          select          =          "designation"          />          </fo:block>          </fo:table-cell>          </fo:table-row>          </xsl:template>          </xsl:stylesheet>        

If you see the XSL, first I am looking for the employees element to get the company Name and also there some formatting is done like how many columns are needed and what should be the width. Then I am looking for the employee element and printing the values, also some logic is there to print the field values in bold if the designation is manager.

Copying the output of PDF I got, that will make it easy to understand the XSL.

PDF from XML using Apache FOP

Java code

          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          .          StreamResult          ;          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          FOPPdfDemo          {          public          static          void                      main          (          String          []                      args          )          {          FOPPdfDemo                      fOPPdfDemo                    =          new          FOPPdfDemo          ();          try          {                      fOPPdfDemo          .          convertToPDF          ();          }          catch          (          FOPException                      e          )          {          // TODO Auto-generated catch block                      e          .          printStackTrace          ();          }          catch          (          IOException                      e          )          {          // TODO Auto-generated catch block                      e          .          printStackTrace          ();          }          catch          (          TransformerException                      e          )          {          // TODO Auto-generated catch block                      e          .          printStackTrace          ();          }          }          /**      * Method that will convert the given XML to PDF       * @throws IOException      * @throws FOPException      * @throws TransformerException      */          public          void                      convertToPDF          ()          throws          IOException          ,          FOPException          ,          TransformerException          {          // the XSL FO file          File                      xsltFile                    =          new          File          (          "F:\\Temp\\template.xsl"          );          // the XML file which provides the input          StreamSource                      xmlSource                    =          new          StreamSource          (          new          File          (          "F:\\Temp\\Employees.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          (          "F:\\Temp\\employee.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          ();          }          }          /**      * This method will convert the given XML to XSL-FO      * @throws IOException      * @throws FOPException      * @throws TransformerException      */          public          void                      convertToFO          ()          throws          IOException          ,          FOPException          ,          TransformerException          {          // the XSL FO file          File                      xsltFile                    =          new          File          (          "F:\\Temp\\template.xsl"          );          /*TransformerFactory factory = TransformerFactory.newInstance();         Transformer transformer = factory.newTransformer(new StreamSource("F:\\Temp\\template.xsl"));*/          // the XML file which provides the input          StreamSource                      xmlSource                    =          new          StreamSource          (          new          File          (          "F:\\Temp\\Employees.xml"          ));          // a user agent is needed for transformation          /*FOUserAgent foUserAgent = fopFactory.newFOUserAgent();*/          // Setup output          OutputStream          out          ;          out          =          new                      java          .          io          .          FileOutputStream          (          "F:\\Temp\\temp.fo"          );          try          {          // 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());          Result                      res                    =          new          StreamResult          (          out          );          //Start XSLT transformation and FOP processing                      transformer          .          transform          (          xmlSource          ,                      res          );          // 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          ();          }          }          }        

In the code there are two methods convertToPDF() and convertToFO(), convertToPDF() method is used to convert XML to PDF. convertToFO() method will create the XSL-FO from the XML using the XSLT. If you want to see the created FO which in turn is used to create PDF please call this method.

In case of web application if you want to provide PDF as a download add following lines with in the convertToPDF() method-

          //Prepare response                      response          .          setContentType          (          "application/pdf"          );                      response          .          setContentLength          (          out          .          size          ());          //Send content to Browser                      response          .          getOutputStream          ().          write          (          out          .          toByteArray          ());                      response          .          getOutputStream          ().          flush          ();        

Reference : click here to go

My Notes:

How it works

We have an XML that holds data and an XSLT that creates an XML containing formatting objects by taking data from the first XML. This resultant XML is de-serialized into Java objects. FOP creates a PDF file using these Java objects.

Apache FOP Stuff

For space

<fo:leader leader-pattern="space"/>

For Horizontal Line

<fo:leader leader-pattern="rule" leader-length="100%" rule-style="solid" rule-thickness="0.5pt" color="#005598″/>

For Image display

<fo:external-graphic src=url('http://………&#8230;./tick.png') content-height="5%" content-width="5%"/>

or

<fo:external-graphic src='http://………&#8230;./tick.png'  content-height="5%" content-width="5%"/>

How to use list elements(with Bullet character)

<fo:list-block > <!– list start –>
<fo:list-item> <!– list item –>
<fo:list-item-label end-indent="label-end()">
<fo:block>
<fo:inline font-family="Symbol">&#x2022</fo:inline> <!– insert a bullet –>
</fo:block>
</fo:list-item-label>
<fo:list-item-body start-indent="body-start()"><!– list text –>
<fo:block>
here is text in the list item body
</fo:block>
</fo:list-item-body>
</fo:list-item>
[other list items…]
</fo:list-block> <!– end list –>

fo:table-cell span 2 columns

<fo:table-cell number-columns-spanned="2">

XSLT Stuff

if else condition in XSLT

<xsl:choose>
<xsl:when test="expression">
… some output …
</xsl:when>
<xsl:otherwise>
… some output ….
</xsl:otherwise>
</xsl:choose>

check node value and display

<xsl:if  test="nodeName[text() != " ]"  </xsl:if> (node value is not empty then it will display else ignore

for-each in XSLT

<xsl:for-each select = ownerList/owner">

<xsl:value-of select="name"/>

<xs:value-of select="age"/>

</xsl:for-each>

List size check

<xsl:if test="count(ownerList/owner) > 0″>

</xsl:if>

Resources : https://www.ibm.com/developerworks/xml/library/x-xslfo2app/