RE: Arrays in the built-in template rules

I can't remember whether we discussed this in detail on a recent telcon, and I seem to have missed this mail previously. If a decision was made, please disregard.

> 
> From: Michael Kay [mailto:mike@saxonica.com]
> Sent: Saturday, September 12, 2015 7:06 PM
> 
> On reflection, instead of handling arrays identically to functions in the built-in
> template rules, I feel the following causes fewer surprises:
> 
> Text-only-copy
> 
> Apply templates to the members of the array:
> 
> <xsl:template match=“.[. instance of array(*)]" mode="M">
>   <xsl:apply-templates mode="#current” select=“?*"/>
> </xsl:template>

If we do this for arrays, as being a "special kind of maps", I think we should do it for maps as well. Since the same lookup operator is defined for maps, this seems to make sense.

In other words, if we rewrite the template as follows, it is orthogonal with maps and it won't break anything. And if we do the same for shallow-skip/copy we have the added advantage that all of a sudden, applying templates on maps becomes trivial (at least less un-trivial) (remember the awkward example Michael Kay gave some time ago, where we discussed a map-specific syntax for patterns).

The template can become:

<xsl:template match=".[. instance of array(*) or . instance of map(*)]" mode="M">
   <xsl:apply-templates mode="#current” select="?*"/>
</xsl:template>

The only caveat being that "?*" is XP31 syntax, but its equivalent expression is a simple ForExpr, I doubt it will give any practical problems, even if a processor does not support XP31.
 

> 
> Deep-copy
> 
> Same as for nodes, atomic values, functions, etc.
> 
> Shallow-copy
> 
> On balance, I recommend doing the same as for functions and maps, though
> this one is debatable.

I could go either way. On the one hand, it seems to be in line with the text-only copy to copy the items and apply templates to their members, on the other hand, it could be reasoned that a map or an array is a kind of atomic item and should not be split in "children" and "parent" relations.

>From a usability standpoint, it seems appropriate to let it behave as follows:

<!-- maps -->
<xsl:template match=".[. instance of map(*)]" mode="M">
    <xsl:map>
        <xsl:apply-templates mode="#current" select="?*"/>
    </xsl:map>
</xsl:template>

<!-- arrays -->
<xsl:template match=".[. instance of array(*)]" mode="M">
    <xsl:variable name="array" as="item()*">
        <xsl:apply-templates mode="#current" select="?*"/>
    </xsl:variable>
    <xsl:sequence select="array { $array }" />
</xsl:template> 

The fact that we need to use a variable here is unfortunate, as it will put the output state into temporary output state, which may limit certain actions. But since these are "virtual" behaviors, I guess that's just a matter of definition.

> 
> Deep-skip
> 
> Same as for functions and maps.
> 
> Shallow skip
> 
> As for text-only-copy: apply templates to the members of the array.

If we do this for shallow-skip, then its counter-part shallow-copy should also behave such that it applies templates to the members. And if possible, we should let maps and arrays behave the same way for usability, orthogonality and (hopefully) least-surprise.

I assume that the template will then be the same as for text-only copy:

<xsl:template match=".[. instance of array(*) or . instance of map(*)]" mode="M">
   <xsl:apply-templates mode="#current" select="?*"/>
</xsl:template>


> 
> Fail
> 
> Like everything else, raise an error.
> 
> Michael Kay
> Saxonica

Received on Wednesday, 23 September 2015 17:41:00 UTC