Skip to content

Modes

Modes allow a node to be processed differently depending on context. Templates declare which mode they belong to, and xsl:apply-templates specifies which mode to use.

Declaring modes

<xsl:mode on-no-match="shallow-copy"/>
<xsl:mode name="toc" on-no-match="text-only-copy"/>

on-no-match

Controls what happens when no user-defined template matches a node:

Value Behavior
text-only-copy (default) Copies text nodes, applies templates to element children. Elements themselves are not copied.
shallow-copy Copies the node (element, attribute, text, comment, PI), then applies templates to attributes and children of elements. This is the identity transform.

Using modes

<!-- Default mode -->
<xsl:template match="chapter">
  <div><xsl:apply-templates/></div>
</xsl:template>

<!-- Named mode for table of contents -->
<xsl:template match="chapter" mode="toc">
  <li><xsl:value-of select="title"/></li>
</xsl:template>

<xsl:apply-templates select="chapter" mode="toc"/>

Shallow copy (identity transform)

The on-no-match="shallow-copy" mode is useful when you want to pass most of the input through unchanged and only modify specific elements:

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:mode on-no-match="shallow-copy"/>

  <!-- Only override what you need to change -->
  <xsl:template match="price">
    <price currency="EUR"><xsl:value-of select=". * 0.92"/></price>
  </xsl:template>

</xsl:stylesheet>

This replaces the verbose XSLT 1.0 identity template pattern:

<!-- No longer needed with on-no-match="shallow-copy" -->
<xsl:template match="@* | node()">
  <xsl:copy>
    <xsl:apply-templates select="@* | node()"/>
  </xsl:copy>
</xsl:template>