2010-02-05 8 views
7

Tengo un problema al tratar de determinar var scoping en xslt. Lo que realmente quiero hacer es ignorar las etiquetas de 'viaje' que tienen un 'tourcode' repetido.Alcance de la variable en XSLT

XML de ejemplo: Procesador

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

salida deseada: Budapest Londres Roma

+1

Título de la pregunta habría sido algo así .., "Extracción de nodos duplicados de XML mediante XSLT" –

Respuesta

8

salida deseada: Budapest Londres Roma

lo que está después es agrupar la producción en nombre de la ciudad. Hay dos formas comunes de hacer esto en XSLT.

Uno de ellos es la siguiente:

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

Y el otro se llama agrupación Muenchian y @Rubens Farías acaba de publicar una respuesta que muestra cómo hacerlo.

+0

Gracias amigo, aunque de 4 duplicados todavía muestra 2, pero me está acercando más a lo que tenía en mente. – Zoheir

+0

@Mazzi: ¿Sí? No lo hice cuando lo probé con tu muestra. Si publicas el XML y el XSL reales con los que trabajas, estoy seguro de que puedo señalar lo que está mal. – Tomalak

+0

@Tomalak: el xsl y xml son un poco voluminosos, traté de simplificarlos tanto como sea posible. No sé si stackoverflow tiene una funcionalidad de envío de mensajes? Entonces puedo enviartelo directamente. – Zoheir

24

Usted no puede cambian las variables en XSLT.

Debe considerarlo más como functional programming en lugar de procedimiento, porque XSLT es un lenguaje funcional. Piense en el ámbito de las variables en algo como esto pseudocódigo:

variable temp = 5 
call function other() 
print temp 

define function other() 
    variable temp = 10 
    print temp 

¿Qué espera que la salida sea? Debe ser 10 5, no 10 10, porque temp dentro de la función other no es la misma variable que temp fuera de esa función.

Pasa lo mismo en XSLT. Las variables, una vez creadas, no se pueden redefinir porque son de escritura única, leídas, muchas variables por diseño.

Si desea realizar el valor de una variable definida de forma condicional, tendrá que definir la variable condicional, así:

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

La variable sólo se define en un solo lugar, pero su valor es condicional. Ahora que el valor de temp está establecido, no puede redefinirse más tarde. En la programación funcional, las variables son más como parámetros de solo lectura en el sentido de que se pueden establecer pero no se pueden cambiar más adelante. Debe comprender esto correctamente para usar variables en cualquier lenguaje de programación funcional.

+0

siento compañero, que respuesta fue grande, sin embargo tengo que cambiar la pregunta un poco para llegar más cerca de lo que yo Estoy después.Gracias – Zoheir

+5

@Mazzi: siempre escriba la pregunta acerca de lo que quiere hacer (entrada-> resultado deseado), nunca solo hacia * cómo * cree que puede hacerlo. En este caso: no desea cambiar los valores de las variables, desea generar una lista de valores únicos a partir de la entrada. – Tomalak

+1

+1, _really_ gran respuesta, @Welbog –

4

Prueba esto:

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