Я пытаюсь найти способ запустить XQuery в XSLT, поскольку у меня есть большая библиотека логики XQuery, которую я использовал для обогащения полезных данных XML в базе данных Oracle, и теперь мне нужно отказаться от использования этой базы данных, но все равно выполнять логика обогащения на новой платформе. Платформа, на которую я перехожу, поддерживает XSLT 3.0, поэтому мне интересно сначала найти способ запускать XQuery внутри XSLT. Я понял, что это возможно с помощью fn:load-xquery-module(), и в настоящее время я пытаюсь смоделировать это в Oxygen XML Editor 24.0 (поскольку он поставляется с Saxon EE 9.9.1.7, который такой же, как мой сервер). время выполнения), однако пока у меня это не работает.
Мой модуль XQuery (сохранен в том же каталоге, что и мой XSLT, с именем файла 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
};
Мой XSLT, который пытается использовать указанный выше модуль XQuery (обратите внимание, я снизил чувствительность приведенных ниже путей URI, в моей локальной реализации они сообщают полный абсолютный путь):
<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>
Когда я запускаю это, я ожидаю, что мой модуль XQuery будет загружен, а функции myfuncs XQuery будут найдены и доступны для XSLT, однако вместо этого я получаю следующую ошибку: Невозможно найти модуль для файла пространства имен: C:\Users...myfuncs.xq





Мой рабочий образец для load-xquery-module выглядит следующим образом:
<?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>
Адаптация этого к вашему модулю (сохраненному как module5.xqm в том же каталоге, что и XSLT) дает
<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>
Замечательно, мне это подходит, Мартин, спасибо за помощь и быстрый ответ!
Поскольку я буду запускать это на платформе SAP, где поставщик упоминает, что можно импортировать xsl в работающий xsl, то я надеюсь, что смогу добиться этого и с помощью модуля XQuery.
Для импорта отчетов поставщика XSL вы сохраняете все xsl в партнерском каталоге под тремя ключами, доступными с помощью префикса pd, поэтому примером этого является <xsl:import href = "pd:GenericPartner:xsl_util:Binary"/>, где xsl_util имя xsl, хранящееся в виде двоичного объекта в партнерском каталоге. Я думаю, что затем я бы сохранил свой XQuery в этом так называемом партнерском каталоге и получил бы к нему доступ с помощью URI pd:GenericPartner:module5:Binary, как я мог бы правильно представить такой URI в приведенном выше случае
то есть могу ли я просто включить карту { 'location-hints': 'pd:GenericPartner:module5:Binary'} в функцию load-query-module? Я понимаю, что вы, возможно, не можете ответить на этот вопрос, и поэтому мне нужно будет обсудить это с поставщиком, но любые подсказки также будут приняты с благодарностью.
@Алекс, извините, я не знаком с платформой SAP, поэтому лучше спросите их поддержку или, если здесь, на StackOverflow, есть тег для этого, поднимите другой вопрос с соответствующими тегами, чтобы кто-то, обладающий опытом в этой области, мог смогу помочь.
Одна из возможностей заключается в том, что ему не нравятся обратные косые черты. Вы должны предоставить URI, а URI всегда используют косую черту.