XSL transformations


eXist-db can perform XSLT transformations inside XQuery code. For this you need to use the transform module.

The transform module

eXist-db transform module allows you to do XSLT transformations from XQuery code using Saxon.

Its function namespace is http://exist-db.org/xquery/transform.


The transform:transform function performs an XSLT transformation and returns you the result:. It has two signatures:

transform:transform($input as node()?, $stylesheet as item(), $parameters as node()?) as node()?
transform:transform($node-tree as node()*, $stylesheet as item(), $parameters as node()?, $attributes as node()?, $serialization-options as xs:string?) as node()?

The node to be transformed. If $input is an empty sequence, the function returns immediately.


The stylesheet to use. This must either be a URI or a node.

If $stylesheet is a URI, the stylesheet is loaded from the specified location. Watch out: A relative URI is interpreted as a file path!

Loading a stylesheet from the database is done best by creating a full absolute path, including an xmldb:exist:// prefix.

The stylesheet is compiled into a template (using the standard Java APIs javax.xml.transform). The result is shared between all instances of the function and will only reload if modified since last invocation.

Some examples for referencing the stylesheet:

  • transform:transform($root, doc("/db/styles/style.xsl"), ())

    Create the stylesheet from a document node.

  • transform:transform($root, xs:anyURI("http:exist-db.org/style.xsl"), ())
    transform:transform($root, xs:anyURI("xmldb:exist:///db/styles/style.xsl"), ())

    Load the stylesheet from the specified URI.


Specify any stylesheet parameters. This must be an XML fragment like the following example:

  <param name="param1" value="value1"/>
  <param name="param2" value="value2"/>

The stylesheet can now reference parameter param1 as follows:

<xsl:param name="param1"/>

There are two special parameters named exist:stop-on-warn and exist:stop-on-error. If set to yes, eXist will generate an XQuery error if the XSL processor reports a warning or error.


Pass attributes to the transformation factory. Verify the Java or Saxon documentation for more details. Its contents must be an XML fragment, below you see how -it:main type transformations are handled:

  <attr name="param1" value="value1"/>
  <attr name="param2" value="value2"/>
  <attr name="http://saxon.sf.net/feature/initialTemplate" value="main"/>

Specifies serialization options in the same way as passed to the declare option exist:serialize expression.

An additional serialization option, xinclude-path, is supported. This specifies the base path against which XInclude-s will be expanded. A relative path is relative to the current module load path.

A common trap is the use of fn:doc() these are not identical inside eXist-db's xquery processing and Saxon's XSL handling. Therefore, for transformation of mutiple XML files stored inside the dababase, you might wish to construct a temporary catalog file for use by the transformation and immediate removal, like this:

declare function obe:make-catalog($col as item()*, $docs as xs:string*) as item() {
    <collection stable="true" xml:base="xmldb:exist://">
            if (exists($docs)) then
                for $doc in $docs
                    <doc href="{$config:data-root || "/" || $doc}"/>
                for $doc in collection($col)//tei:TEI
                    <doc href="{document-uri(root($doc))}"/>


Performs an XSLT transformation like the transform:transform function, but directly streams the transformation result to the HTTP request output stream. It doesn't return anything. The function is therefore only usable in a web context.

The servlet output stream will be closed afterwards.