2010-07-12 12 views
6

Cuando mis hojas de estilo XSL encuentros este nodo:Transformar un valor entero a un carácter repetido

<node attribute="3"/> 

... debe transformarlo en este nodo:

<node attribute="***"/> 

Mi plantilla coincide con el atributo y lo recrea, pero no sé cómo configurar el valor: el carácter '*' se repite tantas veces como el valor del atributo original.

<xsl:template match="node/@attribute"> 
    <xsl:variable name="repeat" select="."/> 
    <xsl:attribute name="attribute"> 
     <!-- What goes here? I think I can do something with $repeat... --> 
    </xsl:attribute> 
</xsl:template> 

Gracias!

+0

¿Qué procesador XSLT estás usando? – AakashM

+1

Supongamos que podemos hacer esto ... ¿por qué? ¿No es '3' mucho más fácil trabajar en la capa de datos? '***' parece tener sentido solo en la capa de presentación. – polygenelubricants

+0

Buena pregunta (+1). Vea mi respuesta para una solución XSLT 2.0. –

Respuesta

8

Un enfoque bastante sucio, pero pragmática sería hacer una llamada en lo que es el número más alto que nunca espera ver en attribute, a continuación, utilizar

substring("****...", 1, $repeat) 

donde se tiene el mayor número de * s en esa cadena como que número máximo que esperas ¡Pero espero que haya algo mejor!

+0

+1 este es el enfoque más rápido si conoce el máximo no. de repeticiones de antemano. – Tomalak

+0

Lo que hago, entonces esto funcionará. –

9

Genérico, solución recursiva (XSLT 1.0):

<xsl:template name="RepeatString"> 
    <xsl:param name="string" select="''" /> 
    <xsl:param name="times" select="1" /> 

    <xsl:if test="number($times) &gt; 0"> 
    <xsl:value-of select="$string" /> 
    <xsl:call-template name="RepeatString"> 
     <xsl:with-param name="string" select="$string" /> 
     <xsl:with-param name="times" select="$times - 1" /> 
    </xsl:call-template> 
    </xsl:if> 
</xsl:template> 

Call como:

<xsl:attribute name="attribute"> 
    <xsl:call-template name="RepeatString"> 
    <xsl:with-param name="string" select="'*'" /> 
    <xsl:with-param name="times" select="." /> 
    </xsl:call-template> 
</xsl:attribute> 
7

Agregando a las dos respuestas agradables de @AakashM y @Tomalak, esto se hace de forma natural en XSLT 2.0:

Esta transformación XSLT 2.0:

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

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

<xsl:template match="@attribute"> 
    <xsl:attribute name="{name()}"> 
    <xsl:for-each select="1 to ."> 
     <xsl:value-of select="'*'"/> 
    </xsl:for-each> 
    </xsl:attribute> 
</xsl:template> 
</xsl:stylesheet> 

cuando se aplica en el documento XML proporcionado:

<node attribute="3"/> 

produce el resultado deseado:

<node attribute="***"/> 

hacer la nota cómo se utiliza el XPath 2.0 to operador en la instrucción <xsl:for-each>.

+0

+1 por proporcionar la respuesta XSLT 2.0 obligatoria. :-) – Tomalak

+0

Tendré que probar si el software (InDesign CS3) es compatible con XSLT 2.0, pero es una buena respuesta, ¡gracias! –

Cuestiones relacionadas