Home Page XSL-FO running subtotals
Home
XSL-FO Server
Getting started
Versions
How to
XSL-FO Editor
XSL-FO resources
XSL-FO in REALbasic
XSL-FO in Php
XSL-FO in VB 6
XSL-FO in .NET
XSL-FO in Ruby
XSL-FO in Delphi
Usage with APEX
Prof. license
XSL-FO running totals

 

In this article we will see how to create a page subtotal in XSL and more specifically using Apache FOP and XSL-FO to create PDF files.

We will use as input for the example this file which is a list of cars: 


<?xml version="1.0"?>
<cars>

<car>
<licenseid>1254-TH</licenseid>
<color>red</color>
<count>2</count>
</car>

<car>
<licenseid>2254-FH</licenseid>
<color>blue</color>
<count>4</count>
</car>

<car>
<licenseid>2264-FT</licenseid>
<color>blue</color>
<count>4</count>
</car>

<car>
<licenseid>4464-FT</licenseid>
<color>gree</color>
<count>3</count>
</car>

<car>
<licenseid>2211-GT</licenseid>
<color>red</color>
<count>5</count>
</car>

</cars>


in each car we have the <count> tag which is required to be added and put in the page footer as page subtotal, the PDF output will look like this:


if we had a long list which occupies 2 pages, we would have a subtotal in each page.

but how do we do that? we do not know which or how many cars will be listed in each page of the PDF file.

In fact we do not need to know that, the way to solve this problem is by using the <fo:marker> tag. The <fo:marker> tag and the <fo:retrieve-marker> tags are used together for creating running totals. This has 2 parts:

  • first we define what and how we will be adding. We will create a marker with name markerRVField6 which will store the running total count. We select the <count> tag of the current car (see  <xsl:value-of select="count below ) and sum it with all preceding <count> tags (see sum(preceding::count) below).

    <fo:marker marker-class-name="markerRVField6"><xsl:value-of select="count + sum(preceding::count)"/></fo:marker>
  • and the second part is, in the page footer we retrieve the current value of the marker

    <fo:retrieve-marker retrieve-class-name="markerRVField6" retrieve-boundary="page" retrieve-position="last-starting-within-page"/>

    note the attribute value last-starting-within-page which makes sure you print in the footer the sum corresponding to the last car in the page (added to the preceding ones).

If you want to test this yourself you will need to download Apache FOP. After that you copy the XML data to a file called carsCount.xml and the xsl file to carsCount.xsl. Once you have these 2 files you run Apache FOP like this:

fop.bat -xml carsCount.xml -xsl carsCount.xsl -pdf carsCount.pdf

 

Do you want to know more?

This is just a simple example to get started, you can find a more detail documentation here:

If on the other hand you do not want to get involved with these details, our J4L FO Designer will create the XSL-FO file for you.


The XSL-FO file:

 

<?xml version="1.0" encoding="UTF-8"?><xsl:transform version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  >
<xsl:template match="/">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="master0" page-width="21.0cm" page-height="10.7cm" margin-top="2.0cm" margin-bottom="2.0cm" margin-left="2.0cm" margin-right="2.0cm" > 
<fo:region-body region-name="body0" margin-top="1.5cm" margin-bottom="1.5cm" /> 
<fo:region-after region-name="footer0" extent="1.5cm"/> 
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="master0">

<!-- page footer -->

<fo:static-content flow-name="footer0">
<fo:block margin-left="0.0cm" margin-right="1.89cm" margin-top="0.0cm" font-size="10pt" font-family="SansSerif" color="#000000" text-align="left">Subtotal <fo:retrieve-marker retrieve-class-name="markerRVField6" retrieve-boundary="page" retrieve-position="last-starting-within-page"/></fo:block>
</fo:static-content>

<!-- page content, list of cars -->

<fo:flow flow-name="body0"> 
<xsl:for-each select="cars/car">

<fo:block margin-left="0.0cm" margin-right="0.21cm" margin-top="0.0cm" font-size="10pt" font-family="SansSerif" color="#000000" text-align="left">License= <xsl:value-of select="licenseid"></xsl:value-of> count <xsl:value-of select="count"></xsl:value-of></fo:block>

<fo:block margin-left="0.25cm" margin-right="11.68cm" margin-top="0.0cm" font-size="10pt" font-family="SansSerif" color="#000000" text-align="left"><fo:marker marker-class-name="markerRVField6"><xsl:value-of select="count + sum(preceding::count)"/></fo:marker></fo:block>

</xsl:for-each>

</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
</xsl:transform>