Colin Mackenzie
Colin Mackenzie

Reputation: 81

Should an XSLT3 unnamed xsl:mode on-no-match behaviour be applied to an element that has no mode matched but a mode is specified on apply-templates?

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?

Upvotes: 2

Views: 1072

Answers (2)

Michael Kay
Michael Kay

Reputation: 163458

"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.

Upvotes: 3

Martin Honnen
Martin Honnen

Reputation: 167696

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

Upvotes: 1

Related Questions