How and where could I output log messages for debug and performance purposes during an XSLT transformation?
I guess the simplest method is using express
I would suggest using xsl:message
if you are in a development environment such as oXygen or Stylus Studio, and using xsl:comment
if you are running in the browser. You shouldn't really be debugging your XSLT code in the browser - the browsers I know about are lousy as XSLT debugging tools.
A simple hack would be to create a variable with xsl:variable
and to either just concat()
new values to it or to set up a xsl:template
which does the same thing. Then you just need to output this variable at the end of the execution and you can explicitly choose where to show the log.
You should be able to use <xsl:message> I think, although where the logging goes is implementation-dependent.
This is exactly what <xsl:message>
is designed for. However, the output location is entirely dependent on the processor. I only have a Mac handy but, sadly, both Firefox and Safari suppress the <xsl:message>
output. I expect MSIE will do the same.
Given that, I think your best bet is to use <xsl:comment>
to generate your logs. Something like the below should do the trick:
<xsl:template match='my-element'>
<xsl:comment>Entering my-element template</xsl:comment>
<p class='my-element'><xsl:apply-templates/></p>
<xsl:comment>Leaving my-element template</xsl:comment>
</xsl:template>
That would give you something like this in the output:
<!-- Entering my-element template -->
<p class='my-element'>...</p>
<!-- Leaving my-element template -->
Clearly, you can put whatever logging you want into that that output. I would consider creating something like the following and using it to run your logging. This references a global param called 'enable-logging' to determine if logging should occur or not.
<xsl:template name='create-log'>
<xsl:param name='message'/>
<xsl:if test="$enable-logging = 'yes'">
<xsl:comment><xsl:value-of select='$message'/></xsl:comment/>
</xsl:if>
</xsl:template>
Use this in your stylesheet as:
<xsl:template match='my-element'>
<xsl:call-template name='create-log'>
<xsl:with-param name='message'/>Entering my-element template</xsl:with-param>
</xsl:call-template>
<p class='my-element'><xsl:apply-templates/></p>
<xsl:call-template name='create-log'>
<xsl:with-param name='message'/>Leaving my-element template</xsl:with-param>
</xsl:call-template>
</xsl:template>
One benefit of doing it this way is you can change that <xsl:comment>
to <xsl:message>
when in a more complete environment. It is more verbose but more general.
By looking for a solution to this problem, I ended up implementing a logging mechanism in XSLT in similar fashion to log4j, using mostly xsl:message and pure XSLT 2.x. I took some of the answers in this page as inputs. The library is available here: https://github.com/ukuko/log4xslt
Modifying your XSLT itself for the purposes of logging is inevitably going to impact on performance, you're probably better off using an external tool. There are a few available depending on what you're working with: