Sponsored

XSLT Reference

xsl:stream

XSLT 3.0 element

Processes a source document in streaming mode without loading it fully into memory, enabling transformation of arbitrarily large XML files.

Syntax
<xsl:stream href="uri">...</xsl:stream>

Description

xsl:stream is the gateway to XSLT 3.0 streaming. Instead of loading the entire source document into memory as a tree, the processor reads it as a sequential stream of events (similar to SAX). This makes it possible to process XML files of any size — gigabytes of log data, large export files, huge datasets — without running out of memory.

The href attribute specifies the URI of the document to stream. The content of xsl:stream is a sequence constructor that is evaluated in streaming mode. The context item within the constructor is the document node of the streamed document.

Streaming imposes important restrictions. You can only make one downward pass through each node. You cannot navigate upward (to the parent or document node after descending) or reference a node more than once. Templates called from within a streaming context must themselves be streamable. xsl:accumulator is the primary mechanism for gathering state as nodes stream past.

xsl:stream is a top-level instruction typically placed inside a template matching / or invoked from an initial template. It is supported by processors that declare streaming support (Saxon EE, for example). Processors that do not support streaming treat xsl:stream as an error unless the [XTSE3430] fallback is handled.

Attributes

AttributeTypeRequiredDescription
hrefURIYesThe URI of the document to process in streaming mode.

Examples

Count elements in a large document without loading it

Stylesheet:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xsl:output method="xml" indent="yes"/>

  <xsl:param name="source-uri" select="'large-log.xml'"/>

  <xsl:template name="xsl:initial-template">
    <xsl:stream href="{$source-uri}">
      <result>
        <count>
          <xsl:value-of select="count(//entry)"/>
        </count>
      </result>
    </xsl:stream>
  </xsl:template>
</xsl:stylesheet>

Streaming with an accumulator to track totals

Stylesheet:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xsl:output method="xml" indent="yes"/>

  <!-- Accumulator tracks running total of order amounts -->
  <xsl:accumulator name="total-sales" as="xs:decimal"
    initial-value="0" streamable="yes">
    <xsl:accumulator-rule match="order" phase="end"
      select="$value + xs:decimal(@amount)"/>
  </xsl:accumulator>

  <xsl:param name="orders-uri" select="'orders.xml'"/>

  <xsl:template name="xsl:initial-template">
    <xsl:stream href="{$orders-uri}" use-accumulators="total-sales">
      <xsl:mode streamable="yes" use-accumulators="total-sales"/>
      <xsl:apply-templates select="." mode="#unnamed"/>
    </xsl:stream>
  </xsl:template>

  <xsl:template match="/" mode="#unnamed">
    <summary>
      <total-sales>
        <xsl:value-of select="accumulator-after('total-sales')"/>
      </total-sales>
    </summary>
  </xsl:template>
</xsl:stylesheet>

Notes

  • Streaming requires processor support; not all XSLT 3.0 processors implement it. Saxon EE supports full streaming.
  • Within xsl:stream, expressions must follow streamability rules: no upward axes after descending, no multiple passes over a node.
  • Use xsl:fork inside xsl:stream to process the stream in multiple independent branches in a single pass.
  • xsl:stream cannot appear inside a template or function — it must be a direct call from an initial template or a template with a streaming-compatible context.

See also