XSLTExtensions

From Print and Page Layout Community Group
(Redirected from FOPRunXSLTExt)
Jump to: navigation, search

This is an experiment in getting the area tree from an XSL formatter run as the result of calling an XSLT extension function in the same XSLT transform as will produce the "final" FO tree to be output for formatting as human readable pages.

It was initially developed in Java by Arved Sandstrom of MagicLamp Software following discussion on the public-ppl@w3.org mailing list. Other XSLT–XSL-FO combinations in Java and DotNet have followed. Further development now happens in the 'ppl' Mercurial repository at https://dvcs.w3.org/hg/ppl, with questions and comments happening on the public-ppl@w3.org mailing list.

The extension is available for Java and DotNet and uses either the Apache FOP XSL formatter or Antenna House AHF formatter to produce the area trees.


The single Java jar file covers four combinations of XSLT processor and XSL-FO formatter:

  • Saxon 9.5 and FOP
  • Saxon 9.5 and Antenna House
  • Xalan and FOP
  • Xalan and Antenna House

The DotNet version supports:

  • DotNet 4.0 and FOP
  • DotNet 4.0 and Antenna House

Contributions of code for more combinations are more than welcome.

License

Available under the W3C license.

Example XSLT

The extension functions and templates are in 'ppl-extensions.xsl'. Functions and named templates for you to use are all in namespace of the PPL namespace URI:

xmlns:ppl="http://www.w3.org/community/ppl/ns/"

Get the area tree for XSL-FO tree:

 <xsl:variable
     name="area-tree"
     select="ppl:area-tree($fo_tree)"
     as="document-node()?" />

Find the block corresponding to an ID in the FO tree:

 <xsl:variable
     name="block"
     select="ppl:block-by-id($area-tree, key('boxes', true())[1]/@id)"
     as="element()" />

Find the block-progression-dimension of a block:

 <xsl:variable
     name="bpd"
     select="ppl:block-bpd($block)"
     as="xs:double" />

Installation

The best way to get an up-to-date version is to clone the Mercurial repository and build it yourself.

The most recent distribution is available at File:XSLTExtensions.zip

The extension requires the following libraries:

Java

  • saxon9he.jar
  • xalan2-2.7.1.jar
  • fop-1.0.jar
  • xmlgraphics-commons-1.4.jar
  • avalon-framework-4.2.0.jar
  • commons-logging-1.1.1.jar
  • batik-all-1.7.jar
  • commons-io-1.4.jar
  • serializer-2.7.1.jar

Building it also requires Apache Ant.

DotNet

  • DotNet FrameWork 4.0 Client Profile

FOP

Antenna House Formatter

  • Antenna House Formatter 6.1
  • pi.ep.xslt.transformer.app.exe File:DotNetXSLTExtProcessor.zip
  • fit pi.ep.xslt.transformer.app.exe.config as described in that file

Windows

Java

Get the most recent (FOP-only) Windows distribution from File:FOPRunXSLTExt-windows-0.0.2.zip, unzip it on your system, and follow the instructions in the 'README' file.

1. Get and install Java JRE

2. Get and install Saxon

Saxon-HE is available from http://saxon.sourceforge.net/ as a Zip-encoded archive. Download the Zip file and extract its contents onto your local disk.

3. Get and install FOP 1.0

FOP distributions are available from http://xmlgraphics.apache.org/fop/download.html. Download the binary distribution of FOP 1.0 and extract its contents onto your local disk.

4. Edit 'runsaxon9he_fop10.bat' so the line beginning "set SAXON=" has the correct path to the Saxon-HE jar file on your system and so the line beginning "set FOP_HOME=" has the correct path to the "fop-1.0" folder that you extracted from the FOP binary distribution.

5. In the same directory as 'runsaxon9he_fop10.bat', run the following command:

     runsaxon9he_fop10.bat example1.xml example1_saxon9_fop10.xsl out/example1_saxon9_fop10.at

DotNet

1. Get the most recent files from File:XSLTExtensions.zip, unzip it on your system, and follow the instructions in the 'README' file.

2. Get and install DotNet 4.0 FrameWork Client Profile

3. Get DotNetXSLTExtProcessor File:DotNetXSLTExtProcessor.zip

4. Apache FOP

5. Antenna House Formatter

  • Get and install Antenna House Formatter
  • open pi.ep.xslt.transformer.app.exe.config in an (XML) editor
  • follow instructions there and fit settings: Path and Version of XfoDotNet40Ctl61.dll

6. Copy all downloaded files in the same directory as rundotnet_fop11.bat or rundotnet_ahf61.bat

7. Run samples Apache FOP (in the same directory as rundotnet_fop11.bat)

     rundotnet_fop11.bat example1.xml example1.xsl out/example1_dotnet_fop11.at

8. Run samples Antenna House Formatter (in the same directory as rundotnet_ahf61.bat)

     rundotnet_ahf61.bat example1.xml example1.xsl out/example1_dotnet_ahf61.at

Rebuild packages

Java

Building it also requires Apache Ant.

DotNet

