xmlxsltapply-templates

XSLT 'apply-templates' and 'apply-templates with mode' in a single go


I am trying to use apply-templates and apply-templates with mode like explained in the below example:

My input xml looks like:

<catalog>
<product dept="aaa">
    <number>111</number>
    <name>cap</name>
    <color>blue</color>
</product>
<product dept="bbb">
    <number>222</number>
    <name>bat</name>
    <color>white</color>
</product>
<product dept="ccc">
    <number>333</number>
    <name>bag</name>
    <color>red</color>
</product>

Now I am trying with the below shown xslt to remove the product element with dept=bbb but it doesn't work. The same input xml appears in the output. I know I can achieve my desired result by removing the mode attribute on the last template but I am trying to understand why it doesn't work in the way I'm trying here.

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common" version="1.0" exclude-result-prefixes="exsl">
  <xsl:template match="/">
    <xsl:variable name="modXml">
      <xsl:apply-templates />
      <xsl:apply-templates mode="remove" />
    </xsl:variable>
    <xsl:copy-of select="exsl:node-set($modXml)/*" />
  </xsl:template>
  <xsl:template match="node( ) | @*">
    <xsl:copy>
      <xsl:apply-templates select="@*" />
      <xsl:apply-templates />
    </xsl:copy>
  </xsl:template>
  <xsl:template match="/catalog/product[@dept='bbb']" mode="remove" />
</xsl:stylesheet>

Can someone please explain how the XSLT processor is running the transformation here..?

Thanks a lot..!


Solution

  • Here:

    <xsl:variable name="modXml">
          <xsl:apply-templates />
          <xsl:apply-templates mode="remove" />
    </xsl:variable>
    

    When you do the first:

    <xsl:apply-templates />
    

    you are applying the identity transform template to all nodes (recursively) in the document. Once this is done, the variable already contains a copy of the entire document. Nothing you will do from this point on will change that.

    Then, when you do:

    <xsl:apply-templates mode="remove" />
    

    you are adding to the variable's existing result-tree-fragment. As it happens, the template applied does not actually add anything - but neither does it remove anything from the already existing result. There is no way to do so.