Создать набор узлов и передать в качестве параметра - PullRequest
25 голосов
/ 07 октября 2010

Используя XSLT 1.0, я пытаюсь создать небольшой набор узлов, а затем передать его в качестве параметра в шаблон, что-то вроде следующего:

<xsl:call-template name="widget">
  <xsl:with-param name="flags">
    <items>
      <item>widget.recent-posts.trim-length=100</item>
      <item>widget.recent-posts.how-many=3</item>
      <item>widget.recent-posts.show-excerpt</item>
    </items>
  </xsl:with-param>
</xsl:call-template>

Идея в том, что тогда из шаблона widget я мог бы написать что-то вроде:

<xsl:value-of select="$flags/item[1]" />

Очевидно, что я получаю ошибки компиляции .. как я могу добиться такого рода вещей?

Ответы [ 2 ]

28 голосов
/ 07 октября 2010

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

Всякий раз, когда узлы динамически создаются внутри тела xsl:variable или xsl:param, типом этого xsl:variable / xsl:param является RTF (Фрагмент дерева результатов) иW3 XSLT 1.0 Spec.строго ограничивает вид выражений XPath, которые могут быть оценены по RTF.

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

Пространство имен, к которому привязан префикс xxx (или любой другой префикс, который вы выберете), отличается для разных поставщиков.Для MSXML и двух .NET XSLT-процессоров это: "urn:schemas-microsoft-com:xslt".Библиотека EXSLT использует пространство имен: "http://exslt.org/common".Это пространство имен EXSLT реализовано на многих процессорах XSLT 1.0, и рекомендуется по возможности использовать его расширение xxx:node-set().

Вот краткий пример :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:msxsl="urn:schemas-microsoft-com:xslt"
 xmlns:ext="http://exslt.org/common"
  exclude-result-prefixes="ext msxsl"
 >
 <xsl:template match="/">
  <xsl:variable name="vTempRTF">
   <a>
    <b/>
   </a>
  </xsl:variable>

  <xsl:copy-of select="ext:node-set($vTempRTF)/a/*"/>
 </xsl:template>
</xsl:stylesheet>
6 голосов
/ 07 октября 2010

Что ж, мне удалось обойти это следующим образом:

Сначала добавьте пользовательское пространство имен в таблицу стилей, например, xmlns:myns="http://my.ns.com"

Затем определите набор узлов в верхней частитаблица стилей:

<myns:recent-posts-flags>
    <item>widget.recent-posts.trim-length=100</item>
    <item>widget.recent-posts.how-many=3</item>
    <item>widget.recent-posts.show-excerpt</item>
</myns:recent-posts-flags>

Затем выполните ссылку следующим образом:

<xsl:call-template name="widget">
    <xsl:with-param name="flags" select="document('')/*/myns:recent-posts-flags" />
</xsl:call-template>

Это работает, но для меня все равно было бы идеально определить набор узлов в теге <xsl:with-param>сам, как в первом примере, который я дал .. кто-нибудь думает, что это будет возможно?

...