2012-09-06 8 views
12

Quiero aplicar una plantilla con un modo que dependa de un valor de variable.Utilice el valor de una variable en el modo de aplicar-templates

<xsl:variable name="mode" select="@attribute"/> 
<xsl:apply-templates mode="{$mode}"/> 

Me sale el error de que la hoja de estilo no se puede compilar. El valor del modo debe ser un QName, pero es "{$ mode}".

¿Existe la posibilidad de utilizar modos dependientes de variables?

+0

Lo que se quiere hacer es sintácticamente incorrecto, pero es posible * * en XSLT 1.0 para lograr el mismo efecto, utilizando el principio de "referencia de plantilla" que es la base de la biblioteca FXSL. –

+0

¡Gracias por esta idea! Traté de entenderlo, pero soy nuevo en XSLT y no tengo mucha experiencia con programación funcional. Para el caso descrito, es "sobre ingeniería". Tal vez, pueda usarlo algunas veces, cuando tenga más experiencia con él. – maria90

+0

maria90, basta con saber que existe tal técnica, y luego usarla siempre que sea necesario. –

Respuesta

7

La única opción que tiene que utilizar un cierto modo basado en una expresión es utilizar

<xsl:choose> 
    <xsl:when test="@attribute = 'foo'"> 
     <xsl:apply-templates mode="bar"/> 
    </xsl:when> 
    <xsl:otherwise> 
     <xsl:apply-templates/> 
    </xsl:otherwise> 
</xsl:choose> 

o el mismo con un xsl:if. El valor del atributo mode debe ser un QName en XSLT 1.0, respectivamente, en XSLT 2.0 permite un QName o tokens especiales como #current o #default '. Pero no puede calcular un valor de mode en tiempo de ejecución.

+0

Esta fue mi primera idea para resolver el problema. Quería evitar probar valores específicos de la variable. Sin embargo, lo usaré de esta manera porque FXSL es un poco pesado para mí. – maria90

3

modo no es un candidato válido para Plantillas de valores de atributo (AVT). Simplemente no puedes hacer esto.

Desde el XSLT 2.0 spec:

[Definición: En un atributo que se designa como un valor de atributo plantilla, como un atributo de un elemento resultado literal, una expresión puede ser utilizado por rodea la expresión con corchetes rizados ({})].

modo no está designado como AVT en la especificación, por lo ou no pueden hacer esto.

0

Me sale el error de que la hoja de estilo no se puede compilar. El valor del modo debe ser un QName, pero es "{$ mode}".

¿Existe la posibilidad de utilizar modos dependientes de variables?

No, esto no es compatible con ninguna versión XSLT - 1.0, 2.0 o 3.0.

Como usted está tratando de hecho para emular funciones de orden superior (HOF), es posible utilizar el principio subyacente de FXSL hacer esto en XSLT 1.0.

FXSL 1.x es una biblioteca de plantillas escritas en XSLT 1.0 puro que admite/emula HOF.

Aquí es una solución completa basada en estos principios:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:f="http://fxsl.sf.net" exclude-result-prefixes="f"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

    <f:inc/> 
    <f:double/> 

<xsl:variable name="vModeInc" select="document('')/*/f:inc[1]"/> 
<xsl:variable name="vModeDouble" select="document('')/*/f:double[1]"/> 

<xsl:template match="node()|@*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="/*"> 
    <nums> 
    <xsl:apply-templates select="$vModeInc"> 
     <xsl:with-param name="pNodes" select="node()"/> 
    </xsl:apply-templates> 
    </nums> 
============== 
    <nums> 
    <xsl:apply-templates select="$vModeDouble"> 
     <xsl:with-param name="pNodes" select="node()"/> 
    </xsl:apply-templates> 
    </nums> 
</xsl:template> 

<xsl:template match="f:inc"> 
    <xsl:param name="pNodes"/> 
    <xsl:apply-templates select="$pNodes" mode="incr"/> 
</xsl:template> 

<xsl:template match="f:double"> 
    <xsl:param name="pNodes"/> 
    <xsl:apply-templates select="$pNodes" mode="double"/> 
</xsl:template> 

<xsl:template match="num" mode="incr"> 
    <num><xsl:value-of select=".+1"/></num> 
</xsl:template> 

<xsl:template match="num" mode="double"> 
    <num><xsl:value-of select=".*2"/></num> 
</xsl:template> 
</xsl:stylesheet> 

Cuando se aplica esta transformación en el siguiente documento XML:

<nums> 
    <num>01</num> 
    <num>02</num> 
    <num>03</num> 
    <num>04</num> 
    <num>05</num> 
    <num>06</num> 
    <num>07</num> 
    <num>08</num> 
    <num>09</num> 
    <num>10</num> 
</nums> 

el resultado deseado, correcta es producido - los elementos nums/num procesados ​​en uno (cada uno) de los dos modos disponibles, de pendiente en la variable especificada - $vModeInc (1 añadido a cada valor) o $vModeDouble (cada valor se multiplica por dos):

<nums> 
    <num>2</num> 
    <num>3</num> 
    <num>4</num> 
    <num>5</num> 
    <num>6</num> 
    <num>7</num> 
    <num>8</num> 
    <num>9</num> 
    <num>10</num> 
    <num>11</num> 
</nums> 
============== 
    <nums> 
    <num>2</num> 
    <num>4</num> 
    <num>6</num> 
    <num>8</num> 
    <num>10</num> 
    <num>12</num> 
    <num>14</num> 
    <num>16</num> 
    <num>18</num> 
    <num>20</num> 
</nums> 
+0

+1 Eso es inteligente. No he estado al día con FXSL, pero he deseado tener el tiempo para hacerlo. :-) Para cualquier otra persona que esté leyendo, vale la pena su tiempo para rastrear a través del XSLT de arriba y ver lo que está haciendo. – LarsH

+0

@LarsH, gracias, solo lea el documento Extreme Markup Languages ​​en FXSL 2 - no toma demasiado tiempo. :) –

+0

¿Puedes dar un enlace a ese documento? Busqué en Google y encontré esto: http://fxsl.sourceforge.net/ que tiene un enlace a 2 documentos, los cuales están rotos. Oh, ¿es esto? http://conferences.idealliance.org/extreme/html/2006/Novatchev01/EML2006Novatchev01.html – LarsH

Cuestiones relacionadas