15

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

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

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

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

4

3 回答 3

9

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

<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 中为 a ,QName在 XSLT 2.0 中分别允许 aQName或特殊标记,如#currentor #default'。但是您无法mode在运行时计算值。

于 2012-09-06T11:57:22.850 回答
5

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

XSLT 2.0 规范

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

模式在规范中没有被指定为 AVT,所以你不能这样做。

于 2012-09-06T11:34:45.007 回答
2

我收到无法编译样式表的错误。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>
于 2012-09-06T12:05:48.677 回答