XQuery/XSL-FO Tables

Motivation
You want to be able to create high-quality tabular outputs suitable for book-publishing.

Method
To accomplish this we will convert our XML into XSL-FO tables. Unlike HTML, XML-FO allows you to create flows of text and you can set up rules on how objects span page boundaries.

Sample Input
Here is a sample XML file that contains a table with two columns.

We would like this XML file to be rendered with two columns, the first containing the person's name and the second their phone extension. It should look like the following.

Example FO File
The following is the core of the XML-FO layout that you will need to create the table (without control on the column widths).

Transform with XSLT
NOTE: This example should be moved to a book on XSLT. XQuery typeswitch transforms should be used to do this.

We can transform the XML structure to XSL-FO using an XSLT script. This generic script only requires that the root of the XML table is called table with a heading attribute.

XQuery integration
Finally we can generate the full XSL-FO document and render as PDF with an XQuery script. We use the XSLT to transform the table, and then embed that XSL-FO fragment in the XSL-FO master before rendering as PDF and streaming the binary document. There are of course other ways to assemble the full XSLT-FO document.

let $table-fo := transform:transform($table,doc("/db/Wiki/eXist/xsl-fo/table2fo.xsl"),) let $fo :=          {$table-fo}     let $pdf := xslfo:render($fo, "application/pdf", ) return response:stream-binary($pdf, "application/pdf", "output.pdf")

Execute

Database data
As a further example, the following XQuery selects all employees and renders them in a PDF table:

let $table-fo := transform:transform($table,doc("/db/Wiki/eXist/xsl-fo/table2fo.xsl"),) let $fo :=    <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> {$table-fo} </fo:block> </fo:flow> </fo:page-sequence> </fo:root> let $pdf := xslfo:render($fo, "application/pdf", ) return response:stream-binary($pdf, "application/pdf", "output.pdf")

Execute