Burst-mode streaming

Burst-mode streaming takes a streamed document as input, and generates a sequence of small subtrees containing the parts of the document that need to be processed. This can be achieved using XSLT 3.0 syntax like this:

<xsl:stream href="employees.xml"> <xsl:apply-templates select="*/employee/copy-of(.)"/> </xsl:stream>

The code that processes an individual employee element does not need to be streamable; it can use any XSLT constructs. The only constraint is that it cannot navigate outside the employee element: because the employee element is a copy of a subtree from the orginal document, it has no parent or siblings.

Burst-mode streaming can also be applied to the principal input of the transformation. This works if the transformation is run from the command line, and also if it is executed from a Java or .NET API provided that the document is supplied as a streamed source object, not as a pre-built tree (under Java, this means a StreamSource or SAXSource). For example:

<xsl:mode streamable="yes"/> <xsl:template match="/"> <xsl:apply-templates select="*/employee/copy-of(.)"/> </xsl:template>

The same effect can be achieved in XQuery if the document is supplied as the initial context item, again in the form of a streamed input source. Although the functions copy-of() and snapshot() are defined in the XSLT 3.0 specification, Saxon also makes them available in XQuery, allowing for example:

*/employee ! copy-of(.)/(name, address)

In XQuery there is no need for the query itself to indicate that streamed execution is required; rather this can be requested from the command line using the option -stream:on.

The same effect can be achieved on external streamed documents using the saxon:stream extension function.

Example: selective copying

A very simple way of using burst mode streaming is when making a selective copy of parts of a document. For example, the following code creates an output document containing all the footnote elements from the source document that have the attribute @type='endnote':

XSLT example (named document)

<xsl:template name="main"> <footnotes> <xsl:stream href="thesis.xml"> <xsl:copy-of select=".//footnote[@type='endnote'])"/> </xsl:stream> </footnotes> </xsl:template>

XQuery example (named document)

<footnotes>{ saxon:stream(doc('thesis.xml')//footnote[@type='endnote']) }</footnotes>

XSLT example (principal input document)

<xsl:mode streamable="yes"/> <xsl:template match="/"> <footnotes> <xsl:copy-of select=".//footnote[@type='endnote'])"/> </footnotes> </xsl:template>

XQuery example (principal input document)

<footnotes>{.//footnote[@type='endnote']}</footnotes>

These examples work because the predicate (the expression in square brackets) is motionless - evaluating the predicate does not require the source document to be repositioned. If the predicate needs access to child elements rather than attributes, it's necessary to make a copy of each footnote and then test the copy. The last example then becomes:

<footnotes>{.//footnote/copy-of(.)[type='endnote']}</footnotes>