Disabling Default XSLT Templates

XSLT No Comments »

As XSLT developers quickly learn, the W3C XSLT Recommendation requires for all XSLT processors to implement a number of built-in rules. Per the spec, these are the built-in rules:

<xsl:template match="* | /">
  <xsl:apply-templates />
</xsl:template>

All XML elements apply child templates recursively

<xsl:template match="* | /" mode="m">
  <xsl:apply-templates mode="m" />
</xsl:template>

All XML elements apply child templates recursively for every processing mode m

<xsl:template match="text() | @*">
  <xsl:value-of select="." />
</xsl:template>

All text nodes and attributes return the value of their contents

<xsl:template match="processing-instruction() | comment()" />

All comments and processing instructions are ignored

The net effect of these implicit rules is that an XSLT stylesheet without any templates defined will simply return the string values of all child elements in the XML document concatenated together. Attribute values are ignored because <xsl:apply-templates /> only applies to child elements and text nodes, not attribute nodes.

There are many instances where these default templates are useful, but I often find they mask bugs in my stylesheet (e.g. when I mistype a template match expression). Instead, I usually prefer that the stylesheet fails if it comes across an unanticipated XML element (hopefully loudly). I use the following XSLT fragment to achieve this behavior:

<xsl:template match="*">
  <xsl:message terminate="yes">
    <xsl:text>ERROR: Unhandled XML element: </xsl:text>
    <xsl:value-of select="name(.)" />
  </xsl:message>
</xsl:template>

When I desire the default apply-templates behavior, I add an explicit handler:

<!-- Enable default apply-templates behavior for these elements -->
<xsl:template match="/a/b/c | /a/d/e | ...">
  <xsl:apply-templates />
</xsl:template>
WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS Log in