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:
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.
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.
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:
You can call any of the MarkLogic Server Built-In XQuery functions from an XSLT 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 stylesheet into an XQuery library, as described in Importing XQuery Function Libraries to a Stylesheet.
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>})
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.
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.
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:
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.<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.<xdmp:import-module>
extension instruction, as described in Importing XQuery Function Libraries to a Stylesheet.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:
The sample XSLT rewriter consists of two files, both installed in the <marklogic-dir>/Samples/xslt
directory:
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.
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:
xslt-invoker.xqy
and xslt-rewrite-handler.xqy
modules from the <marklogic-dir>/Samples/xsl
t 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.url rewriter
field (it is towards the bottom of the page).url rewriter
field.Request against the App Server will now be automatically rewritten to directly invoke stylesheets as described in the previous section.
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.