Logging with XSLT

2019-03-15 21:06发布

问题:

How and where could I output log messages for debug and performance purposes during an XSLT transformation?

I guess the simplest method is using expressions like this:

<xsl:text>message text</xsl:text>

here and there in the code, using xsl:value-of if needed.

But this method prints the messages in a lot of places in the output file (HTML page in my case), that is where it is called, and not always in the same place (like a log file).

Is this the only way or is there a better solution? Thanks!

回答1:

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.



回答2:

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.



回答3:

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



回答4:

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:

  • Stylus Studio
  • Visual Studio
  • Altova XMLSpy


回答5:

You should be able to use <xsl:message> I think, although where the logging goes is implementation-dependent.



回答6:

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.



标签: xslt logging