« A Wii AdventureWho The Hell Is Mo Henry? »

Remember the XSL Default Rule

05/25/07

  02:21:16 pm, by Nimble   , 494 words  
Categories: Thoughts, Programming

Remember the XSL Default Rule

XSL or Extensible Stylesheet Language can be a bit mind-bending. I have essentially come up to speed on it in a week to use it in the generation of migration scripts. It is essentially a big list of rules, calls and writing commands for matching XML. It can seem a bit "backwards" to normal programming, but you can figure it out.

Starting with...

<?xml-stylesheet?>
<xsl:stylesheet
version='1.0'
xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
<xsl:template match="/">
</xsl:template>
<!-- Do stuff here -->
</xsl:stylesheet>

...can give you a pretty good start in playing around with XSL, since that template matches the root of the XML file, and you can then apply-templates or call-template... or even just say "screw that" and put in text instead:

<xsl:text>Meaningless drivel</xsl:text>

Things were going along nicely, but when I stopped to look at the output, there were things in the output that I had not specified. Instead of FIELD1,FIELD2, I got DETAIL1DETAIL2DETAIL3DETAIL4FIELD1,FIELD2.

I was most confused, because I was using the mode keyword to make sure to just apply templates with a matching mode, e.g.

<xsl:apply-templates select="node()" mode="list-fields"/>

This matches templates like:

<xsl:template match="Field" mode="list-fields">

but would not match an equivalent template without a mode:

<xsl:template match="Field">

(or with a different mode, it goes without saying)

I took a hard look for any mode="list-fields" and came up empty. I started stripping out includes and paring down the functionality, and still I got those extra details.

Now select="node()" essentially means "process all of my children". This is the default if you leave the select clause out of apply-templates entirely.

What I did not know, not being an XSL maven, is that there is a default rule in XSL, and that is to say that if there is no template match, just spit out the text!

I could understand that more if the rule applied when you leave out the mode, but having a specific mode seems like the default rule ought not to match. Well, fair enough.

You can override the default rule (there are other ways to do this) like so:

<xsl:template match="text()"/>

This matches the text in between XML tags, e.g. <DETAIL>Employees</DETAIL>.

However, as I found out, it appears that you have to override this default rule separately for each mode as well, e.g.

<xsl:template match="text()" mode="list-fields"/>

A relatively thorough search on the topic did not turn up any better ways of handling this, but they might exist.

So if you find yourself making XSL transformations, and you get mysterious other bits of the XML text contents making its way into your output, remember the default rule.

No feedback yet