2010-11-17 31 views
18

¿Qué puedo hacer para que este código funcione?XSLT: puedo declarar una variable globalmente y luego asignarle un valor

<xsl:choose> 
    <xsl:when test='type = 6'> 
    <xsl:variable name='title' select='root/info/title' /> 
    </xsl:when> 
    <xsl:when test='type = 7'> 
    <xsl:variable name='title' select='root/name' /> 
    </xsl:when> 
    <xsl:otherwise> 
    <xsl:variable name='title'>unknown</xsl:variable> 
    </xsl:otherwise> 
</xsl:choose> 

<div class='title'> 
    <xsl:value-of select='$title'/> 
</div> 

Esto no funciona porque cuando hago <xsl:value-of select='$title'/>, $title está fuera de alcance. Traté de agregar la línea <xsl:variable name='title'/> fuera del alcance, pero eso tampoco funcionará, porque cuando llamo a <xsl:variable name='title' select='root/info/title' /> por ejemplo, ya he configurado esta variable antes. ¿Cómo debería resolver esto?

+1

Buena pregunta, +1. Ver mi respuesta para tres soluciones diferentes. :) –

Respuesta

27

se puede mover el elegir dentro de la configuración de la variable, así:

<xsl:variable name="title"> 
    <xsl:choose> 
    <xsl:when test='type=6'> 
     <xsl:value-of select="root/info/title" /> 
    </xsl:when> 
    ... 
    </xsl:choose> 
</xsl:variable> 

<div class='title'> 
    <xsl:value-of select="$title" /> 
</div> 
+1

Sí, eso es lo que estaba pensando también. No me gusta mucho esta solución porque tengo más de 20 tipos, cada uno de los cuales necesita 5 variables. Si pudiera enumerar esas 5 variables para cada tipo, una después de la otra, eso haría que mi código fuera mucho más claro, y sería fácil agregar otro tipo. Con la solución que sugiera, si tiene que agregar una línea para el nuevo tipo en cada una de las cinco variables. Pero creo que no habrá otro camino correcto. Lo superaré, gracias por la respuesta :) –

+0

Puedes hacer una plantilla de llamada dentro de cada variable en lugar de una opción, y luego elegir una plantilla. – carols10cents

+0

Oh, pero espera - entonces tendrías que verificar qué variable estás configurando dentro de la plantilla;) – carols10cents

3

No se pueden volver a asignar variables en XSLT (1.0). El nombre probablemente no fue elegido afortunadamente; un xsl:variable es más un símbolo que una variable.

En el ejemplo que puede utilizar lo siguiente:

<xsl:variable name='title'> 
    <xsl:choose> 
    <xsl:when test='type = 6'> 
     <xsl:value-of select='root/info/title' /> 
    </xsl:when> 
    <xsl:when test='type = 7'> 
     <xsl:value-of select='root/name' /> 
    </xsl:when> 
    <xsl:otherwise> 
     <xsl:text>unknown</xsl:text> 
    </xsl:otherwise> 
    </xsl:choose> 
</xsl:variable> 
+0

Es una variable, no un literal constante. Pero es una variable en el paradigma declarativo: más como una variable en una ecuación. –

+1

@Alejandro: Sí, me refería al símbolo/variable como en el sentido matemático descrito por Michael Kay: "Algunas personas han preguntado, ¿por qué llamarlo una variable si no se puede variar? La respuesta está en la matemática tradicional uso de la palabra variable: una variable es un símbolo que puede usarse para denotar diferentes valores en diferentes ocasiones ". (http://gandhimukul.tripod.com/xslt/facts.html) –

11
<xsl:choose> 
    <xsl:when test='type = 6'> 
    <xsl:variable name='title' select='root/info/title' /> 
    </xsl:when> 
    <xsl:when test='type = 7'> 
    <xsl:variable name='title' select='root/name' /> 
    </xsl:when> 
    <xsl:otherwise> 
    <xsl:variable name='title'>unknown</xsl:variable> 
    </xsl:otherwise> 
</xsl:choose> 

<div class='title'> 
    <xsl:value-of select='$title'/> 
</div> 

Esto no tiene' t trabajo

Esta es una pregunta frecuente:

Está definiendo varias variables, cada una llamada $title y cada una es inútil, porque sale inmediatamente del alcance.

La manera apropiada en XSLT 1.0 para definir una variable en función de las condiciones es:

<xsl:variable name="vTitle"> 
    <xsl:choose> 
     <xsl:when test='type = 6'> 
     <xsl:value-of select='root/info/title' /> 
     </xsl:when> 
     <xsl:when test='type = 7'> 
     <xsl:value-of select='root/name' /> 
     </xsl:when> 
     <xsl:otherwise> 
     <xsl:value-of select="'unknown'"/> 
     </xsl:otherwise> 
    </xsl:choose> 
</xsl:variable> 

Otra manera de definir la misma variable: En este caso particular, se desea que la variable tiene una cadena valor. Esto se puede expresar en una forma más compacta:

<xsl:variable name="vTitle2" select= 
"concat(root/info/title[current()/type=6], 
     root/name[current()/type=7], 
     substring('unknown', 1 div (type > 7 or not(type > 5))) 
     ) 
"/> 

Finalmente, en XSLT 2.0 se puede definir una variable tal aún más convenientemente:

<xsl:variable name="vTitle3" as="xs:string" select= 
"if(type eq 6) 
    then root/info/title 
    else if(type eq 7) 
      then root/name 
      else 'unknown' 
"/> 
+0

'porque sale inmediatamente del alcance. Sospeché que este era el caso. ¿Qué etiqueta define el alcance, 'xsl: choose'? Mi problema es que trato de establecer alrededor de 50 variables en función de una sola prueba, y no quiero que cada variable repita la prueba. Traté de hacerlo lógicamente similar a (elegir, (cuando (a), variable *), (cuando (b), variable *)) y salí del alcance ... ¿hay alguna manera de usar un solo prueba para múltiples variables pero aún las mantiene dentro del alcance? – n611x007

1

Además de @ carolclarinet respuesta standar y más compacto @ La respuesta de Dimitre, cuando el resultado depende de algún nodo y le preocupa la reutilización y la extensibilidad, puede aplicar plantillas y usar la coincidencia de patrones, es decir:

<xsl:variable name="title"> 
    <xsl:apply-templates select="type" mode="title"/> 
</xsl:variable> 

<xsl:template match="type[.=6]" mode="title"> 
    <xsl:value-of select='../root/info/title"/> 
</xsl:template> 
<xsl:template match="type[.=7]" mode="title"> 
    <xsl:value-of select='../root/name"/> 
</xsl:template> 
<xsl:template match="type" mode="title"> 
    <xsl:text>unknown</xsl:text> 
</xsl:template> 
-1

Lo estoy haciendo para guardar el valor local en xml xsl:desult _document en la carpeta /temp_variables_loop/loop-data-id_(position()).xml.

Y en el siguiente ciclo, leo archivos de/temp_variables_loop.alias/loop-data-id_(position()-1).xml.

Necesita engañar al motor xsl haciendo alias de /temp_variables_loop en temp_variables_loop.alias porque no puede leer y escribir en el mismo archivo en una xsl.

Cuestiones relacionadas