text: Long before they turn to a debugger, most developers start with the equivalent of.
  Listing 1 (labels.xml) is a source document I shall use throughout this discussion. It is a simple XML document that contains data for mailing address labels.
  Listing 1. Mailing labels (labels.xml)
  Listing 2 (plainmsg.xslt) is a simple style sheet. In it, I use
  xsl:message to display the node set of addresses I get from a simple XPath expression.
  Listing 2. Example that uses plain xsl:message for debugging (plainmsg.xslt)
  The message displays only the address element for each label, and its descendants. The XPath expression in question,
  label/address, is accessed through the
  addresses variable. I might use such a technique to spot the common XPath error where a typo is made in an element name, and thus a returned node set would be unexpectedly empty. This can lead to odd effects further on in the processing. By using such debugging messages, you can spot the problem closer to the source. The most important thing to notice is that I use
  xsl:copy-of rather than
  xsl:value-of to put the node set into the message. The output I get using 4XSLT is:
  If I had instead used
  xsl:value-of --
  -- then the output would have been the considerably less useful:
  This is because
  xsl:value-of converts the results of its select expression to a flattened string representation of the first node in the node set.
  xsl:copy-of actually copies all the nodes to the message body in their entirety as intact markup, which is what you usually want.
  In more complex scenarios, where there are many templates and several debug messages sprinkled about, it may be handy to present some of the XPath context in the message, as well. The context node itself is usually the handiest bit of information for debugging the most common errors. Listing 3 is a fragment of XSLT that illustrates this:
  Listing 3. An xsl:message instruction formatted to display the serialized context node as well
  This formats the message into a header and body, and displays the context node in the header (
  <xsl:copy-of). Notice the "
  " entities that I sprinkle about: These are line feed entities, and are a safe way to force carriage returns in XSLT (as long as they are not stripped as white space, which is why I made sure they are in the
  xsl:text tag).
  If your XSLT processor supports the
  dyn module of the EXSLT standard XSLT extensions, there is a lot more you can do while debugging. The
  dyn module provides tools for dynamically evaluating XPath expressions at run time. You can exploit this facility to add some neat debugging tricks by examining the style sheet itself at run time. This is similar to what is referred to as introspection in some languages. As an example, I shall add a little utility template for displaying the value of all global variables. Listing 4 is a full style sheet (global-vars.xslt) that uses it:
  Listing 4. A script that demonstrates the use of dynamic evaluation to display global variables (global-vars.xslt)
  Here is the output that 4XSLT produces from this transform, applied against the labels.xml document:
  As you can see, the result is to display all the global variable names and values. The code that performs this trick is the
  dump-globals template, which I have designed to be fully encapsulated, including the extension namespaces it needs. You can copy this template directly into your own XSLT code to use it, or you can copy it into a standalone XSLT file for import. Just invoke
  <xsl:call-template to use it. It will dump the global variable listing into the output. In Listing 4, I invoke it from the body of an
  xsl:message, so that it appears as the message content. I inserted comments marked by letters in order to more clearly explain the workings of the
  dump-globals template. The following paragraphs explain each lettered section.
  A: I use the standard
  document('') form to retrieve the current style sheet as a source document. I assign the document element of this style sheet to the
  ctde variable, to have ready access to the top-level XSLT elements. Notice that I am careful to use
  xsl:* as the name test for the document element. This is because both
  xsl:stylesheet and
  xsl:transform are legal document element names, and I can't be sure which will be used in any particular script. This template won't work for style sheets that use the literal result element as root form allowed by XSLT, but you can't have truly global variables in such transforms, anyway, so you will not be likely to use the
  dump-globals template.
  B: The
  xsl:for-each loops over top-level variable and parameter elements.
  C: Each variable or parameter element has a
  name attribute. Since I have the variable name, all I have to do is evaluate a variable reference to get its value. I do this by creating an XPath expression on the fly, taking the current variable name and prepending dollar sign,
  $. Now I need to evaluate the resulting string as an XPath expression. This is where the
  dyn:evaluate function comes in. It takes a string and executes it as an XPath expression, returning the result. In this way I get the value from each global variable or parameter, and assign it to
  $value for later use.
  D: After displaying the variable name, this code displays the value. As I mentioned above, it is generally most useful to use
  xsl:copy-of when displaying node sets for informational purposes. When displaying numbers, strings, and booleans, however,
  xsl:value-of is what you want. Since I do not know ahead of time whether each variable value will be a node set or other type of object, I need a way to determine this at run time. Luckily, EXSLT provides another useful function,
  exsl:object-type in the
  common module. This function returns a string that indicates the type of the XPath object that results from evaluating its argument.
  You can take these basic ideas much further. Dynamic XPath expressions and the
  document('') form open up a lot of possibilities for processing tricks, even beyond debugging. Also, EXSLT has many other useful modules and functions you should experiment with. If your favorite XSLT processor does not support EXSLT, be sure to request such support from your vendor. EXSLT support is growing, and Saxon, Xalan, libxslt, jd.xslt, and 4XSLT (part of 4Suite) all support some or all of the EXSLT modules.
  Don't forget that
  xsl:message supports the
  terminate attribute, which, if set to
  yes aborts the style sheet. This provides for a simple way of supporting assertions in XSLT -- that is, you can place checks for unexpected situations into the style sheet and use a terminating message to abort if such situations occur.
  In this article I have demonstrated how to use
  xsl:message for debugging, some general tips and techniques that are handy for debugging tasks, and some of the new possibilities opened up by extending transforms with the EXSLT functions. I imagine all XML developers get to the point at some time or another where they have to haul out an XSLT debugger with all the bells and whistles, but I hope I've helped to reduce the number of times that is necessary.
  - For a good introduction to XSLT, read "Investigating XSLT: The XML transformation language," by LindaMay Patterson (developerWorks, August 2001).
  - Look into EXSLT for useful and widely supported extension functions and elements for XSLT. The common module includes the
  exsl:object-type()function I use in this article. The dynamic module includes the
  dyn:evaluate()function.
  - Check out the W3C's XSL page, which includes many useful links to XSLT-related resources, including the specifications themselves, tutorials, articles, and implementations.
  - If you are not familiar with the literal result element as stylesheet form for XSLT, see the relevant section in the XSLT spec, which offers a simple example. While you are there, you might want to review xsl:message.
  - Be sure to bookmark XSL Frequently Asked Questions, which features many notes that are handy for debugging.
  - See my other XSLT-related tips on developerWorks: "Counting with node sets" (May 2002), "Generating internal HTML links with XSLT" (February 2001), and "XSLT lookup tables" (February 2001).
  - The style sheet processor I use in examples is 4XSLT, part of 4Suite, which I co-develop.
  - Find.