Sponsored

XSLT Reference

array:flatten()

XSLT 3.0 array function

Recursively flattens nested arrays into a single flat sequence of atomic items and nodes.

Syntax
array:flatten(items)

Description

array:flatten() takes a sequence of items that may contain arrays—including arrays nested inside arrays—and returns a flat sequence in which every array has been dissolved. Non-array items (strings, integers, nodes, maps, etc.) pass through unchanged; only array wrappers are removed.

The recursion is unbounded: a three-level-deep nesting such as [[1, [2, 3]], [4]] is fully flattened to (1, 2, 3, 4). This makes array:flatten() useful when assembling arrays incrementally or when consuming data structures of unknown depth.

Note that the result is a sequence, not an array. Wrap it in array:join() if an array is required.

Parameters

ParameterTypeRequiredDescription
itemsitem()*YesA sequence of items, which may include arrays at any depth of nesting.

Return value

item()* — a flat sequence with all array wrappers removed. Maps are not unwrapped; only arrays are affected.

Examples

Flattening nested integer arrays

Input XML:

<?xml version="1.0" encoding="UTF-8"?>
<data/>

Stylesheet:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:array="http://www.w3.org/2005/xpath-functions/array">

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/">
    <xsl:variable name="nested" select="[[1, 2], [3, [4, 5]], [6]]"/>
    <xsl:variable name="flat" select="array:flatten($nested)"/>
    <result>
      <flat><xsl:value-of select="$flat" separator=", "/></flat>
      <sum><xsl:value-of select="sum($flat)"/></sum>
    </result>
  </xsl:template>
</xsl:stylesheet>

Output:

<result>
  <flat>1, 2, 3, 4, 5, 6</flat>
  <sum>21</sum>
</result>

Normalising a heterogeneous collection before processing

Input XML:

<?xml version="1.0" encoding="UTF-8"?>
<catalog>
  <group id="A">
    <item>alpha</item>
    <item>beta</item>
  </group>
  <group id="B">
    <item>gamma</item>
  </group>
</catalog>

Stylesheet:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:array="http://www.w3.org/2005/xpath-functions/array">

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/catalog">
    <!-- Build one sub-array per group, then wrap them all -->
    <xsl:variable name="groups"
      select="array:join(for $g in group return [array:join(for $i in $g/item return [$i])])"/>
    <!-- Flatten the two-level structure into a single sequence -->
    <xsl:variable name="all" select="array:flatten($groups)"/>
    <items count="{count($all)}">
      <xsl:for-each select="$all">
        <item><xsl:value-of select="."/></item>
      </xsl:for-each>
    </items>
  </xsl:template>
</xsl:stylesheet>

Output:

<items count="3">
  <item>alpha</item>
  <item>beta</item>
  <item>gamma</item>
</items>

Notes

  • Only arrays are unwrapped. Maps, even though they are also XDM structured types, are left intact.
  • The function accepts a plain sequence as its argument, not only an array. Items in the sequence that are not arrays pass through unchanged.
  • Members that are sequences (e.g. a member holding (1, 2)) remain as sequences inside the result because they are not themselves arrays.
  • To convert the resulting sequence back into an array, use array:join() with individual wrapping: array:join(for $x in array:flatten($arr) return [$x]).

See also