2012-01-31 19 views
6

Quiero usar el atributo @sourcename de la siguiente manera, para su conveniencia:XSLT: la asignación de las variables iguales a uno de los dos casos

Si @sourcename tiene un punto en ella, la parte delante del primer punto debe ser asignado a $srcgroup y la parte posterior al primer punto debe asignarse a $srcword.

De lo contrario $srcgroup debe establecerse igual a @sourcename y $srcword debe ser la cadena vacía.

En ambos casos, quiero hacer las mismas cosas usando $srcgroup y $srcword.

He intentado esto con el siguiente fragmento:

<xsl:choose> 
    <xsl:when test="contains(@sourcename, '.')">  
    <xsl:variable name="srcgroup" select="substring-before(@sourcename, '.')"/> 
    <xsl:variable name="srcword" select="substring-after(@sourcename, '.')" /> 
    </xsl:when> 
    <xsl:otherwise> 
    <xsl:variable name="srcgroup" select="@sourcename" /> 
    <xsl:variable name="srcword" />      
    </xsl:otherwise> 
</xsl:choose> 

<foo group="{$srcgroup}" word="{$srcword}" /> 
<!-- there's some other more complicated users of $srcgroup and $srcword --> 

El problema es que aparece un error (esto es usar JAXP en Java):

ERROR: [my xsl file]: line 35: Variable or parameter 'srcgroup' is undefined.' 
FATAL ERROR: 'Could not compile stylesheet' 
Exception in thread "main" javax.xml.transform.TransformerConfigurationException: Could not compile stylesheet 
    at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl.newTemplates(TransformerFactoryImpl.java:825) 

Si entiendo este derecho, I' Supongo que las variables solo tienen el alcance del caso particular en el bloque <xsl:choose>. ¿Hay alguna forma de evitar esto? No quiero tener que repetir mi otro código dos veces.


p.s. Encontré una solución:

<xsl:variable name="srcgroup" select="substring-before(concat(@sourcename, '.'), '.')" /> 
<xsl:variable name="srcword" select="substring-after(@sourcename, '.')" /> 

pero todavía quiero saber cómo resolver mi pregunta original, para referencia futura.

Respuesta

5

sólo tiene que utilizar (no condicionales necesarias):

<xsl:variable name="srcgroup" select= 
    "substring-before(concat(@sourcename, '.'), '.')"/> 

    <xsl:variable name="srcword" select= 
    "substring-after(@sourcename, '.')"/> 

ejemplo completo:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="x|y"> 
    <xsl:variable name="srcgroup" select= 
    "substring-before(concat(@sourcename, '.'), '.')"/> 

    <xsl:variable name="srcword" select= 
    "substring-after(@sourcename, '.')"/> 

    $srcgroup = "<xsl:value-of select="$srcgroup"/>" 
    $srcword = "<xsl:value-of select="$srcword"/>" 
</xsl:template> 
</xsl:stylesheet> 

cuando se aplica en este documento XML:

<t> 
    <x sourcename="a.b.c"/> 
    <y sourcename="noDots"/> 
</t> 

el resultado deseado se produce en ambos casos:

$srcgroup = "a" 
    $srcword = "b.c" 

    $srcgroup = "noDots" 
    $srcword = "" 

Explicación: la lógica innecesaria evitado mediante la colocación de un centinela .


comparar esto con la sintaxis mucho más detallado condicional:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="x|y"> 
    <xsl:variable name="srcgroup"> 
    <xsl:choose> 
    <xsl:when test="contains(@sourcename, '.')"> 
     <xsl:value-of select="substring-before(@sourcename, '.')"/> 
    </xsl:when> 
    <xsl:otherwise> 
     <xsl:value-of select="@sourcename"/> 
    </xsl:otherwise> 
    </xsl:choose> 
    </xsl:variable> 

    <xsl:variable name="srcword"> 
    <xsl:choose> 
    <xsl:when test="contains(@sourcename, '.')"> 
     <xsl:value-of select="substring-after(@sourcename, '.')"/> 
    </xsl:when> 
    <xsl:otherwise/> 
    </xsl:choose> 
    </xsl:variable> 

    $srcgroup = "<xsl:value-of select="$srcgroup"/>" 
    $srcword = "<xsl:value-of select="$srcword"/>" 
</xsl:template> 
</xsl:stylesheet> 

Cuando se aplica esta transformación más detallado en el documento mismo XML (arriba), de nuevo el mismo resultado correcto es producido:

$srcgroup = "a" 
    $srcword = "b.c" 

    $srcgroup = "noDots" 
    $srcword = "" 
+0

Si lee mi comentario al final de mi publicación, verá que me di cuenta de que ... esto es útil para manejar ese caso específico, pero no responde mi pregunta sobre cómo asignar una variable de manera condicional. –

+0

Por cierto, tiene un error: no debería usar el concat en el caso 'substring-after', ya que produce un punto extra al final de' srcword' en el caso no vacío. –

+0

@JasonS: He solucionado mi respuesta. Y sí, responde exactamente a la pregunta de cómo definir condicionalmente una variable. Como puede ver, no son necesarios condicionales para definir las variables de la manera deseada. –

5

Es de la misma familia:

<xsl:variable name="srcgroup"> 
<xsl:choose...> 
    ... 
</xsl:choose> 
</xsl:variable> 
+0

+1, pero podría ayudarme con la sintaxis? No estoy familiarizado con cómo usar '' sin un 'select =' –

+0

El contenido de la etiqueta es el valor de la variable. Coloque '' donde colocará la asignación en ''. –

+0

Y mira aquí - http://www.w3.org/TR/xslt - en caso de duda, recurso realmente útil. –

Cuestiones relacionadas