[xsl] Clarifying mode and built-in template usage

Subject: [xsl] Clarifying mode and built-in template usage
From: "Bjorndahl, Brad" <brad.bjorndahl@xxxxxxxxxxxxxxxx>
Date: Thu, 14 Jun 2007 15:52:18 -0400
I was surprised by XSLT 2.0 processing behaviour when applying templates
with modes.

Test XML is:
<?xml version='1.0'?>
<top>
  <A>Contents of element A</A>
  <B>Contents of element B</B>
  <C>Contents of element C</C>
</top>

The test transform is:
<?xml version='1.0'?>
<xsl:transform version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; >

  <xsl:output method="text"/>

  <xsl:template match="/">
    <xsl:text>
Apply templates with default mode</xsl:text>
    <xsl:apply-templates />
    <xsl:text>
Apply templates with mode M1</xsl:text>
    <xsl:apply-templates mode="M1" />
    <xsl:text>
Apply templates with mode M2</xsl:text>
    <xsl:apply-templates mode="M2" />
    <xsl:text>
Apply templates with mode M3</xsl:text>
    <xsl:apply-templates mode="M3" />
  </xsl:template>

  <xsl:template match="top">
    <xsl:apply-templates mode="#current" />
  </xsl:template>
  <xsl:template match="top" mode="M1">
    <xsl:apply-templates mode="#current" />
  </xsl:template>
  <xsl:template match="top" mode="M2">
    <xsl:apply-templates mode="#default" />
  </xsl:template>
  <xsl:template match="top" mode="M3">
    <xsl:apply-templates mode="#current" />
    <xsl:text>End of output.</xsl:text>
  </xsl:template>

  <xsl:template match="*" >
    default <xsl:value-of select="." />
  </xsl:template>
  <xsl:template match="*" mode="M1" >
    M1 <xsl:value-of select="." />
  </xsl:template>
  <xsl:template match="*" mode="M2" >
    M2 <xsl:value-of select="." />
  </xsl:template>
</xsl:transform>

The output is:

Apply templates with default mode

    default Contents of element A

    default Contents of element B

    default Contents of element C

Apply templates with mode M1

    M1 Contents of element A

    M1 Contents of element B

    M1 Contents of element C

Apply templates with mode M2

    default Contents of element A

    default Contents of element B

    default Contents of element C

Apply templates with mode M3
  Contents of element A
  Contents of element B
  Contents of element C
End of output.

The output looks correct to me except the last block for mode M3.
Apparently the built-in template for "*" was used for processing in mode
M3, which does not exist.

I thought the "*" template with no mode attribute would be used because
it would override the built-in template.
In the specs in 6.6 Built-in Template Rules: "The built-in template
rules apply to all modes." so I guess that is the reason.

Still, I think this is a subtle point worth mentioning because it can
cause hairloss.

Brad.

Current Thread