22 Arrays

Arrays are defined in the XDM Data Model.

22.1 Array Construction

The instruction xsl:array constructs and returns a new array.

<!-- Category: instruction -->
<xsl:array
  select? = expression
  composite? = boolean >
  <!-- Content: sequence-constructor -->
</xsl:array>

If the composite attribute is omitted or set to no, the resulting array has one singleton member for each item returned by the select attribute or sequence constructor. For example <xsl:array select="1 to 5"/> returns an array with five members: [1, 2, 3, 4, 5].

If the composite attribute is present with the value yes, then each item returned by the select attribute or sequence constructor must be an zero-arity function, and the sequences that result from the evaluation of these zero-arity functions become the members of the array. For example, <xsl:array select="function(){1 to 3}, function(){8 to 10}" composite="yes"/> returns an array with two members: [(1,2,3), (8,9,10)].

The select attribute and the contained sequence constructor are mutually exclusive: if the select attribute is present, then the only permitted child element is xsl:fallback.

For convenience and readability, the instruction xsl:array-member can be used to construct a zero-arity function suitable for use with xsl:array.

<!-- Category: instruction -->
<xsl:array-member
  select? = expression >
  <!-- Content: sequence-constructor -->
</xsl:array-member>

For example:

<xsl:array composite="yes">
  <xsl:for-each select="'jane', 'mary', 'pete', 'andy'">
     <xsl:array-member select="lower-case(.), upper-case(.)"/>
  </xsl:for-each>
</xsl:array>

The result of this instruction is the array [('jane', "JANE"), ('mary', 'MARY'), '('pete', 'PETE'), ('andy', 'ANDY')]: that is, an array with four members, each of which is a sequence of two items.

Although the syntax is designed to be intuitive, the underlying mechanism is non-obvious. The effect of the xsl:array-member instruction is to return a zero-arity anonymous function which, on evaluation, delivers the result of its select attribute or contained sequence constructor. That is, the xsl:array-member instruction in this example is actually equivalent to:

<xsl:sequence select="let $member := (lower-case(.), upper-case(.)) 
                       return function(){$member}"/>              
               

Specifically, the xsl:array-member instruction evaluates its select expression or contained sequence constructor (which are mutually exclusive), to obtain a value V, and returns a zero-arity anonymous function with signature function() as item()*, which when invoked returns V.

Note:

The reason for this rather obscure formulation is to prevent the flattening of nested sequences that would normally occur when instructions within a sequence constructor deliver sequences rather than individual items. Wrapping the individual sequences within anonymous functions prevents this flattening.

More formally, the semantics of the xsl:array instruction are as follows:

  1. When there is no composite attribute, or when composite="no":

    1. The select expression or contained sequence constructor is evaluated, in the same way as for the xsl:sequence instruction, to yield a value V.

    2. An array is constructed, containing one member for each item in V, whose value is that item.

    3. This array is returned as the result of the xsl:array instruction.

  2. When composite="yes" is specified:

    1. The select expression or contained sequence constructor is evaluated, in the same way as for the xsl:sequence instruction, to yield a value V.

    2. A type error is raised if V is not an instance of (function() as item()*)*. [TODO: add error code]

    3. An array is constructed, containing one member for each item $v in V, the value of the array member being $v().

    4. This array is returned as the result of the xsl:array instruction.

The semantics of the xsl:array-member instruction are as follows:

  1. The select expression or contained sequence constructor is evaluated, in the same way as for the xsl:sequence instruction, to yield a value V.

  2. The xsl:array-member instruction returns a zero-arity anonymous function with signature function() as item()*, whose evaluation returns V.

The select attribute and the contained sequence constructor of xsl:array are mutually exclusive [Error condition TBA].

The select attribute and the contained sequence constructor of xsl:array-member are mutually exclusive [Error condition TBA].

Note:

XPath offers two constructs for creating arrays, the so called square and curly array constructors. The square array constructor (for example [1, 3, 5, (7 to 10)] can only construct an array where the number of members is statically known (in this case there are four members). The curly array constructor (for example array{1, 3, 5, (7 to 10)} can only construct an array whose members are singleton items (in this case there are seven members, each being a single integer).

The combination of xsl:array and xsl:array-member, by contrast, can deliver an array whose size is determined dynamically and whose members can be arbitrary XDM values.

An equivalent construct using array functions would be ['jane', 'mary', 'pete', 'andy'] => array:for-each(function($s){lower-case($s), upper-case($s)}).