Loading TOC...
XQuery and XSLT Reference Guide (PDF)

MarkLogic 9 Product Documentation
XQuery and XSLT Reference Guide
— Chapter 7

XSLT in MarkLogic Server

In MarkLogic Server, you have both the XQuery and XSLT languages available. You can use one or both of these languages as needed. This chapter briefly describes some of the XSLT language features and describes how to run XSLT in MarkLogic Server, and includes the following sections:

XSLT 2.0

MarkLogic Server implements the W3C XSLT 2.0 recommendation. XSLT 2.0 includes compatibility mode for 1.0 stylesheets. XSLT is a programming languages designed to make it easy to transform XML.

For details about the XSLT 2.0 recommendation, see the W3C website:

An XSLT stylesheet is an XML document. Each element is an instruction in the XSLT language. For a summary of the syntax of the various elements in an XSLT stylesheet, see https://www.w3.org/TR/xslt20/#element-syntax-summary.

Invoking and Evaluating XSLT Stylesheets

To run an XSLT stylesheet in MarkLogic Server, you run one of the following functions from an XQuery context:

The xdmp:xslt-invoke function invokes an XSLT stylesheet from the App Server root, and the xdmp:xslt-eval function takes a stylesheet as an element and evaluates it as an XSLT stylesheet. As part of running a stylesheet, you pass the stylesheet a node to operate on. For details on xdmp:xslt-invoke and xdmp:xslt-eval, see the MarkLogic XQuery and XSLT Function Reference.

MarkLogic Server Extensions to XSLT

Besides the ability to invoke and evaluate XSLT stylesheets from an XQuery context (as described in Invoking and Evaluating XSLT Stylesheets), there are several extensions to XSLT available in MarkLogic Server. This section describes those extensions and includes the following parts:

Calling Built-In XQuery Functions in a Stylesheet

You can call any of the MarkLogic Server Built-In XQuery functions from an XSLT stylesheet.

Importing XQuery Function Libraries to a Stylesheet

In addition to using <xsl:import> to import other XSLT stylesheets into your stylesheet, you can use the <xdmp:import-module> instruction to import an XQuery library module to an XSLT stylesheet. Once you have imported the module, any functions defined in the module are available to that stylesheet. When using the <xdmp:import-module> instruction, you must specify xdmp as a value of the extension-element-prefixes attribute on the <xsl:stylesheet> instruction and you also must bind the xdmp prefix to its namespace in the stylesheet XML.

The following is an example of an <xdmp:import-module> instruction:

xquery version "1.0-ml";

xdmp:xslt-eval(
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
       xmlns:xdmp="http://marklogic.com/xdmp"
       xmlns:search="http://marklogic.com/appservices/search"
       extension-element-prefixes="xdmp"
       version="2.0">     
     <xdmp:import-module 
           namespace="http://marklogic.com/appservices/search"
           href="/MarkLogic/appservices/search/search.xqy"/>
     <xsl:template match="/">
     <xsl:copy-of select="search:search('hello')"/>
     </xsl:template>
   </xsl:stylesheet>
,
document{ <doc/> })

Similarly, you can import an XSLT sytlesheet into an XQuery library, as described in Importing XQuery Function Libraries to a Stylesheet.

Try/Catch XSLT Instruction

You can use the <xdmp:try> instruction to create a try/catch expression in XSLT. When using the <xdmp:try> instruction, you must specify xdmp as a value of the extension-element-prefixes attribute on the <xsl:stylesheet> instruction and you also must bind the xdmp prefix to its namespace in the stylesheet XML.

The following is an example of a try/catch in XSLT. This example returns the error XML, which is bound to the variable named e in the name attribute of the <xdmp:catch> instruction.

xquery version "1.0-ml";

