Re: [xsl] XSLT 4 xsl:with

Subject: Re: [xsl] XSLT 4 xsl:with
From: "Imsieke, Gerrit, le-tex gerrit.imsieke@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Tue, 19 May 2020 14:29:10 -0000
Maybe we don't need a new instruction for switching context. We could re-use the @context-item attribute that already is allowed on xsl:evaluate. If used on a non-xsl element, the attribute will become @xsl:context-item.

A contrived example follows.

Consider this variable:

<xsl:variable name="baz" as="element(baz)">
  <baz>
    <bar>
      <foo n="1"/>
      <foo n="2"/>
    </bar>
  </baz>
</xsl:variable>

Then a template might create this output tree:

<xsl:for-each select="$baz/bar">
  <td>
    Count of foo elements in {path()}:
    <xsl:value-of select="count(foo)"/>
  </td>
</xsl:for-each>

(The stylesheet author preferred to switch context to $baz/bar in order to "simplify" expressions.)

With @xsl:context-item, this can be written as:

<td xsl:context-item="$baz/bar">
  Count of foo elements in {path()}:
  <xsl:value-of select="count(foo)"/>
</td>

or in an xsl:message:

<xsl:message context-item="$baz/bar">
  Count of foo elements in {path()}:
  <xsl:value-of select="count(foo)"/>
</xsl:message>

On elements such as xsl:for-each and xsl:copy, @context-item will have the same semantics as the existing @select attribute. Therefore it need not be allowed on these elements. (Maybe xsl:copy/@select would have better been named @context-item in the first place.)

Another example with xsl:choose:

<xsl:choose context-item="$baz/bar">
  <xsl:when test="count(foo) = 2">...</xsl:when>
  <xsl:otherwise>...</xsl:otherwise>
</xsl:choose>

This one combines @context-item with the @select attribute on xsl:when, as proposed by Michael Kay at this year's XML Prague:

<xsl:choose>
  <xsl:when context-item="$baz/bar"
    test="count(foo) = 2" select="'two'"/>
  <xsl:when test="count($baz/bar/foo) = 1">
    <xsl:sequence select="'one'"/>
  </xsl:when>
  <xsl:otherwise>...</xsl:otherwise>
</xsl:choose>

I'm not sure though whether all occasions on which people use xsl:for-each merely to switch context can be substituted with this context-item attribute.

Sometimes the xsl:for-each instruction will comprise many result tree elements or XSLT instructions. Then there is no single element to stick the @context-item attribute onto.

The common case of one or more xsl:variable declarations in the new context can be replaced by not switching context, but instead by declaring the variables or the first variable with a @context-item:

<xsl:variable name="count" as="xs:integer" select="count(foo)" context-item="$baz/bar"/>
<xsl:variable name="is-positive" as="xs:boolean" select="$count gt 0"/>


(Don't tell me that I don't need all these variables; this is a contrived example.)

-- Gerrit


On 19.05.2020 14:00, Graydon graydon@xxxxxxxxx wrote:
On Tue, May 19, 2020 at 08:53:54AM -0000, Pieter Masereeuw pieter@xxxxxxxxxxxx scripsit:
I would be very happy if I could make my intentions clearer by using a real
XSLT construct in this situation, such as *<xsl:with select="...">*. The
semantics could also help as an assertion that, indeed, the selection has
exactly length 1.

Despite a certain mad temptation to xsl:each-with, I think this might be better as xsl:with-context.

I agree that the clarity would be an improvement.  I wouldn't want to
see it force a single member sequence on the select, though.

-- Graydon

Current Thread