XSL, используя XML в качестве параметра для шаблона - PullRequest
7 голосов
/ 19 сентября 2010

Можно ли передавать XML в шаблон XSL через параметр? Например, ниже у меня есть шаблон body шаблон вызова test1, который передает некоторый XML через параметр var1. Затем я пытаюсь дойти до узла a, используя XPATH

<xsl:template name="test1">
    <xsl:param name="var1" />
    <fo:block>
        <xsl:value-of select="$var1/a" />
    </fo:block>
</xsl:template>

<xsl:template name="body">
    <xsl:call-template name="test1">
        <xsl:with-param name="var1" >
            <a>foo</a>
        </xsl:with-param>
    </xsl:call-template>
</xsl:template>

Проблема в том, что это приводит к сбою моего интерпретатора XSL с ненужным сообщением об ошибке. Я вынужден использовать систему поставщиков с закрытым исходным кодом для генерации документов, поэтому я не могу отлаживать. Но прежде чем углубляться в это, я ищу подтверждение того, что это допустимое использование XSL.

1 Ответ

14 голосов
/ 19 сентября 2010
<xsl:template name="body"> 
    <xsl:call-template name="test1"> 
        <xsl:with-param name="var1" > 
            <a>foo</a> 
        </xsl:with-param> 
    </xsl:call-template> 
</xsl:template>

Параметр $var1, передаваемый шаблону, вряд ли можно использовать в XSLT 1.0 / XPath 1.0 из-за печально известного типа RTF (Result-Tree Fragment).

Из спецификации W3C XSLT 1.0 .:

11.1 Фрагменты дерева результатов

Переменные вводят дополнительный тип данных в язык выражения. это дополнительный тип данных называется результатом фрагмент дерева. Переменная может быть связана к фрагменту результирующего дерева вместо один из четырех основных типов данных XPath (строка, число, логическое значение, набор узлов). Фрагмент результирующего дерева представляет собой фрагмент результирующего дерева. Результат фрагмент дерева трактуется одинаково к набору узлов, который содержит только один корневой узел. Тем не менее операции, разрешенные в дереве результатов фрагмент является подмножеством тех разрешено на наборе узлов. операция разрешена на результат фрагмент дерева, только если эта операция будет разрешено на строку ( операция над строкой может включать сначала преобразовать строку в число или логическое значение). В частности, это не разрешается использовать /, //, и [] операторы в дереве результатов фрагменты. Когда разрешена операция выполняется на дереве результатов фрагмент, он выполняется точно так же, как это было бы на эквивалент набор узлов.

Когда фрагмент результирующего дерева копируется в дерево результатов (см. [11.3 Использование Значения переменных и параметров с xsl: copy-of]), затем все узлы которые являются потомками корневого узла в эквивалентный набор узлов добавляется в последовательность к результирующему дереву.

Выражения могут возвращать только значения фрагмент дерева результатов типа ссылки на переменные типа результата фрагмент дерева или вызывающее расширение функции, которые возвращают дерево результатов фрагмент или получение системного свойства значение которого является фрагментом результирующего дерева.

Чтобы обойти это ошибочное решение, почти каждый XSLT-процессор имеет собственную функцию расширения, обычно называемую xxx:node-set(), где префикс xxx должен быть связан с пространством имен, определяемым поставщиком.

Решение

Узнайте, как именно называется эта функция расширения, предлагаемая поставщиком вашего процессора XSLT.

Или, если ваш XSLT-процессор поддерживает EXSLT , используйте функцию расширения exsl:node-set(), как определено в EXSLT.

Вот некоторые специфичные для поставщика пространства имен:

MSXML и .NET XslCompiledTransform, XslCompiledTransform :

xmlns:vendor="urn:schemas-microsoft-com:xslt"

Xalan (обратите внимание, имя функции: xxx:nodeset()!):

 xmlns:vendor="http://xml.apache.org/xalan"

Сакс (6x):

 xmlns:vendor="http://icl.com/saxon"

Altova:

 xmlns:vendor="http://www.altova.com/xslt-extensions"

Все процессоры XSLT, которые реализуют EXSLT :

xmlns:vendor="http://exslt.org/common"

В случае, если тело <xsl:param> не построено динамически, можно избежать

xxx:node-set() работает следующим образом:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes"/>

 <xsl:variable name="vrtfparamXML">
   <a>
     <b>foo</b>
   </a>
 </xsl:variable>

 <xsl:variable name="vparamXML" select=
 "document('')/*/xsl:variable
                [@name='vrtfparamXML']/*"/>

 <xsl:template match="/">
   <xsl:copy-of select="$vparamXML/b"/>
 </xsl:template>
</xsl:stylesheet>

когда это преобразование применяется к любому документу XML (не используется), результатом является требуемый дочерний элемент RTF :

<b xmlns:xsl="http://www.w3.org/1999/XSL/Transform">foo</b>

Примечание : XSLT 2.0 / XPath 2.0 избавился от «типа» RTF, и нет проблем с доступом к временным деревьям и навигацией по ним с использованием полной мощности XPath 2.0

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...