What Is xsl:use-package in XSLT 3.0?
The <xsl:use-package> declaration in XSLT 3.0
serves as the primary mechanism for importing and linking modular,
independently compiled stylesheet packages. Unlike legacy inclusion
mechanisms, it enables enterprise-grade software engineering practices
in XSLT by establishing strict encapsulation boundaries, managing
version dependencies, and allowing selective overriding or renaming of
library components such as functions, templates, and modes.
Modular Packaging Versus Legacy Inclusion
Prior to XSLT 3.0, modular stylesheets relied heavily on
<xsl:include> and <xsl:import>.
While functional, these directives operate on a textual and
tree-inclusion level, pulling all declarations into a single flat global
scope. This frequently caused namespace collisions, made library
refactoring risky, and prevented independent compilation.
XSLT 3.0 introduced <xsl:package> to define
self-contained compilation units and
<xsl:use-package> as the consumer-side link. A
package exports only explicitly declared public or abstract components,
while keeping private implementation details hidden. When a stylesheet
or package invokes <xsl:use-package>, the XSLT
processor links the pre-compiled package without exposing or interfering
with internal helper functions or local variables.
Key Attributes and Dependency Resolution
The <xsl:use-package> element appears at the top
level of a package or stylesheet declaration. It identifies target
dependencies using standardized attributes:
name: Specifies the absolute URI that uniquely identifies the target package.package-version: Defines the acceptable version range using semantic version patterns (e.g.,package-version="2.1.*"orpackage-version="[1.0, 2.0)").location: Provides an optional URI hint for locating the source or pre-compiled package resource on disk or across the network.
During static analysis, the processor uses these attributes to locate, compile (if not already cached), and link the exact matching library binary or AST (Abstract Syntax Tree).
Encapsulation and Component Renaming with xsl:accept
To prevent naming collisions and manage interface boundaries,
<xsl:use-package> uses child
<xsl:accept> elements. Through
<xsl:accept>, the importing module controls which
public components of the imported package are exposed:
component: Specifies the type of component to filter (template,function,variable,mode, orattribute-set).names: Selects specific components by QName or wildcard pattern.visibility: Alters the component’s downstream visibility (setting it toprivate,public,final, orhidden).equivalent-name: Renames an imported component locally to resolve naming clashes with other imported packages.
<xsl:use-package name="http://example.com/math-lib" package-version="1.0">
<xsl:accept component="function" names="math:calculate-tax" visibility="public"/>
<xsl:accept component="function" names="math:format-*" visibility="private"/>
</xsl:use-package>Specialization and Component Customization with xsl:override
The <xsl:use-package> element also supports
behavioral extension through the <xsl:override> child
element. This allows developers to supply specialized implementations
for public or abstract components defined in the base package without
modifying the original library source code.
When a function or template is overridden, the new implementation takes precedence throughout the linked package's internal execution path, enabling dynamic polymorphism and library extension across separately maintained modules.
By enforcing strict boundaries, supporting versioned linking, and
providing granular control over component visibility and overrides,
<xsl:use-package> transforms XSLT into a scalable
language suitable for large-scale, component-driven data transformation
pipelines.