Search code examples
xmlxsltxslt-2.0

Why text() is matched by XSL template in non-#default mode?


This is my XML:

<?xml version="1.0" encoding="utf-8" ?>
<x>
  <y>test</y>
</x>

This is XSL:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:template match="/x">
    <xsl:copy>
      <xsl:apply-templates select="//y" mode="foo"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="node()|@*" mode="#default">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

I expect this output, because the second template should be reached for the <y/> element:

<x/>

However, I'm getting:

<x>test</x>

Why?


Solution

  • You do not have a template matching y in mode foo. Therefore it is processed by the built-in template rule of:

    <xsl:apply-templates mode="#current">
    

    and its child text node by:

    <xsl:value-of select="string(.)"/>