EXSLT dyn: оценить с пространством имен

В своем XSLT-преобразовании я загружаю другой документ с помощью функции document(). Когда я динамически запрашиваю этот документ с помощью функции EXSLT dyn:evaluate(), она работает только с тегами без пространств имен.

Загруженный XML-документ выглядит следующим образом:

<?xml version="1.0"?>
<root xmlns:ctm="http://www.michielmeulendijk.nl/custom">
  <nativeNamespace>1</nativeNamespace>
  <ctm:externalNamespace>2</ctm:customNamespace1>
</root>

В преобразовании XSLT я загружаю его следующим образом:

<xsl:variable name="xml-doc">
    <xsl:copy-of select="document('complex-sample.xml')/*"/>
</xsl:variable>

Затем я запрашиваю его с расширениями EXSLT:

<xsl:message>
  <xsl:value-of select="dyn:evaluate('exsl:node-set($xml-doc)//nativeNamespace')"></xsl:value-of>
</xsl:message>
<xsl:message>
  <xsl:value-of select="dyn:evaluate('exsl:node-set($xml-doc)//ctm:externalNamespace')"></xsl:value-of>
</xsl:message>

Примечательно, что результат первого запроса предоставляется правильно («1»), но результат второго запроса пуст.


person Michiel Meulendijk    schedule 22.07.2017    source источник
comment
В документе нет элемента externalNamespace.   -  person michael.hor257k    schedule 22.07.2017
comment
Можете показать минимальный, но полный образец, позволяющий воспроизвести проблему? Публикация XSLT-кода с использованием префикса пространства имен без демонстрации объявления пространства имен в XSLT довольно бессмысленна.   -  person Martin Honnen    schedule 22.07.2017
comment
Извини, я виноват. Это должно было быть externalNamespace вместо customNamespace.   -  person Michiel Meulendijk    schedule 22.07.2017
comment
Я начну готовить полный образец.   -  person Michiel Meulendijk    schedule 22.07.2017
comment
Я не могу воспроизвести проблему. Если я устраню несоответствие между <ctm:externalNamespace> и </ctm:customNamespace1> и удостоверюсь, что в таблице стилей есть объявление пространства имен, связывающее префикс ctm с тем же URI пространства имен, что и в исходном XML, я получаю 2 в результате второго вызова. Это использование libxslt.   -  person michael.hor257k    schedule 22.07.2017
comment
Я понимаю. Я тоже добавил свое собственное пространство имен в таблицу стилей XSLT, и оно работает, как и ожидалось. Однако я не всегда знаю, какой внешний документ моя таблица стилей загружает через функцию document(). Итак, могу ли я динамически добавлять пространства имен из загруженного документа в свою таблицу стилей XSLT...?   -  person Michiel Meulendijk    schedule 23.07.2017
comment
Если вы не знаете, с каким документом имеете дело, то как вы вообще можете его обработать? Пространства имен являются частью схемы — так же, как имена элементов и их иерархия.   -  person michael.hor257k    schedule 23.07.2017
comment
Что ж, я получаю структуру, которую хочу пройти, непосредственно из схемы XSD. Я автор этого проекта: github.com/MichielCM/xsd2html2xml. Я использую схему XSD для создания HTML-формы через XSLT. Я хочу, чтобы пользователи могли добавлять любой соответствующий XML-документ для заполнения формы значениями по умолчанию. Таким образом, на пространство имен ссылаются как в XSD, так и в загруженном XML-документе, но не в таблице стилей XSLT. Однако я могу генерировать запросы из схемы XSD.   -  person Michiel Meulendijk    schedule 23.07.2017
comment
Боюсь, я не совсем понимаю это (и я подозреваю, что очень мало шансов, что это можно объяснить мне в этом месте).   -  person michael.hor257k    schedule 23.07.2017


Ответы (1)


Это может быть ошибка/ограничение в реализации Xalan dyn:evaluate:

Известны ли проблемы с функцией расширения dyn:evaluate в Xalan-J 2.7.1?

Почему вы все равно используете Ксалан? Его не обновляли десять лет. Переключитесь на Saxon, и тогда вы сможете использовать XSLT 3.0 xsl:evaluate, который гораздо более всеобъемлющий, чем dyn:evaluate.

Хотя, если это ошибка, которую я привел, вы можете обойти ее, не используя фрагмент дерева результатов. Заменять

<xsl:variable name="xml-doc">
    <xsl:copy-of select="document('complex-sample.xml')/*"/>
</xsl:variable>

by

<xsl:variable name="xml-doc" select="document('complex-sample.xml')/*"/>

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

person Michael Kay    schedule 23.07.2017
comment
Это может быть ошибка/ограничение в реализации Xalan dyn:evaluate Нет, не может. Прочитайте комментарии: он отлично работает, как только вы добавите объявление пространства имен. - person michael.hor257k; 23.07.2017
comment
@ michael.hor257k Вы сказали, что используете libxslt, а не Xalan. - person Michael Kay; 23.07.2017
comment
Правильно. И OP сказал, что они тоже заработали после добавления объявления пространства имен: exslt dynevaluate с пространством имен"> stackoverflow.com/questions/45258695/ - person michael.hor257k; 23.07.2017
comment
Спасибо за ответ, но я думаю, что это действительно было вызвано отсутствием объявления пространства имен в таблице стилей XSLT. Я обнаружил, что такой запрос: //*[name() = 'ctm:exernalNamespace'] работает с отдельно загруженными документами. - person Michiel Meulendijk; 23.07.2017
comment
@MichielMeulendijk, но всего этого использования exsl:node-set($xml-doc) в вашем коде действительно можно полностью избежать, просто используя <xsl:variable name="xml-doc" select="document('complex-sample.xml')/*"/>, как предложил Майкл Кей. Таким образом, вы никогда не создаете фрагмент результирующего дерева в первую очередь, а затем вам никогда не нужно преобразовывать его в набор узлов перед использованием на нем XPath, вы напрямую получаете узлы из проанализированного ввода. - person Martin Honnen; 23.07.2017
comment
Спасибо, я не знаю, почему я использовал копию для моей переменной document(). Однако, когда я использую такое решение своей проблемы, оно больше не работает: dyn:evaluate('$xml-doc//*[name() = ctm:externalNamespace]. С копией переменной и набором узлов это работает: dyn:evaluate('exsl:node-set($xml-doc)//*[name() = ctm:externalNamespace]'). - person Michiel Meulendijk; 24.07.2017