xdmp:xslt-eval(
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                   xmlns:xdmp="http://marklogic.com/xdmp"
                   extension-element-prefixes="xdmp"
                   version="2.0">
     <xsl:template match="/">
     <xdmp:try>
     <xsl:value-of select="error(xs:QName('MY-ERROR'), 
                                 'This is an error')"/>
     <xdmp:catch name="e">
           <xsl:copy-of select="$e"/>
     </xdmp:catch>
     </xdmp:try>
     </xsl:template>
   </xsl:stylesheet>
,
document{<doc>hello</doc>})

EXSLT Extensions

MarkLogic Server includes many of the EXSLT extensions (http://www.exslt.org/). The extensions include the exslt:node-set and exslt:object-type functions and the exsl:document instruction. For details about the functions, see the MarkLogic XQuery and XSLT Function Reference and the EXSLT web site.

The following is an example of the exsl:document instruction. Note that this is essentially the same as the xsl:result-document instruction, which is part of XSLT 2.0.

xquery version "1.0-ml";
(: Assumes this is run from a file called c:/mypath/exsl.xqy :)
xdmp:set-response-content-type("text/html"),
let $nodes := xdmp:xslt-eval(
<xsl:stylesheet  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                   xmlns:exsl="http://exslt.org/common"
                   extension-element-prefixes="exsl"
                   xmlns:xdmp="http://marklogic.com/xdmp"
                   version="2.0">
<xsl:template match="/">
  <html>
    <head><title>Frame example</title></head>
    <frameset cols="20%, 80%">
      <frame src="toc.html"/>
      <exsl:document href="toc.html">
        <html>
          <head><title>Table of Contents</title></head>
          <body>
             <xsl:apply-templates mode="toc" select="*"/>
          </body>
        </html>
      </exsl:document>
      <frame src="body.html"/>
      <exsl:document href="body.html">
        <html>
          <head><title>Body</title></head>
          <body>
             <xsl:apply-templates select="*"/>
          </body>
        </html>
      </exsl:document>
    </frameset>
  </html>
</xsl:template>
</xsl:stylesheet>,
document{element p { "hello" }})
for $node at $i in $nodes
return 
if ( fn:document-uri($node) )
then xdmp:save(
       fn:resolve-uri(fn:document-uri($node), 
       "C://mypath/exsl.xqy"), $node)
else ($node) 

The above query will save the two documents created with exsl:document to the App Server root on the filesystem, making them available to the output document with the frameset. For more details about the exsl:document instruction, see the EXSLT web site.

xdmp:dialect Attribute

You can add the attribute xdmp:dialect to any element in a stylesheet to control the dialect in which expressions are evaluated, with a value of any valid dialect (for example, "1.0-ml" or "1.0"). If no xdmp:dialect attribute is present, the default value is "1.0", which is standards-compliant XSLT 2.0 XPath.

If you are using code shared with other stylesheets (especially stylesheets that might be used with other XSLT processors), use care when setting the dialect to 1.0-ml, as it might have subtle differences in the way expressions are evaluated.

For details about dialects, see Overview of the XQuery Dialects.

Notes on Importing Stylesheets With <xsl:import>

XSLT includes the <xsl:import> instruction, which is used to import other stylesheets into a stylesheet. The MarkLogic implementation of the <xsl:import> instruction is conformant to the specification, but the <xsl:import> instruction can be complicated. For details on the <xsl:import> instruction, see the XSLT specification or your favorite XSLT programming book.

Some of the important points to note about the <xsl:import> instruction are as follows:

  • Any absolute URI references in the href attribute are resolved in the context of the current MarkLogic Server database URIs. Relative paths are resolved relative to current module in the App Server root. For details, see XQuery Library Modules and Main Modules in the Application Developer's Guide.
  • Any code imported in an <xsl:import> instruction follows the rules of precedence for XSLT imports. In general, that means that a stylesheet that imports has precedence over an imported stylesheet.
  • Any XQuery library modules imported into a styleheet follow the rules for XQuery imports, not the rules for XSLT imports. Notably, only functions and variables in the imported module are directly available to the stylesheet, not functions and variables that the XQuery library might import. XQuery library module imports use the <xdmp:import-module> extension instruction, as described in Importing XQuery Function Libraries to a Stylesheet.

Invoking Stylesheets Directly Using the XSLT Rewriter

As described in Invoking and Evaluating XSLT Stylesheets, you invoke a stylesheet from an XQuery program. To set up an HTTP App Server to invoke a stylesheet by directly calling it from the App Server, you can set up a URL rewriter. For general information on using a URL rewriter, see Creating an Interpretive XQuery Rewriter to Support REST Web Services in the Application Developer's Guide.

This section describes the sample URL rewriter for XSLT stylesheets and includes the following parts:

About the Sample Rewriter

The sample XSLT rewriter consists of two files, both installed in the <marklogic-dir>/Samples/xslt directory:

  • xslt-invoker.xqy
  • xslt-rewrite-handler.xqy

Once you set up the rewriter as described in the next section, URLs to the App Server of the form:

/filename.xsl?doc=/url-of-context-node.xml

will invoke the filename.xsl stylesheet and pass it the context node at the URI specified in the doc request field.

It will also take URLs if the form:

/styled/url-of-context-node.xml?stylesheet=/stylesheet.xsl

will invoke the stylesheet at the path specified in the stylesheet request field passing in the context node in the path after /styled (/url-of-context-node.xml in the above sample).

The following table describes what the request fields you pass translate to when you are using the sample XSLT rewriter.

Request Field Description
doc
Specifies the URI of the document to be passed into the stylesheet as the context node. If there is no doc request field, then it defaults to a context node of default.xml. If no document with the URI default.xml exists in the database, then the rewriter will throw an exception.
stylesheet
Used with paths that start with /styled. Specifies the path to the stylesheet to invoke. If it is not present, uses the stylesheet at default.xslt.
mode
The name of the initial mode to pass into the stylesheet. If not present, no mode is passed.
template
The name of the initial template to pass into the stylesheet. If not present, no template is passed in.

Setting Up the Sample Rewriter in Your HTTP App Server

You can use the sample rewriter as-is or you can modify it to suit your needs. For example, if it makes sense for your stylesheets, you can modify it to always pass a certain node as the context node.

To use the sample XSLT rewriter, perform the following steps:

  1. Copy the xslt-invoker.xqy and xslt-rewrite-handler.xqy modules from the <marklogic-dir>/Samples/xslt directory to your App Server root. The files must be at the top of the root of the App Server, not a subdirectory of the root. For example, if your root is set to /space/my-app-server, you must copy the new files to /space/my-app-server/xslt-invoker.xqy and /space/my-app-server/xslt-rewrite-handler.xqy. If your root is in a modules database, then you must load the 2 files as text document (with any needed permissions) with URIs that begin with the App Server root.
  2. In the Admin Interface, navigate to the HTTP App Server configuration for the App Server in which want to directly invoke XSLT stylesheets.
  3. On the HTTP Server Configuration page, find the url rewriter field (it is towards the bottom of the page).
  4. Enter /xslt-rewrite-handler.xqy into the url rewriter field.
  5. Click OK.

Request against the App Server will now be automatically rewritten to directly invoke stylesheets as described in the previous section.

XSLT, XQuery, or Both

Both XQuery and XSLT are Turing Complete programming languages; that is, in theory, you can use either language to compute whatever you need to compute. XQuery and XSLT share the same data model and share XPath 2.0, so there are a lot of commonalities between the two languages.

On some level, choosing which language to perform a specific task is one of style. Different programmers have different styles, and so there is no correct answer to what to do in XQuery and what to do in XSLT.

In practice, however, XSLT is very convenient for performing XML transformation. You can do these transformations in XQuery too, and you can do them well in XQuery, but some programmers find it more natural to write a transformation in XSLT.

« Previous chapter
Next chapter »