---
title: "XSLT 3.0 new features: what changed from 2.0"
description: "A practical guide to XSLT 3.0 features including streaming, maps, arrays, and JSON support. What to adopt and why."
date: 2025-02-10T00:00:00Z
tags: ["xslt3", "saxon", "xslt2"]
---
XSLT 3.0 is a significant step beyond 2.0. If you are running Saxon on the backend — as XSLT Playground does — you have access to the full 3.0 feature set today. This post covers the additions that matter most in practice and shows how to try each one directly in the playground.
## Streaming
The most impactful change in 3.0 is streaming. In earlier versions, the processor loads the entire source document into memory before any template can run. With 3.0 streaming, selected templates can consume the document as a stream, which drastically reduces memory usage for large inputs.
To enable streaming, declare it on the stylesheet and on the mode:
```xml
```
Not every expression is streamable. Saxon will tell you at compile time if a pattern is not compatible. The key restriction is that you can only visit each node once — no backward axes, no variables that hold nodes for later inspection.
## Maps and arrays
XSLT 3.0 adds maps and arrays as first-class values, borrowed from XPath 3.1. A map is a collection of key-value pairs; an array is an ordered sequence that can hold any value including other maps or arrays.
```xml
```
Arrays work similarly:
```xml
```
Arrays use 1-based indexing. Use `array:size()`, `array:get()`, and `array:append()` from the array namespace for common operations.
## JSON input and output
XSLT 3.0 can parse and produce JSON natively via `json-to-xml()` and `xml-to-json()`. This eliminates the need for a pre-processing step when your source is JSON.
```xml
```
The function converts JSON into a predictable XML representation defined by the W3C. Objects become `