How to Integrate XSD with Schema-Aware XSLT?

Schema-aware XSLT processors enhance document transformation by incorporating XML Schema Definitions (XSD) directly into the XSLT execution environment. Integrating an XSD allows the transformation engine to validate input and output documents, apply strict data typing, match templates based on schema types rather than just node names, and catch structural errors at compile time. This article explains how to import schemas into stylesheets, enforce input and output validation, and leverage schema types within XPath expressions and template rules.

Importing XML Schemas Using xsl:import-schema

The primary mechanism for introducing an XSD into an XSLT 2.0 or 3.0 schema-aware stylesheet is the xsl:import-schema declaration. This element is placed at the top level of the stylesheet as a child of xsl:stylesheet or xsl:transform.

You can import a schema by declaring its target namespace and specifying the schema location:

<xsl:stylesheet version="3.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:app="http://example.com/ns/application">

    <xsl:import-schema 
        namespace="http://example.com/ns/application" 
        schema-location="schemas/application.xsd" />

</xsl:stylesheet>

For schemas without a target namespace, omit the namespace attribute or specify namespace="". Once imported, all named simple types, complex types, element declarations, and attribute declarations from the XSD become accessible throughout the stylesheet.

Validating Input and Output Documents

Schema-aware XSLT allows explicit validation instructions during document loading, node creation, and result-tree serialization.

Validating Source Documents

When loading source documents via functions such as doc() or collection(), or processing the primary input document, you can request validation using processor-specific flags or standard XSLT instructions. When an input document is validated against an imported schema, every element and attribute is annotated with its corresponding schema type instead of defaulting to untyped data (xs:untyped or xs:untypedAtomic).

Validating Result Documents and Elements

You can validate constructed output trees by adding the validation or type attribute to result elements, literal result elements, xsl:element, xsl:document, or xsl:result-document.

<xsl:result-document href="output.xml" validation="strict">
    <app:order id="1042">
        <app:total>249.99</app:total>
    </app:order>
</xsl:result-document>
<xsl:element name="app:discountPrice" type="app:MonetaryAmountType">
    <xsl:value-of select="$calculatedDiscount" />
</xsl:element>

Pattern Matching on Schema Types

In standard XSLT, template matching relies on node names and positions. Schema-aware XSLT introduces type-based pattern matching using the schema-element() and type() sequence type tests.

<!-- Match any element declared as an 'order' in the imported schema -->
<xsl:template match="schema-element(app:order)">
    <xsl:apply-templates />
</xsl:template>

<!-- Match any node whose type is or derives from MonetaryAmountType -->
<xsl:template match="element(*, app:MonetaryAmountType)">
    <span class="currency">
        <xsl:value-of select="format-number(., '$#,##0.00')" />
    </span>
</xsl:template>

This capability decouples transformation rules from specific element tag names, enabling rules that automatically handle any element derived from a common base type.

Type Safety in XPath Expressions and Variables

Integrating XSD allows XPath operations to work with native primitive types (such as xs:date, xs:decimal, and xs:boolean) directly from validated source trees without requiring explicit cast operations like xs:decimal(price).

<xsl:variable name="taxRate" as="xs:decimal" select="0.08" />

<!-- Direct arithmetic on typed node values -->
<xsl:template match="schema-element(app:item)">
    <totalWithTax>
        <xsl:value-of select="app:price * (1 + $taxRate)" />
    </totalWithTax>
</xsl:template>

Functions and named templates can also enforce strict parameter and return types:

<xsl:function name="app:is-expired" as="xs:boolean">
    <xsl:param name="expiryDate" as="xs:date" />
    <xsl:sequence select="$expiryDate &lt; current-date()" />
</xsl:function>

Practical Benefits of Schema Integration