我在尝试找出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>
期望的输出: 布达佩斯伦敦罗马
答案 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>