Передача узла в качестве параметра таблице стилей XSL

Мне нужно передать узел в качестве параметра в таблицу стилей XSL. Проблема в том, что параметр отправляется в виде строки. Я видел несколько вопросов SO по этой теме и знаю, что решение (в XSLT 1.0) заключается в использовании внешней функции node-set() для преобразования строки в набор узлов.

Моя проблема в том, что я использую eXist DB. Кажется, я не могу заставить свой XSLT-процессор найти любую такую ​​функцию. Я пробовал EXSLT node-set() из пространства имен http://exslt.org/common, а также версии Saxon и Xalan (я думаю, что eXist раньше использовал Xalan, но теперь это может быть Saxon).

Разрешены ли эти расширения даже в процессоре XSLT, используемом eXist? Если нет, могу ли я сделать что-то еще?


person pajevic    schedule 19.11.2016    source источник
comment
Что ж, вы можете сначала проверить сведения об используемом процессоре XSLT с помощью таблицы стилей, такой как home. arcor.de/martin.honnen/xslt/processorTest3.xml для вывода таких свойств, как system-property('xsl:vendor') и system-property('xsl:product-version'). Что касается ваших текущих попыток, вы используете код Java для выполнения преобразования XSLT или XQuery? Рассмотрите возможность показать подробности этого кода, передающего параметр и выполняющего преобразование.   -  person Martin Honnen    schedule 19.11.2016
comment
Вы не хотите читать другие подобные вопросы/ответы SO, если они не относятся конкретно к eXist, потому что способ передачи параметров в XSLT-преобразование зависит от деталей API, предлагаемых конкретным продуктом, и это варьируется от одного продукта к Другая. И целью функции node-set() НЕ является анализ XML, предоставленного в виде строки, хотя некоторые реализации делают это.   -  person Michael Kay    schedule 19.11.2016
comment
http://exist-db.org/exist/apps/fundocs/view.html?uri=http://exist-db.org/xquery/transform&location=java:org.exist.xquery.functions.transform.TransformModule&details=true говорит о параметрах Параметры таблицы стилей могут быть переданы в третий аргумент с использованием фрагмента XML со следующей структурой: <parameters><param name="param-name1" value="param-value1"/></parameters>. Это выглядит так, как будто параметры, по крайней мере, для функции transform, представляют собой просто пары строк имя/значение.   -  person Martin Honnen    schedule 19.11.2016
comment
И github .com/eXist-db/exist/blob/develop/src/org/exist/xquery/ похоже подтверждает, что параметры обрабатываются как java.util.Properties. Но, надеюсь, какой-нибудь существующий пользователь или разработчик может дать более информированный ответ.   -  person Martin Honnen    schedule 19.11.2016
comment
@Martin Honnen Да, я действительно использую функцию XQuery transform:transform() для запуска преобразования. И я думаю, что ты прав. ‹param›, похоже, удаляет любые переданные ему XML-теги. Поэтому я не думаю, что узел вообще можно воссоздать.   -  person pajevic    schedule 20.11.2016
comment
@Michael Kay Несмотря на то, что это может быть не целью функции node-set(), вы должны иметь возможность использовать ее для этого, по крайней мере, в версии EXSLT. В его документации сказано: Вы также можете использовать эту функцию для преобразования строки в текстовый узел, что полезно, если вы хотите передать строку функции, которая принимает только набор узлов. exslt.org/exsl/functions/node-set   -  person pajevic    schedule 20.11.2016
comment
@pajevic Боюсь, вы неправильно понимаете, что делает функция node-set(). Чтобы превратить строку в текстовый узел, НЕ означает синтаксический анализ экранированной разметки, как если бы это был XML, и превращение ее в набор узлов. Для этого вам понадобится такая функция, как parse-xml(), которая доступна в XSLT 3.0. В XSLT 1.0 единственным выходом является вывод строки с отключенным экранированием, а затем обработка полученного документа на втором проходе.   -  person michael.hor257k    schedule 20.11.2016
comment
Я никогда не понимал, чего он пытается достичь, превращая строку в текстовый узел. Вы можете сделать это с помощью инструкции xsl:value-of, вам не нужны какие-либо расширения.   -  person Michael Kay    schedule 20.11.2016
comment
@MichaelKay Говорят, что это полезно, если вы хотите передать строку функции, которая принимает только набор узлов. Это не очень драматично, но должно позволить вам делать такие вещи, как sum(amount | exsl:node-set($fee)). -- Кстати, в каких реализациях вы можете использовать node-set() для разбора экранированного XML?   -  person michael.hor257k    schedule 21.11.2016
comment
Я не знаю ответа на вопрос BTW, но я встречал людей, которые ожидали такого поведения и ссылались на другие продукты, которые (они верили) делали это таким образом.   -  person Michael Kay    schedule 21.11.2016


Ответы (2)


Для ссылки или преобразования документов из базы данных необходимо передать путь в качестве параметра преобразования, а затем обратиться к нему с помощью параметра и переменной

(: xquery :)

let $path-to-document := "/db/test/testa.xml"
let $stylesheet := 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:param name="source" required="no"/>
    <xsl:variable name="error"><error>doc not available</error></xsl:variable>
    <xsl:variable name="theDoc" select="if (doc-available($source)) then doc($source) else $error"/>
    <xsl:template match="/">
       <result><xsl:value-of select="$source"/> - <xsl:value-of select="node-name($theDoc/*)"/></result>
    </xsl:template>
</xsl:stylesheet>


return transform:transform(<dummy/>,$stylesheet, <parameters><param    name="source" value="xmldb:exist://{$path-to-document}"/></parameters>)
person GSpringTech    schedule 20.11.2016
comment
Спасибо, но моего XML нет в базе данных. Это фрагмент в памяти. - person pajevic; 20.11.2016

Согласно комментариям Мартина Хоннена, я не думаю, что можно передать узел XML через структуру <parameters> функции transform:transform() в eXist. Кажется, что функция удаляет любые теги XML, переданные ей в качестве значения.

В качестве обходного пути я оберну входной XML и XML параметров в корневой элемент и передам его в качестве входных данных для функции преобразования.

person pajevic    schedule 20.11.2016
comment
Ты прав. Функция transform:transform разрешает только строки в качестве значений параметров для преобразования, решение, как вы пришли к выводу, состоит в том, чтобы изменить входной документ в преобразование, чтобы обернуть узел вашего параметра. В ближайшем будущем мы планируем добавить в eXist уже стандартизированную функцию fn:transform (из XQuery 3.0), чтобы заменить transform:transform, что позволит вам отправлять узлы (или любого типа) в качестве параметра. - person adamretter; 29.11.2016
comment
Спасибо за разъяснение Адам. - person pajevic; 29.11.2016