XSLT中的可变范围

时间:2010-02-05 01:46:47

标签: xslt variables scope

我在尝试找出xslt上的var作用域时遇到了问题。我实际上想要做的是忽略那些有重复'tourcode'的'trip'标签。

示例XML:

<trip>
 <tourcode>X1</tourcode>
 <result>Budapest</result>
</trip>
<trip>
 <tourcode>X1</tourcode>
 <result>Budapest</result>
</trip>
<trip>
 <tourcode>X1</tourcode>
 <result>Budapest</result>
</trip>
<trip>
 <tourcode>Y1</tourcode>
 <result>london</result>
</trip>
<trip>
 <tourcode>Y1</tourcode>
 <result>london</result>
</trip>
<trip>
 <tourcode>Z1</tourcode>
 <result>Rome</result>
</trip>

XSLT处理器:

<xsl:for-each select="trip">    
    <xsl:if test="not(tourcode = $temp)">
      <xsl:variable name="temp" select="tour"/>
      // Do Something (Print result!)
    </xsl:if>
</xsl:for-each>

期望的输出: 布达佩斯伦敦罗马

3 个答案:

答案 0 :(得分:24)

无法更改XSLT中的变量。

您需要将其视为functional programming而不是过程,因为XSLT是一种功能语言。想想像这个伪代码那样的变量范围:

variable temp = 5
call function other()
print temp

define function other()
  variable temp = 10
  print temp

您对输出的期望是什么?它应该是10 5,而不是10 10,因为函数temp内的other与该函数外的temp不是同一个变量。

在XSLT中也是如此。变量一旦创建,就无法重新定义,因为它们是设计的一次写入,多次读取的变量。

如果要有条件地定义变量的值,则需要有条件地定义变量,如下所示:

<xsl:variable name="temp">
  <xsl:choose>
    <xsl:when test="not(tourcode = 'a')">
      <xsl:text>b</xsl:text>
    </xsl:when>
    <xsl:otherwise>
      <xsl:text>a</xsl:text>
    </xsl:otherwise>
  </xsl:choose>
</xsl:variable>
<xsl:if test="$temp = 'b'">
  <!-- Do something -->
</xsl:if>

变量仅在一个地方定义,但其值是有条件的。现在temp的值已设置,以后无法重新定义。在函数式编程中,变量更像是只读参数,因为它们可以设置但不能在以后更改。您必须正确理解这一点才能在任何函数式编程语言中使用变量。

答案 1 :(得分:8)

  

期望输出:布达佩斯伦敦罗马

您所追求的是按城市名称​​分组输出。在XSLT中有两种常见的方法。

其中一个就是:

<xsl:template match="/allTrips">
  <xsl:apply-templates select="trip" />
</xsl:template>

<xsl:template match="trip">
  <!-- test if there is any preceding <trip> with the same <result> -->
  <xsl:if test="not(preceding-sibling::trip[result = current()/result])">
    <!-- if there is not, output the current <result> -->
    <xsl:copy-of select="result" />
  </xsl:if>
</xsl:template>

另一个被称为Muenchian分组,而@Rubens Farias刚刚发布了一个答案,显示了如何做到这一点。

答案 2 :(得分:4)

试试这个:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:key name="trip" match="trip" use="result" />

  <xsl:template match="/trips">

    <xsl:for-each select="trip[count(. | key('trip', result)[1]) = 1]">
      <xsl:if test="position() != 1">, </xsl:if>
      <xsl:value-of select="result"/>
    </xsl:for-each>

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