通过动态名称引用XSLT变量

7

I'm stuck with a small problem.

The XSL-File:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0"  
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fn="http://www.w3.org/2005/xpath-functions"> 
<xsl:template match="/"> 


<xsl:variable name="unumericValue" select="10" />
<xsl:variable name="uanotherValue" select="8" />



<xsl:for-each select="/root/try">
<xsl:value-of select="var" />
<xsl:variable name="min"><xsl:value-of select="@minimum" /></xsl:variable>
<xsl:value-of select="@type" />
<xsl:variable name="referenceName"><xsl:value-of select='concat("u",var)' /></xsl:variable>
<xsl:value-of select="$referenceName" />
<xsl:if test='$referenceName > $min'>
<p>Do something.</p>
</xsl:if>
</xsl:for-each>

</xsl:template>
</xsl:stylesheet>

XML文件:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="q1.xsl"?>
<root>
<try type="compare" minimum="9">
<var>numericValue</var>
<something>...</something>
</try>

<try type="compare" minimum="10">
<var>anotherValue</var>
<something>...</something>
</try>
</root>

如您所见,XML文件有两个var元素,应该与XSLT文件中的变量相匹配。然而我不知道哪个语法是正确的。 $referenceName只是我想使用的变量的名称。但我不知道如何将名称引用到现有变量。


3个回答

11

$referenceName并不是指向名称为"unumericValue"的变量的引用,而只是字符串值"unumericValue"等等。因此,它永远不会大于$min。但是,通过一些额外的工作,可以有一个技巧来根据变量名查找变量:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:variable name="numericValue" select="10" />
  <xsl:variable name="anotherValue" select="8" />
  <xsl:variable name="vars" select="document('')/*/xsl:variable" />

  <xsl:template match="/">
    <xsl:variable name="referenceName" select="'numericValue'" />
    <xsl:variable name="referenceValue" select="$vars[@name = $referenceName]/@select" />
    Reference value: <xsl:value-of select="$referenceValue" />
  </xsl:template>
</xsl:stylesheet>

需要注意的一个重要限制是,这只适用于常数数值变量。

以下是一种模拟具有常数字符串值的变量的方法:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                 xmlns:v="variables-node"
>
  <v:variables>
    <v:variable n="numericValue" value="10" />
    <v:variable n="nonNumericValue" value="Hello World" />
  </v:variables>
  <xsl:variable name="vars" select="document('')//v:variables/v:variable" />

    <xsl:template match="/">
      <xsl:variable name="referenceName" select="'nonNumericValue'" />
      <xsl:variable name="referenceValue" select="$vars[@n = $referenceName]/@value" />
      <xsl:value-of select="concat('The variable with the name ', $referenceName, ' has the value ', $referenceValue)"/>
    </xsl:template>
</xsl:stylesheet>

最后,一种模拟具有计算值的变量的方法:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:exslt="http://exslt.org/common"
>

  <xsl:variable name="varsRaw">
    <var n="computedValue" value="{concat('2 + 4 is ', 2 + 4)}" />
    <var n="computedNumber" value="{22 div 7}" />
  </xsl:variable>
  <xsl:variable name="vars" select="exslt:node-set($varsRaw)/var" />

    <xsl:template match="/">
      <xsl:variable name="referenceName" select="'computedValue'" />
      <xsl:variable name="referenceValue" select="$vars[@n = $referenceName]/@value" />
      <xsl:value-of select="concat('The variable with the name ', $referenceName, ' has the value ', $referenceValue)"/>

      <xsl:value-of select="'     '"/>

      <xsl:variable name="referenceName2" select="'computedNumber'" />
      <xsl:variable name="referenceValue2" select="$vars[@n = $referenceName2]/@value" />
      <xsl:value-of select="concat('The variable with the name ', $referenceName2, ' has the value ', $referenceValue2)"/>
    </xsl:template>
</xsl:stylesheet>

最后一种方法可能实际上是最正统的,但需要 XSLT 处理器相关(至少在 XSLT 1.0 中)node-set() 函数。


6
顺便说一下,不要这样做:
<xsl:variable name="min"><xsl:value-of select="@minimum" /></xsl:variable>

当你可以做到这一点时:
<xsl:variable name="min" select="@minimum" />

这不仅啰嗦,而且效率低下 - 当你只需要引用现有节点时,没有必要复制数据并构造新树,这是一项非常昂贵的操作。


当然,你是正确的。这样写起来也更容易和简短 :) - eadrax

1

与大多数编程语言一样,XSLT变量名在运行时不可访问。变量甚至可能在运行时不存在 - 优化器可以玩各种花招,例如在使用变量的点上内联所有对变量的引用。

最好的方法是使用标准名称的变量,并为其提供XML内容。XML中的元素和属性名称在运行时是可访问的,而变量名称则不是。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接