2010-07-02 15 views
6
<xsl:choose> 
    <xsl:when test="long convoluted expression"> 
     <xsl:element name="Class">123</xsl:element> 
     <a lot more xsl:elements> 
    </xsl:when> 
    <xsl:when test="next very long expression"> 
     <xml:element name="Class">124</xsl:element> 
     <a lot more xsl:elements> 
    </xsl:when> 
    <tens of more similar xsl:when> 
</xsl:choose> 

¿Hay alguna manera de simplificar el código anterior con condicionales? Para cada valor de clase que se les da a los objetos, siguen decenas de filas con atributos adicionales. Estos atributos forman conjuntos de acuerdo con el valor de la clase. La clase 0-99 tiene un conjunto de etiquetas adicionales, clase 100-199 por segundo, formando una pesadilla de mantenimiento cuando cambia uno de estos conjuntos de etiquetas adicionales.Condiciones XSLT/alcance variable

que estaba considerando una solución como esta:

<xsl:choose> 
    <xsl:when test="long convoluted expression"> 
     <xml:element name="Class">123</xsl:element> 
     <xsl:variable name="outputclass" select="123"> 
    </xml:when> 
    <xsl:when test="next very long expression"> 
     <xml:element name="Class">124</xsl:element> 
     <xsl:variable name="outputclass" select="124"> 
    </xsl:when> 
</xsl:choose> 
<xsl:choose> 
    <xsl:when test="$outputclass > 99"> 
     <xml:elements for classes 100-199 here> 
    </xsl:when> 
<xsl:choose> 

Pero por supuesto esto no funciona, como la variable outputclass no está en el mismo ámbito. ¿Alguna forma de resolver esto?

+0

Esto es confuso.Puede ser más claro si agrega un documento de entrada y salida de muestra. –

+0

Buena pregunta (+1). Vea la mejor solución * real * en mi respuesta, con un código completo y explicaciones. :) –

Respuesta

6

La mejor solución para este problema es bien conocido:

<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="/"> 
    <xsl:variable name="voutType"> 
     <xsl:choose> 
     <xsl:when test="long convoluted expression">123</xsl:when> 
     <xsl:when test="next very long expression">124</xsl:when> 
     <!-- Etcetera ... --> 
     </xsl:choose> 
    </xsl:variable> 

    <Class><xsl:value-of select="$voutType"</Class> 
     <xsl:choose> 
      <xsl:when test="not($voutType > 99)"> 
       <!-- elements for classes 0 - 99 here --> 
      </xsl:when> 
      <xsl:otherwise> 
       <!-- elements for classes 100-199 here --> 
      </xsl:otherwise> 
     <xsl:choose> 
</xsl:template> 
</xsl:stylesheet> 

Ten en cuenta:

  1. Con el fin de dar valores a una variable ($voutType), la <xsl:choose> instrucción debe ser dentro el cuerpo de <xsl:variable>

  2. Sólo es necesario especificar el elemento <Class> vez - fuera de todo lo demás.

  3. No es necesario que use <xsl:element> si se conoce el nombre del elemento.

+0

Esta es una hermosa solución. Tan fácil de mantener como las otras soluciones, pero aún más corto. Que puedes anidar elegir dentro de una variable que no sabía. ¡Gracias! – diskis

+0

@diskis: estoy muy contento de que hayas rechazado mi respuesta. No parecía suficiente, pero pensé que podría ayudarte a avanzar en la dirección correcta. Esta definitivamente parece ser la mejor manera. – MJB

+0

¿qué hace que una solución sea exactamente '' notoriamente conocida''? – n611x007

0

Solo he hecho XSLT varias veces, pero cada vez parece una gran pesadilla de mantenimiento. En cualquier caso, creo que podría establecer una variable que diga qué clase es y luego llamar a una función como xsl: coincidencia de plantilla con la clase como arg. Declararía esa función como xsl: nombre de la plantilla, porque no desea que coincida automáticamente. Dentro de la función, deberías poder escribir esos 100 valores. No estoy seguro de si esto ayuda, pero organiza el código de una manera que podría hacerlo.

+0

Sí, gracias. Las pruebas rápidas muestran que esto funcionará perfectamente para mis propósitos. Ahora solo para repasar la sintaxis xml: with-param, y me irá bien con algunas plantillas menos. – diskis

1

Si usted está tratando de hacer más fácil para especificar un grupo de atributos (! no etiquetas aka elementos), entonces suena a mí como conjuntos de atributos son lo que necesita, y puede que no necesite variables:

http://www.w3.org/TR/xslt#attribute-sets

eso supone que el atributo de los propios valores no dependen del valor de la clase; solo su presencia es

Si los elementos son realmente lo que quiere decir, intente utilizar plantillas con nombre con un parámetro de entrada. En el nivel superior de la hoja de estilos:

<xsl:template name="classdef"> 
    <xsl:param name="classid"/> 
    <!-- Note: I put the class elem in here so I don't have to 
     write individual class ids more than once --> 
    <xsl:element name="Class"><xsl:value-of select="$classid"/></xsl:element> 
    <xsl:choose> 
    <xsl:when test="$classid > 99"> 
     ... 
    </xsl:when> 
    </xsl:choose> 
</xsl:template> 

y en su otra plantilla:

<xsl:call-template name="classdef"> 
    <xsl:with-param name="classid">124</xsl:with-param> 
</xsl:call-template> 

Ver http://www.w3.org/TR/xslt#variables para obtener más información sobre params.

+0

Gracias, esta es esencialmente la misma solución que MJB publicado, y lo hará perfectamente para mis necesidades. Volveré y le daré un voto positivo cuando tenga suficiente reputación para hacerlo :) – diskis