在apply-templates模式下使用变量的值

时间:2012-09-06 11:21:00

标签: xslt xslt-1.0

我想应用一个模板,该模板的模式取决于变量值。

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

我收到无法编译样式表的错误。 mode的值应该是QName,但它是“{$ mode}”。

是否有可能使用依赖于变量的模式?

3 个答案:

答案 0 :(得分:7)

您必须使用基于表达式的特定模式的唯一选择是使用

<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属性值本身需要分别是XSLT 1.0中的QName,而XSLT 2.0允许使用QName#current#default等特殊令牌。但是您无法在运行时计算mode值。

答案 1 :(得分:3)

模式不是属性值模板(AVT)的有效候选者。你根本无法做到这一点。

来自XSLT 2.0 spec

  

[定义:在指定为属性值的属性中   模板,例如文字结果元素的属性,   表达式可以通过用curly包围表达式来使用   括号({})]。

模式未在规范中指定为AVT,因此您无法执行此操作。

答案 2 :(得分:0)

  

我收到无法编译样式表的错误。的价值   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(每个值乘以2):

<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>