Подтвердить что ты не робот

Используйте значение переменной в режиме шаблонов apply-templates

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

<xsl:variable name="mode" select="@attribute"/>
<xsl:apply-templates mode="{$mode}"/>

Я получаю ошибку, которую таблица стилей не может быть скомпилирована. Значение режима должно быть QName, но это "{$ mode}".

Есть ли возможность использовать режимы, зависящие от переменных?

4b9b3361

Ответ 1

Единственный вариант, который вы должны использовать в определенном режиме на основе выражения, - это использовать

<xsl:choose>
   <xsl:when test="@attribute = 'foo'">
      <xsl:apply-templates mode="bar"/>
   </xsl:when>
   <xsl:otherwise>
      <xsl:apply-templates/>
   </xsl:otherwise>
</xsl:choose>

или то же самое с xsl:if. Значение атрибута mode должно быть QName в XSLT 1.0, соответственно, в XSLT 2.0 допускает QName или специальные токены, такие как #current или #default '. Но вы не можете вычислить значение mode во время выполнения.

Ответ 2

режим не является допустимым кандидатом для шаблонов значений атрибутов (AVT). Вы просто не можете этого сделать.

Из Спецификация XSLT 2.0:

[Определение: в атрибуте, который обозначается как значение атрибута шаблон, такой как атрибут элемента с литеральным результатом, выражение можно использовать, окружая выражение с кудрявым скобки ({})].

режим не обозначается как AVT в спецификации, поэтому вы не можете этого сделать.

Ответ 3

Я получаю ошибку, которую таблица стилей не может быть скомпилирована. Значение mode должен быть QName, но это "{$ mode}".

Есть ли возможность использовать режимы, зависящие от переменных?

Нет, это не поддерживается ни в одной версии XSLT - 1.0, 2.0 или 3.0.

Как вы пытаетесь эмулировать функции более высокого порядка (HOF), вы можете использовать базовый принцип FXSL, чтобы сделать это в XSLT 1.0.

FXSL 1.x - это библиотека шаблонов, написанная в чистом XSLT 1.0, которая поддерживает/эмулирует HOF.

Вот полное решение, основанное на этих принципах:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:f="http://fxsl.sf.net" exclude-result-prefixes="f">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

   <f:inc/>
   <f:double/>

 <xsl:variable name="vModeInc" select="document('')/*/f:inc[1]"/>
 <xsl:variable name="vModeDouble" select="document('')/*/f:double[1]"/>

 <xsl:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="/*">
  <nums>
    <xsl:apply-templates select="$vModeInc">
      <xsl:with-param name="pNodes" select="node()"/>
    </xsl:apply-templates>
  </nums>
==============
  <nums>
    <xsl:apply-templates select="$vModeDouble">
      <xsl:with-param name="pNodes" select="node()"/>
    </xsl:apply-templates>
  </nums>
 </xsl:template>

 <xsl:template match="f:inc">
   <xsl:param name="pNodes"/>
   <xsl:apply-templates select="$pNodes" mode="incr"/>
 </xsl:template>

 <xsl:template match="f:double">
   <xsl:param name="pNodes"/>
   <xsl:apply-templates select="$pNodes" mode="double"/>
 </xsl:template>

 <xsl:template match="num" mode="incr">
  <num><xsl:value-of select=".+1"/></num>
 </xsl:template>

 <xsl:template match="num" mode="double">
  <num><xsl:value-of select=".*2"/></num>
 </xsl:template>
</xsl:stylesheet>

Когда это преобразование применяется к следующему документу XML:

<nums>
  <num>01</num>
  <num>02</num>
  <num>03</num>
  <num>04</num>
  <num>05</num>
  <num>06</num>
  <num>07</num>
  <num>08</num>
  <num>09</num>
  <num>10</num>
</nums>

вызывается желаемый, правильный результат - элементы nums/num, обработанные в одном (каждом) из двух доступных режимов, в зависимости от указанной переменной - $vModeInc (1 добавлено к каждое значение) или $vModeDouble (каждое значение умножается на два):

<nums>
   <num>2</num>
   <num>3</num>
   <num>4</num>
   <num>5</num>
   <num>6</num>
   <num>7</num>
   <num>8</num>
   <num>9</num>
   <num>10</num>
   <num>11</num>
</nums>
==============
  <nums>
   <num>2</num>
   <num>4</num>
   <num>6</num>
   <num>8</num>
   <num>10</num>
   <num>12</num>
   <num>14</num>
   <num>16</num>
   <num>18</num>
   <num>20</num>
</nums>