1. Get and install Microsoft Visual Studio 2010 (C#) (Express Edition and 2012 works, too)

2. Create a solution project in MS VS

3. Add C# projects to this solution

  • Antenna House Formatter: src\org\w3c\ppl\xslt\ext\ahf\dotnet\pi.ep.ppl.xslt.ext.ahf.dotnet\pi.ep.ppl.xslt.ext.ahf.dotnet.csproj
  • Apache FOP: src\org\w3c\ppl\xslt\ext\fop\dotnet\pi.ep.ppl.xslt.ext.fop.dotnet\pi.ep.ppl.xslt.ext.fop.dotnet.csproj

4. Antenna House Formatter

  • Get XfoDotNet40Ctl61.dll (in AHF instdir)
  • Copy it to: src\org\w3c\ppl\xslt\ext\ahf\dotnet\pi.ep.ppl.xslt.ext.ahf.dotnet\import

5. Apache FOP

  • Copy all IKVM.OpenJDK.*.dll s to src\org\w3c\ppl\xslt\ext\fop\dotnet\pi.ep.ppl.xslt.ext.fop.dotnet\import
  • Copy IKVM.Runtime.dll to src\org\w3c\ppl\xslt\ext\fop\dotnet\pi.ep.ppl.xslt.ext.fop.dotnet\import
  • Copy IKVM.Runtime.JNI.dll to src\org\w3c\ppl\xslt\ext\fop\dotnet\pi.ep.ppl.xslt.ext.fop.dotnet\import
  • Copy Fop11.dll to src\org\w3c\ppl\xslt\ext\fop\dotnet\pi.ep.ppl.xslt.ext.fop.dotnet\import

Examples

Example 1 - Area Tree

This just writes an area tree to a file.

Windows

runsaxon9he_fop10.bat example1.xml example1_saxon9_fop10.xsl out/example1_saxon9_fop10.at
rundotnet_fop11.bat example1.xml example1.xsl out/example1_dotnet_fop11.at

Linux/Mac

./runsaxon9he_fop10.sh example1.xml example.xsl out/example1_saxon9_fop10.at
./runsaxon9he_ahf61.sh example1.xml example1.xsl out/example1_saxon_ahf61.at
./runxalan_fop10.sh example1.xml example1.xsl out/example1_xalan_fop10.at
./runxalan_ahf61.sh example1.xml example1.xsl out/example1_xalan_ahf61.at

Example 3 - Rotate wide block

Rotates a fixed-size box if it is too wide for the page.

This is effectively a simplified version of requirement #10 from CustomerRequirements. That requirement is for knowing whether a table should be column-wide, page-wide, or rotated to to be page-high based on its formatted size. To do that, the stylesheet would have to get the sizes of the table when it's formatted to be column-wide, page-wide, and page-high and, based on those, decide which width and orientation to use for the table in the formatted result. This example reduces that to a single fixed-size block, analogous to the size of the formatted table, and the stylesheet just makes the single decision whether or not to rotate the block based on its formatted width.

The <box> element in 'example3.xml' specifies its formatted height and width:

  <box id="box001" width="8in" height="5in">

With those dimensions, if you transform 'example3.xml' with 'formatting.xsl' and format the result, the box is wider than the width of the page and some of the text is lost.

FOPRunXSLTExt-example3-overflow.png

If you transform 'example3.xml' with 'example3_saxon9_fop10.xsl', which uses the extension function to make an area tree during the transform and makes decisions based on formatted areas, the box is rotated when it is too wide for the page.

FOPRunXSLTExt-example3-rotated.png

Run the example using one of the command lines below then then run an XSL formatter on 'out/example3_saxon9_fop10.fo' to see the result.

You can change the box/@width value in 'example3.xml' and run it again to see whether or not the box is rotated.

Windows

runsaxon9he_fop10.bat example3.xml example3.xsl out/example3_saxon9.fo

Linux/Mac

./runsaxon9he_fop10.sh example3.xml example3.xsl out/example3_saxon9.fo
./runsaxon9he_ahf61.sh example3.xml example3.xsl out/example3_saxon9.fo

Example 4 - List item label width

Adjusts the lengths allowed for list items to exactly fit the formatted width of the list item labels.

This demonstrates a solution to requirement #9, "Ability to modify label field width in a single list when labels are large", from CustomerRequirements.

'example4.xml' includes two lists that, when transformed with 'formatting.xsl' and formatted, have list item label widths that are either too wide or too narrow for the labels in the lists.

FOPRunXSLTExt-example4-wrong.png

When transformed with 'example4_saxon9_fop10.xsl' and formatted, the list item label widths are set based on the actual maximum formatted width of the labels in each list. The 'example4_saxon9_fop10.xsl' stylesheet does this by constructing a test document containing just the list item label texts, using the extension function to format that and get the area tree, and determining the maximum widths from the area tree. The document that is formatted mid-transform is, unlike in previous examples, a different document to the one used to produce the final output.

FOPRunXSLTExt-example4-right.png

Example 5 - Copyfitting by adjusting 'font-size'

Adjusts the 'font-size' property until the formatted text fills a 'fo:block-container'.

The stylesheet includes a 'do-box' named template that -- based on the provided text and the initial values of minimum, optimum, and maximum font sizes, the tolerance for a good fit, and the maximum number of iterations -- runs the XSL formatter on the provided text and, when the size of the formatted text differs from the required size by more than the tolerance, iteratively calls itself again with adjusted font size limits until either the formatted size is within the tolerance or the maximum number of iterations is reached.

Fill-box.png


Windows

runsaxon9he_fop10.bat example5.xml example5.xsl out/example3.fo

Linux/Mac

./runsaxon9he_fop10.sh example5.xml example5.xsl out/example3.fo
./runsaxon9he_ahf61.sh example5.xml example5.xsl out/example3.fo

Contributors

  • Arved Sandstrom
  • Tony Graham
  • Markus Wiedenmaier