How Do Maps and Arrays Work in XSLT 3.0?

XSLT 3.0 fundamentally expands the language beyond node trees and atomic sequences by introducing maps and arrays as first-class items. As first-class data structures, they can be stored in variables, passed into functions and templates, returned as results, and manipulated without serializing back into XML. This modern functional model bridges the gap between XML and JSON processing, enabling developers to build flexible, high-performance transformations for nested, heterogeneous, and non-XML datasets.

The First-Class Status of Maps and Arrays

In earlier versions of XSLT, sequences served as the only collection mechanism. However, standard sequences in XPath flatten automatically—a sequence of sequences simply becomes one flat sequence. This design prevented the nesting of multi-dimensional data structures.

With XPath 3.1 and XSLT 3.0, maps and arrays are treated as distinct item types that belong to the item() hierarchy. Because an array or map is a single item, putting an array inside another array does not cause flattening.

Maps and arrays benefit from complete first-class support:

Working with Maps

A map in XSLT 3.0 is a collection of key-value pairs where keys are atomic values and values are arbitrary sequences.

Creation and Syntax

Maps can be constructed using literal syntax or constructor functions:

<!-- Literal Map Constructor -->
<xsl:variable name="user" select="map{
    'id': 101,
    'name': 'Alice',
    'roles': ('admin', 'editor')
}" />

<!-- Function-based Map Constructor -->
<xsl:variable name="scores" select="map:merge((
    map:entry('math', 95),
    map:entry('science', 88)
))" />

Accessing Map Data

Maps function syntactically as functions that take a key and return the associated value. You can also use explicit functions or the lookup operator (?):

<!-- Function-call syntax -->
<xsl:value-of select="$user('name')" />

<!-- Lookup operator syntax -->
<xsl:value-of select="$user?name" />

<!-- Standard library function -->
<xsl:value-of select="map:get($user, 'roles')" />

Map Immutability

All map operations are purely functional and immutable. Functions like map:put() and map:remove() do not modify the original map in place; they return a new map reflecting the changes:

<xsl:variable name="updatedUser" select="map:put($user, 'status', 'active')" />

Working with Arrays

An array is an ordered list of zero or more members where each member can be an arbitrary sequence (including empty sequences or nested collections). Unlike standard sequences, arrays preserve internal nesting.

Creation and Syntax

Arrays use square brackets [...] for composite constructors or curly braces array { ... } for flattening constructors:

<!-- Square bracket constructor (preserves internal sequences as single members) -->
<xsl:variable name="matrix" select="[ [1, 2], [3, 4] ]" />

<!-- Flattening constructor (evaluates the expression and turns each item into a member) -->
<xsl:variable name="items" select="array { //book/@id }" />

Accessing Array Members

Array indices are 1-based. Like maps, arrays act as functions that accept an integer index:

<!-- Function-call invocation -->
<xsl:value-of select="$matrix(1)(2)" /> <!-- Returns 2 -->

<!-- Lookup operator -->
<xsl:value-of select="$matrix?1?2" />

<!-- Unwrapping all members into a sequence -->
<xsl:sequence select="$matrix?*" />

Array Manipulation

Functions in the array: namespace allow functional additions, deletions, and transformations:

JSON Integration and Modern Data Processing

The inclusion of first-class maps and arrays enables bidirectional JSON processing without external libraries:

Through these structures, XSLT 3.0 serves as a full-featured data transformation engine capable of handling mixed XML, JSON, and in-memory key-value workflows efficiently.