I'm trying to find a way to run XQuery within XSLT as I have a large library of XQuery logic that I've been using for enriching XML payloads in a Oracle database and I now need to migrate away from using this database but still carryout the enrichment logic in a new platform. The platform I'm migrating to supports XSLT 3.0 so I'm interested to first find a way to be able to run XQuery within XSLT. I've understood this to be possible by using fn:load-xquery-module() and I'm currently trying to mock this up in Oxygen XML Editor 24.0 (as this ships with Saxon EE 9.9.1.7 which is same as my Server runtime) however I don't get it working so far.
My XQuery module (saved in the same directory as my XSLT with file name myfuncs.xq):
module namespace myfuncs = "http://example.com/functions";
declare function myfuncs:double($num as xs:double) as xs:double {
$num * 2
};
declare function myfuncs:triple($num as xs:double) as xs:double {
$num * 3
};
My XSLT that attempts to use the XQuery module above (note, I've desensitised the URI paths below, in my local implementation they report the full absolute path):
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xf="http://www.w3.org/2002/xforms"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:myfuncs="http://example.com/functions"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:saxon="http://saxon.sf.net/"
exclude-result-prefixes="xs">
<!-- Load the XQuery module -->
<xsl:function name="myfuncs:double" as="xs:double">
<xsl:param name="num" as="xs:double"/>
<xsl:sequence select="fn:load-xquery-module('file:C:\Users\...\...\myfuncs.xq') ! myfuncs:double($num)"/>
</xsl:function>
<xsl:function name="myfuncs:triple" as="xs:double">
<xsl:param name="num" as="xs:double"/>
<xsl:sequence select="fn:load-xquery-module('file:C:\Users\...\...\myfuncs.xq') ! myfuncs:triple($num)"/>
</xsl:function>
<!-- Example usage -->
<xsl:template match="/">
<result>
<double> <xsl:value-of select="myfuncs:double(5)"/> </double>
<triple> <xsl:value-of select="myfuncs:triple(5)"/> </triple>
</result>
</xsl:template>
</xsl:stylesheet>
When I run this then I would expect my XQuery module to be loaded and myfuncs XQuery functions to be found and available for the XSLT, however instead I get the following error: Cannot locate module for namespace file:C:\Users...myfuncs.xq
My working sample for load-xquery-module
I have is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:math="http://www.w3.org/2005/xpath-functions/math"
xmlns:functx="http://www.functx.com"
exclude-result-prefixes="xs math functx"
version="3.0">
<xsl:variable name="functx-module" select="load-xquery-module('http://www.functx.com', map { 'location-hints' : 'http://www.xqueryfunctions.com/xq/functx-1.0-doc-2007-01.xq' })"/>
<xsl:template name="xsl:initial-template" match="/">
<xsl:sequence select="$functx-module?functions(xs:QName('functx:word-count'))?1('This is a test.')"/>
</xsl:template>
</xsl:stylesheet>
Adapting that to your module (saved as module5.xqm
in the same directory as the XSLT) gives
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xf="http://www.w3.org/2002/xforms"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:myfuncs="http://example.com/functions"
exclude-result-prefixes="#all">
<!-- Load the XQuery module -->
<xsl:variable name="module5" select="load-xquery-module('http://example.com/functions', map { 'location-hints' : 'module5.xqm' })"/>
<xsl:function name="myfuncs:double" as="xs:double">
<xsl:param name="num" as="xs:double"/>
<xsl:sequence select="$module5?functions(xs:QName('myfuncs:double'))?1($num)"/>
</xsl:function>
<xsl:function name="myfuncs:triple" as="xs:double">
<xsl:param name="num" as="xs:double"/>
<xsl:sequence select="$module5?functions(xs:QName('myfuncs:triple'))?1($num)"/>
</xsl:function>
<!-- Example usage -->
<xsl:template match="/" name="xsl:initial-template">
<result>
<double> <xsl:value-of select="myfuncs:double(5)"/> </double>
<triple> <xsl:value-of select="myfuncs:triple(5)"/> </triple>
</result>
</xsl:template>
</xsl:stylesheet>