Visually debugging XSL-FO stylesheets

When developing XSL-FO stylesheets sooner or later you will see something that doesn’t look as intended: It has the wrong margin, padding, line height, floats in the wrong place, etc. If you have no visual debugging tool, the quickest way to check for errors is setting a border or background attribute on the element in question.

<curmudgeon>Just like we debugged web layouts in 1999! We had nothing like that fancy Firebug plugin, just our trusty notepad and bare HTML! And we liked it!</curmudgeon>

I had several gripes with this ad-hoc approach:

  • I have to remember to take out the debugging attributes
  • I have to search all over my stylesheet when elements reside in different templates
  • Removing attributes can be a bit error-prone: You have to select excactly the right characters with the mouse or press several keys. You run the risk of leaving whitespace behind or deleting parts of other attributes
  • Sometimes borders and backgrounds are deliberate. How do you tell debugging attributes and \“real\” attributes apart?

My solution: *Insert a special debugging attribute (from a separate namespace) into the elements you want to debug and postprocess your XSL-FO output with a stylesheet that replaces the debugging attribute with the desired debug formatting!* When your debug work is finished, you can leave the debugging attributes where they are and turn off the postprocessing.

Using a separate stylesheet will ensure that you can group the debugging requirements neatly in one stylesheet. To make this even easier, the debugging attributes are placed in a separate stylesheet, debugattributes.xsl. The code for postprocessing is in the debugging.xsl stylesheet and doesn’t need to be changed.

How to use the xsldebug stylesheet

Step 1: Enable debugging in the stylesheet

Suppose you want to debug the following template:

<xsl:template match="p">
    <fo:block-container>
        <fo:block font-size="100%" space-after="1em" text-align="justify">
            <xsl:apply-templates/>
        </fo:block>
    </fo:block-container>
</xsl:template>

Add the debugging namespace http://lebenplusplus.de/xsldebug to your stylesheet header:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
   xmlns:fo="http://www.w3.org/1999/XSL/Format"
   xmlns:h="http://www.w3.org/TR/REC-html40"
   xmlns:xs="http://www.w3.org/2001/XMLSchema"
   xmlns:dbg="http://www.lebenplusplus.de/xsldebugging/v1"
   exclude-result-prefixes="xs dbg"
   >

Now add the attribute dbg:class to each element you want to modify. You can freely choose the name of the debug class.
Tip 1: Choose a debug class that fits the match or name attribute of your template.
Tip 2: Liberally sprinkle your stylehseet with debugging attributes, you’ll never know when you need them!

<xsl:template match="p">
    <fo:block-container dbg:class="p">
        <fo:block font-size="100%" dbg:class="p" space-after="1em" text-align="justify">
            <xsl:apply-templates/>
        </fo:block>
    </fo:block-container>
</xsl:template>

Step 2: Define styles for the debugging attributes

Open the file debugattributes.xsl and put fo: elements in the debugattributes variable definition.

<xsl:variable name="debugattributes">
    <fo:block border="solid 1pt #33aa22" dbg:class="comment" />
    <fo:block-container border="solid 1pt #aa3322" dbg:class="comment" />
</xsl:variable>

You don’t need to define an element you don’t want to debug - the debugging stylesheet will remove all debug attributes from the elements.

You can put non-empty elements inside $debugattributes, but the stylesheet will only copy the attributes, all other content is ignored.

Step 3: Integrate debugging into your workflow

If you are using the Saxon XSLT processor, you can integrate debugging in two steps:

First, add the saxon namespace to your namespace declarations:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
   xmlns:fo="http://www.w3.org/1999/XSL/Format"
   xmlns:h="http://www.w3.org/TR/REC-html40"
   xmlns:xs="http://www.w3.org/2001/XMLSchema"
   xmlns:dbg="http://www.lebenplusplus.de/xsldebugging/v1"
   xmlns:saxon="http://saxon.sf.net/"
   exclude-result-prefixes="xs"
   >

Then, add a postprocessing attribute to your <xsl:output> tag:

<xsl:output method="xml" indent="no" saxon:next-in-chain="debugging.xsl"/>

If you use Ant or a Makefile for your workflow, add an additional task that processes the output of your regular XSLT transformation with the debugattributes.xsl stylesheet.

If you are already using a XProc tool I don’t need to tell you how to integrate the postprocessing :-)

When you are done debugging, but not done developing your stylesheet, you can simply leave $debugattributes empty until the need for debugging arises again.

What next?

I have created the stylesheet to scratch a personal itch. If it’s useful for you or if you want to improve it, fork xslfodebugging on GitHub!.

Some ideas of what could be useful in the future:

  • Debug id attributes
  • Insert debugging elements
  • Output debug messages with <xsl:message>
  • Turn the stylesheet into a general-purpose postprocessing-for-debugging tool for other dialects than XSL-FO?