I pity the fool who don't report with FO

I needed a reporting system to replace JFreeReport. Although it's a decent project I found it very cumbersome to create reports with dynamic columns. My solution is to create the report in XHTML, and use FO to convert that into PDF. It's very easy to code my document's tables using XHTML, and very well understood. This is an overview of that solution.

First off, some FO projects:
XSL-FO an XML schema that describes a paper document. I like to think of it as an XML alternative to PDF. It's also a W3C recommendation.
Apache FOP an open source renderer for FO coded in Java. It's mostly feature complete. Apache FOP takes a FO file and sends it to PDF, a printer, or the screen. This is the FO implementation I used.
Antenna House a commercial renderer for FO. It's $1250 for a client and $5000 for a server. They have some useful FO documentation on their site, but their XSL transformation won't work with Apache FOP.
RenderX another commercial renderer for FO. It's probably more complete than FOP but it costs $299 for a client and $4000 for a server.

Its fairly straightforward to convert an XHTML document into a FO document. DeveloperWorks has a fantastic article describing the whole process. The article includes a starter XSLT transformation to get you started. The transformation is well documented and it was easy for me to tweak it for my reporting system. I made the following changes:
  • Removed table of contents
  • Changed left footer to document title
  • Changed right footer to page count
  • Removed headers
  • Added an XML namespace for XHTML. This requires the document's <html> tag to include the namespace. For example: <html xml:lang="en" lang="en" xmlns="">
    The finished stylesheet creates a nice PDF that includes a "table of contents" for navigating the document easily.

    FOP's Limited XHTML
    The biggest limitation of Apache's FOP is that it requires that column widths be specified in advance. To overcome this, we have to modify the tables in our XHTML file to specify these column widths. Widths must be specified in points, which is 1/72 of an inch. Fortunately the math is pretty easy. For simplicity assume our page is letter size (8.5" x 11") with 1" margins. Then we have 6.5x72=468 points to distribute over our columns. If we have 3 columns, thats 156 points each. This give us this XHTML table tag: <table border="1" cols="156pt 156pt 156pt">

    XHTML rules. Everyone understands it and it's easy to generate. This provides a nice mechanism for your Java program to create nice PDF reports using XHTML.
  • Thank you for this analysis. it is very helpful.
    I am using RenderX XEP Engine for rendering purposes