2

This questions is simpler to describe by example rather than as text.

With the following XML

<?xml version="1.0" encoding="UTF-8"?>
<tests>
    <test>1</test>
    <test>2</test>
</tests>

If I run the following XSLT3

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

    <xsl:output method="xml" />
    <xsl:mode on-no-match="shallow-copy" />
    <!--<xsl:mode name="test" on-no-match="shallow-copy"/>-->

    <xsl:template match="/">
        <mytests>
            <xsl:apply-templates/>
            <xsl:apply-templates mode="test"/>
        </mytests>
    </xsl:template>

    <xsl:template match="tests" mode="test">
        <modetest>
            <xsl:apply-templates mode="#current"/>
        </modetest>
    </xsl:template>
</xsl:stylesheet>

I get following output in Saxon 9

<?xml version="1.0" encoding="UTF-8"?>
<mytests>
    <tests>
        <test>1</test>
        <test>2</test>
    </tests>
    <modetest>
            1
            2
    </modetest>
</mytests>

You can see that when the mode "test" is being used we do not get the test element being output, only that elements content. There is not template for the element "test" with a mode of "test".

I would have guessed that as there is no match the on-no-match="shallow-copy" would have kicked in from the xsl:mode with no name attribute? My guess was that a no named xsl:mode would apply to all no matches even if a mode was is in effect (unless another xsl:mode is defined with a name that matches the current mode). If you uncomment the xsl:mode name="test" on-no-match="shallow-copy" then everything works as expected (so no workaround required thanks) but this means that in an XSLT with lots and lots of modes in apply-templates, I need to define lots and lots of named xsl:modes just to get the identity template behavior.

Can anyone point out if I am doing something wrong or if this is behaving as per the w3C specification?

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62

2 Answers2

3

"My guess was that a no named xsl:mode would apply to all no matches even if a mode was is in effect"

Sorry, your guess would be wrong. Think of it this way: there is a mode whose name is #unnamed, and any xsl:template, xsl:apply-templates, or xsl:mode element with no @mode attribute defaults to mode="#unnamed". (That's an approximation, it gets more complicated when default-mode is specified, but that's the basic concept.)

There's no way of defining the properties of lots of modes "in bulk", you need one xsl:mode declaration per mode.

Michael Kay
  • 156,231
  • 11
  • 92
  • 164
1

The default, built-in processing for any mode is text-only-copy, see https://www.w3.org/TR/xslt-30/#modes "If a mode name is used (for example in an xsl:template declaration or an xsl:apply-templates instruction) and no declaration of that mode appears in the stylesheet, the mode is implicitly declared with default properties" and https://www.w3.org/TR/xslt-30/#built-in-rule

There are six sets of built-in template rules available. The set that is chosen is a property of the mode selected by the xsl:apply-templates instruction. This property is set using the on-no-match attribute of the xsl:mode declaration, which takes one of the six values deep-copy, shallow-copy, deep-skip, shallow-skip, text-only-copy, or fail, the default being text-only-copy.

The built-in default processing in XSLT 2 or 1 it not different.

If having to declare the identity transformation separately with separate xsl:mode declarations appears to be too cumbersome, you can of course also write a template

<xsl:template match="@* | node()" mode="#all">
   <xsl:copy>
      <xsl:apply-templates select="@*" mode="#current"/>
      <xsl:apply-templates mode="#current"/>
   </xsl:copy>
</xsl:template>

https://www.w3.org/TR/xslt-30/#using-modes

Martin Honnen
  • 160,499
  • 6
  • 90
  • 110
  • Thanks Martin. Understood. I have used such "all modes" identity transforms in the past, I was just attempting to stop having to do that using the XSLT3 feature. In my particular use case I have lots of modes. – Colin Mackenzie Jan 14 '20 at 14:46
  • In my understanding there is no declarative, single `xsl:mode` for several modes. Let's wait what Michael Kay is going to say (if Saxonica is not too busy with Saxon-JS 2 :)). – Martin Honnen Jan 14 '20 at 16:18