xslt-2.0xslt-3.0

Logic of except in XSLT


This question is just so that I may understand the logic of except when one attempts to avoid certain nodes. So a completely useless example follows, but it illustrates my question.

Why is it that this code

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:math="http://www.w3.org/2005/xpath-functions/math"
    exclude-result-prefixes="xs math"
    expand-text="true"
    version="3.0">
    <xsl:strip-space elements="*" />
    <xsl:mode on-no-match="shallow-copy"/>
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:template match="A[1]">
        <xsl:apply-templates select="/S//A/* except (B, C)" mode="P"/>
    </xsl:template>
    <xsl:template match="*" mode="P">
        <M>{text()}</M>
    </xsl:template>
</xsl:stylesheet>

when run on this xml

<?xml version="1.0" encoding="UTF-8"?>
<S>
    <A>
        <B>X</B>
        <C>Y</C>
    </A>
    <A>
        <B>T</B>
        <C>R</C>
    </A>
</S>

yields this,

<?xml version="1.0" encoding="UTF-8"?>
<S>
   <M>T</M>
   <M>R</M>
   <A>
      <B>T</B>
      <C>R</C>
   </A>
</S>

and this code

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:math="http://www.w3.org/2005/xpath-functions/math"
    exclude-result-prefixes="xs math"
    expand-text="true"
    version="3.0">
    <xsl:strip-space elements="*" />
    <xsl:mode on-no-match="shallow-copy"/>
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:template match="A[1]">
        <xsl:apply-templates select="/S//A/*[not(self::B or self::C)]" mode="P"/>
    </xsl:template>
    <xsl:template match="*" mode="P">
        <M>{text()}</M>
    </xsl:template>
</xsl:stylesheet>

yields this?

<?xml version="1.0" encoding="UTF-8"?>
<S>
   <A>
      <B>T</B>
      <C>R</C>
   </A>
</S>

Shouldn't the result be the same? I would expect the last result from both code examples.


Solution

  • You want <xsl:apply-templates select="/S//A/(* except (B, C))" mode="P"/>, not <xsl:apply-templates select="/S//A/* except (B, C)" mode="P"/>.