How Does collection() Work in XSLT 2.0?
In XSLT 2.0, the collection() function serves as a
standardized mechanism to query, aggregate, and process multiple XML
documents simultaneously within a single transformation. While XSLT 1.0
relied primarily on the document() function to load files
one by one or through explicit URI node-sets, collection()
returns an arbitrary sequence of document nodes from a URI-identified
source or an implementation-defined default environment. This allows
stylesheets to treat an entire directory, a database collection, or a
designated list of XML resources as a unified dataset that can be
filtered, sorted, and transformed using standard XPath 2.0
expressions.
Core Purpose and Syntax
The standard XPath and XSLT function signature is
collection() or
collection($uri as xs:string?). Calling the function
without arguments accesses the processor's default collection of
documents. When supplied with a URI string argument, the function
resolves that URI against the base URI of the static context and returns
a sequence of document nodes.
Unlike the doc() function, which resolves a single
document, collection() abstracts the multi-document
retrieval process. It outputs a flat sequence
(document-node()*), enabling developers to apply path
expressions across many files in parallel without manual recursion or
external drivers.
Common Use Cases and Patterns
The primary use cases for collection() involve
aggregation, batch processing, and global search across distinct XML
documents.
- Multi-File Aggregation: Merging scattered data points—such as monthly sales reports or chapter files of a book—into a single unified document or master index.
- Batch Reporting and Filtering: Querying hundreds of XML records to extract only those elements meeting specific criteria, such as all records updated after a certain date.
- Cross-Document Keying: Building lookups and indexes across multiple auxiliary files to enrich a primary document during transformation.
A typical pattern involves assigning the retrieved sequence to a
variable and then using for-each or template matching to
iterate through each document:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:template match="/">
<master-catalog>
<xsl:for-each select="collection('file:///data/catalogs?select=*.xml')//item">
<xsl:copy-of select="."/>
</xsl:for-each>
</master-catalog>
</xsl:template>
</xsl:stylesheet>Processor-Specific URI Resolution
The W3C XSLT 2.0 and XPath 2.0 specifications define the semantics of
collection(), but the exact syntax of the URI string
argument depends heavily on the underlying XSLT processor.
In processors like Saxon, the URI parameter often supports custom
query parameters to locate files on a filesystem. For example,
collection('dir/?select=*.xml;recurse=yes') instructs the
engine to recursively scan a folder for all XML documents. Other XML
engines or native XML databases (such as BaseX or eXist-db) map
collection URIs to specific database collections or catalog catalogs
registered via an XML Catalog resolver.
Differences Between doc(), document(), and collection()
Understanding when to use collection() requires
contrasting it with its related functions:
doc($uri): Introduced in XSLT/XPath 2.0, this function takes a single URI string and returns exactly one document node or an error if the document cannot be retrieved.document($uri-sequence, $base-node?): Carried over from XSLT 1.0 for backward compatibility, it accepts a sequence of URIs or nodes and resolves each individually relative to an optional base node.collection($uri?): Retrieves an open-ended sequence of zero or more document nodes from a collection identifier, abstracting file system queries or database sets into a single call.
By decoupling the stylesheet logic from the exact number of incoming
files, the collection() function provides a scalable and
declarative approach to multi-document management in XSLT 2.0
workflows.