Processiing arrays in XSLT 4

It seems a no-brainer to provide an XSLT instruction along the lines

<xsl:for-each-member select="array">
  ....
</xsl:for-each>

to process the members of a supplied array.

The question is: within the body of this instruction, how should one refer to the current member of the array?

Recall that a member of an array can be any sequence, not just a single item.

Here are some ideas I have considered. I'm not 100% happy with any of them, and I'd be interested to know what other people think.

With xsl:for-each-group, we bind current-group(), but we also bind the context-item (to the first item in the current group) and position() and last(). Binding the context item (as well as position and last) seems friendly, but the current member of an array might be an empty sequence, and it's not clear how to handle that.

Following precedent suggests a current-member() function, but I'm not keen on adding yet more current-xyz() functions, and it's not clear how we provide current position.

An alternative would be to depart from precedent and bind variables:

<xsl:for-each-member select="array" bind-to="member" position="pos">
   <xsl:if test="$pos ne 1">,</xsl:if>
   <xsl:for-each select="$member">
      ...

That's the way I would do it if it weren't so inconsistent with the way other things are done. Also, many arrays in practice have members that are single items (or perhaps zero-or-one items), and binding "." in those cases seems more intuitive.

Another possibility is to bind "." to a zero-arity function that returns the current member: so to access the current member you write select=".()". Is that just too weird, or would people get used to it? The attraction is that it doesn't involve inventing any new machinery - no new functions, no additions to the dynamic context, and position() and last() work nicely.

Related to this is how array construction works. I'm currently proposing

<xsl:array>
  <xsl:for-each select="1 to 10">
    <xsl:array-member select=". * 2"/>
  </xsl:for-each>
</xsl:array>

To allow this to construct arrays whose members hold multiple items, I'm proposing that "under the good", xsl:array-member actually creates a zero-arity-function containing the value of the array member, so the sequence constructor contained in xsl:array actually returns a sequence of zero-arity functions. Using the same device for both instructions has some merit.

Thoughts?

Michael Kay
Saxonica

Received on Saturday, 9 January 2021 16:38:45 UTC