How Does doc() Differ from document() in XSLT 2.0?

In XSLT development, accessing external XML data transitioned significantly between XSLT 1.0 and XSLT 2.0. While XSLT 1.0 relied exclusively on the versatile but complex document() function, XSLT 2.0 introduced doc() alongside document() to provide a simpler, standardized mechanism based on XPath 2.0 and the XML Query data model. This article breaks down the technical differences between doc() and document(), examining their URI resolution rules, handling of multiple arguments, node sequencing, and error behavior.

Core Purpose and Origins

The document() function was designed specifically for XSLT 1.0 to load external resources, process secondary XML files, and read lookup tables. Because XPath 1.0 lacked a native mechanism for opening external documents, document() was an XSLT-specific instruction.

With XSLT 2.0 and XPath 2.0, the core specification integrated the doc() function into the XPath 2.0 Functions and Operators standard. The goal was to provide a streamlined, predictable function for retrieving a single document, aligning XPath with XQuery.

Key Differences

1. Argument Types and Document Counts

2. Base URI Resolution

3. Whitespace and Node Stripping

4. Error Handling and Missing Resources

Comparison Summary

Feature doc() (XPath 2.0 / XSLT 2.0) document() (XSLT 1.0 / 2.0)
Standard Origin XPath 2.0 / XQuery 1.0 XSLT 1.0 / XSLT 2.0
Input Arguments Single URI string (or empty) Sequence/Node-set of URIs, optional base node
Return Value Single document node or empty Node-set of multiple document nodes
Base URI Default Static base URI of stylesheet Static base URI or dynamic node base
Safety Check Use with doc-available() Implementation-dependent empty fallback

When to Use Which

In modern XSLT 2.0 and 3.0 stylesheets, doc() is preferred for loading individual external XML resources due to its strict typing and cross-compatibility with XQuery. The document() function remains useful when you need to load a batch of documents simultaneously from a list of URI nodes or require dynamic base URI resolution using a secondary context node.