How to Define Custom Functions Using xsl:function in XSLT?

Defining custom stylesheet functions with <xsl:function> in XSLT 2.0 and later allows developers to encapsulate reusable logic, perform complex calculations, and return strongly typed data directly within XPath expressions. Unlike traditional named templates, custom functions can be invoked seamlessly within XPath select attributes, predicates, and test conditions without disrupting the structural flow of the transformation. This guide covers how to declare a custom namespace, define function parameters, enforce return types, and implement custom functions in real-world scenarios.

Declaring Required Namespaces

Every user-defined function in XSLT 2.0 and above must reside in a non-default namespace to prevent naming collisions with built-in XPath and XSLT functions. This requirement is enforced by the XSLT processor.

To declare a custom namespace, add a namespace prefix mapping on the root <xsl:stylesheet> or <xsl:transform> element:

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:custom="http://example.com/custom-functions"
    exclude-result-prefixes="xs custom">

The exclude-result-prefixes attribute prevents namespace declarations from leaking into the output XML, HTML, or text document.

Structure of the xsl:function Element

The <xsl:function> element is a top-level declaration that defines the name, parameters, and evaluation logic of a reusable routine.

Key Attributes and Child Elements

While <xsl:value-of> converts results into text nodes, <xsl:sequence> preserves the underlying data type and sequence structure without adding extra text node wrappers. For mathematical operations and structural node handling, <xsl:sequence> is the standard practice.

<xsl:function name="custom:celsius-to-fahrenheit" as="xs:double">
    <xsl:param name="temp-c" as="xs:double"/>
    <xsl:sequence select="($temp-c * 9 div 5) + 32"/>
</xsl:function>

Step-by-Step Implementation Example

Consider an XML document containing an inventory list with item prices and tax categories:

<inventory>
    <item id="101">
        <name>Mechanical Keyboard</name>
        <price>120.00</price>
        <category>standard</category>
    </item>
    <item id="102">
        <name>Prescription Glasses</name>
        <price>250.00</price>
        <category>exempt</category>
    </item>
</inventory>

Complete XSLT Stylesheet

The following stylesheet defines a function to calculate final prices based on categorical tax rates:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:custom="http://example.com/shop"
    exclude-result-prefixes="xs custom">

    <xsl:output method="xml" indent="yes"/>

    <!-- Custom Function Definition -->
    <xsl:function name="custom:apply-tax" as="xs:decimal">
        <xsl:param name="base-price" as="xs:decimal"/>
        <xsl:param name="category" as="xs:string"/>
        
        <xsl:variable name="rate" as="xs:decimal">
            <xsl:choose>
                <xsl:when test="$category = 'standard'">0.20</xsl:when>
                <xsl:when test="$category = 'reduced'">0.05</xsl:when>
                <xsl:otherwise>0.00</xsl:otherwise>
            </xsl:choose>
        </xsl:variable>

        <xsl:sequence select="$base-price * (1 + $rate)"/>
    </xsl:function>

    <!-- Template Invoking the Function in XPath -->
    <xsl:template match="/inventory">
        <priced-inventory>
            <xsl:for-each select="item">
                <product id="{@id}">
                    <name><xsl:value-of select="name"/></name>
                    <total-price>
                        <xsl:value-of select="custom:apply-tax(xs:decimal(price), category)"/>
                    </total-price>
                </product>
            </xsl:for-each>
        </priced-inventory>
    </xsl:template>

</xsl:stylesheet>

Key Considerations for Using xsl:function