Custom functions in XSL

Custom functions in XSL

XSLT provides a number of native functions such as not(), sum() and many others. XSLT 2.0 also brought support for defining custom functions in an XSLT template, and that's what I want to look at in this article.

A custom XSLT function can be defined using the xsl:function element, which has three attributes. The first is the name of the function, name, which must also contain a namespace prefix. This is particularly important to avoid collisions with existing XSLT functions. The prefix must also not contain any of the reserved prefixes see W3 documentation. The second attribute is as, which defines the data type returned by the function. The most common data types can be found, for example, on the IBM web site, but remember to use the xs: prefix for basic types. The last attribute is override, which specifies what should happen if the same function already exists in the template with the same number of parameters, arity. It is not necessary to specify the last two attributes.

1<xsl:function name="rocek:getElementId" as="attribute()" override="yes">
2<!-- ... -->
3</xsl:function>

The function can also accept parameters, the xsl:param element is used for this purpose. As in the case of a function, the name attribute must be specified, but this time it is not necessary to specify a namespace prefix. The as attribute again specifies the data type.

The ```xml <xsl:function name="rocek:getElementId" as="attribute()" override="yes"> <xsl:param name="element" as="element()" /> </xsl:function>


Finally, the function should contain some body. In our case, we will return the ID of the element, either from the `xml:id` or `ana` attribute. Depending on whether the ID is present. I'm not sure that such a function would ever need to be created, but for illustrative purposes, this simple function is sufficient.

```xml
<xsl:function name="rocek:getElementId" as="attribute()" override="yes">
  <xsl:param name="element" as="element()" />
  <xsl:choose>
    <xsl:when test="$element/@xml:id">
      <xsl:sequence select="$element/@xml:id"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:sequence select="$element/@ana"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:function>

In addition to defining the function, you must also register your own namespace. This can be done by editing the XSL stylesheet header as follows. The address after the equation can be arbitrary.

1<xsl:stylesheet
2  xmlns="http://www.tei-c.org/ns/1.0"
3  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
4  xmlns:rocek="http://libovolna.adresa"
5  version="3.0"
6  exclude-result-prefixes="tei lindat"
7>
8  <!-- template body -->
9</xsl:stylesheet>

After this modification, the function is successfully defined and ready to be used in our transformations. For example:

1<xsl:template match="div">
2  <div id="section-{rocek:getElementId(current())}">
3    <xsl:apply-templates/>
4  </div>
5</xsl:template>