Debug XSLT

Debug

1. Debugging tips
2. Debugging XSLT
3. Debugging.... Conditionally including XML
4. How to include or exclude content for debug

1.

Debugging tips

Michael Kay et al

Here's a selection, of varying degrees of obviousness.

General-purpose:

Add <xsl:message> to output progress messages

Add <xsl:comment> to put messages into the result tree indicating where output nodes came from

Use <xsl:comment><xsl:value-of select="system-property('xsl:vendor')"/></xsl:comment> so you are in no doubt about which XSLT processor you are using

To output the values of variables, using attribute value templates is quicker than using xsl:value-of, e.g. write <debug x="{$x}" y="{$y}"/>

If you want to leave debug lines in the stylesheet that can be switched on and off at will, make them into extension elements:

  <xsl:stylesheet xmlns:debug="debug.uri"
    extension-element-prefixes="debug">
  ...

      <debug:debug x="{$x}" y="{$y}"><xsl:fallback/></debug:debug>

The <debug:debug> element will be ignored, but values will be output if "debug" is removed from the "extension-element-prefixes" attribute.

To see what's in a temporary tree (or result tree fragment), copy it to the output:

  <debug tree="$x">
    <xsl:copy-of select="$x"/>
  </debug>

To add tracing to all template rules, add a debug module:

  <xsl:import href="real-stylesheet.xsl"/>
  <xsl:template match="*">
    <xsl:message>Processing <xsl:value-of
select="name()"/></xsl:message>
    <xsl:apply-imports/>
    <xsl:message>Finished processing <xsl:value-of
select="name()"/></xsl:message>
  </xsl:template>

(You can also use xsl:comment instead of xsl:message)

To deal with character-encoding problems: use a hex editor!

If the source (or result) XML is badly laid out and difficult to understand, run it through an indentation transform:

  <xsl:strip-space elements="*"/>
  <xsl:output method="xml" indent="yes"/>
  <xsl:template match="/">
    <xsl:copy-of select="."/>
  </xsl:template>  

If you don't understand the error messages from your XSLT processor (or if you are beginning to suspect that it has a bug), run the transformation through another XSLT processor to see if it sheds any light on the matter.

Saxon-specific:

Use -T on the command line to switch on tracing

Use saxon:path() to output an XPath expression that identifies the context node

Use saxon:line-number() to output the line number of the context node in the source file (having switched on numbering using -l on the command line)

In 7.x only: add type declarations on variables and parameters, e.g. <xsl:param name="x" as="xs:integer"/> to trap type errors.

MSXML3-specific:

Get your transformation working in standalone mode first, before you integrate it into the browser. Write the version used in the browser as a customisation layer (using xsl:import) of the standalone version, and when debugging is necessary, use the standalone version. Try to avoid debugging in the browser.

2.

Debugging XSLT

David Tolpin



> I am currently trying to track down an XHTML problem. I would love to 
> have the transformation break at the point of the error. I hate having 
> to view source and copy the contents to a new file to submit it for 
> validation (the render is dynamic).

Validity errors are just one kind of many, they are neither the most frequent nor the most nasty errors. Providing one error-prone mechanism for one kind of errors is a mistake.

I do not propose you 'copy the contents to a new file' to submit it to validation. Cut-and-paste is not the only IPC (inter-process communication) technology. The XSLT specification could describe an extension mechanism usable for plug-in debugging/assertion facilities.

You do not want the transformation to break each time an error condition is met, it is waste of time. Instead, you want as many reports about failed assertions as feasible during one run. Embedding back-references to the code of the stylesheet and to the input tree into the transformation result and using a tool to check and report assertion failures (not just validity assertion, and obviously not just validity assertions using one schema language) is much better for the following reasons:

- it is as powerful fo the same validation task
- its is more powerful for debuggin in general since it allows to provide other types of assertions too, using Schematron, for example;
- it is easier to implement and support
- it provides clear separation of layers
- it does not contaminate the language with ugly kludges solving partial problems.

3.

Debugging.... Conditionally including XML

Jeni Tennison

Probably the best way to approach this is to have a parameter called debugp that is by default 'false' and can be set to true when you call the processor from the command line.

To set up the parameter:

<xsl:param name="debugp" select="'false'" />

How you pass the value for the parameter into the stylesheet is dependent on the processor that you're using. With Saxon, for example, you'd use something like:

  saxon -a -o out.xml in.xml debugp=true

Within the stylesheet, I would then set up a variable that is true() when $debugp is 'true' and false() when $debugp is 'false' - this is just to make testing for whether you're in debug mode easier:

<xsl:variable name="debug" select="$debugp = 'true'" />

You can then conditionally add text when in debug mode using xsl:if or xsl:choose/xsl:when that test on the value of $debug:

<xsl:if test="$debug">
  <!-- add some debugging text -->
</xsl:if>

<xsl:choose>
  <xsl:when test="$debug">
    <!-- text added when debugging -->
  </xsl:when>
  <xsl:otherwise>
    <!-- text added when not debugging -->
  </xsl:otherwise>
</xsl:choose>

To send the debugging information to the screen rather than into the output file, you can use xsl:message within the debugging sections (or outside them for messages that you always want to see).

> But how do I include debuging information,
> in particular a copy of the source XML, into
> the output while not effecting the output XML.
> I.e. it needs to be in an xsl:comment block.

Well it's kinda ugly, but you could do:

<xsl:if test="$debug">
  <!-- start comment -->
  <xsl:text disable-output-escaping="yes">&lt;--</xsl:text>
  <!-- copy the document -->
  <xsl:copy-of select="/" />
  <!-- end comment -->
  <xsl:text disable-output-escaping="yes">--></xsl:text>
</xsl:if>

I would normally stay well away from disable-output-escaping but Mike Kay used it the other day in a similar situation so I don't feel so bad.

4.

How to include or exclude content for debug

David Carlisle




something like this?


<xsl:param name="debug-flag" select="0"/>

...


<xsl:if test="$debug-flag &gt; 0">
  <xsl:message>foo</xsl:message>
  <xt:document href="debug-trace.txt">....</xt:document>
</xsl:if>

...

xt file.xml style.xsl out.xml debug-flag=6