2010-02-05 97 views
7

我有一个问题,试图找出xslt上的var范围。我实际上想要做的是忽略具有重复“旅游编码”的“旅行”标签。XSLT中的变量范围

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

所需的输出: 布达佩斯伦敦罗马

+1

标题问题的本来..类似, – 2010-02-08 08:55:07

回答

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法里亚斯只是张贴解答,说明如何做到这一点。

+0

感谢队友,尽管出了4个副本,但它仍然显示2,但它让我更接近我的想法。 – Zoheir 2010-02-07 23:04:35

+0

@Mazzi:它呢?当我用你的样品测试它时没有。如果您发布与您一起工作的实际XML和XSL,我相信我可以指出哪些问题。 – Tomalak 2010-02-07 23:36:09

+0

@Tomalak:xsl和xml有点笨重,我尽量简化它们。我不知道如果stackoverflow有发送消息功能?!所以我可以直接发给你。 – Zoheir 2010-02-08 00:39:50

24

不能更改XSLT中的变量。

因为XSLT是一种功能性语言,所以您需要更多地考虑它作为functional programming而不是程序性的。想想像这样的伪代码的变量作用域:

variable temp = 5 
call function other() 
print temp 

define function other() 
    variable temp = 10 
    print temp 

你期望输出是什么?它应该是10 5而不是10 10,因为函数other中的temp与该函数外部的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的值已设置,它不能在稍后重新定义。在函数式编程中,变量更像只读参数,因为它们可以设置,但以后不能更改。为了在任何函数式编程语言中使用变量,您必须正确理解这一点。

+0

对不起队友“从XML使用XSLT删除重复节点”,你的回答是伟大的,但我有改变的问题一点得到它接近我之后。谢谢 – Zoheir 2010-02-05 04:17:29

+5

@Mazzi:总是写出你想要做的事(输入 - >想要的输出)的问题,而不仅仅是*你怎么认为你可以做到这一点。在这种情况下:您不想更改变量值,您想要从输入中生成唯一值列表。 – Tomalak 2010-02-05 09:49:35

+1

+1,_really_伟大的答案,@ Welbog – 2010-02-05 09:56:08

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>