2010-07-12 11 views
6

Quando i miei fogli di stile XSL incontra questo nodo:Trasformare un valore intero a un carattere ripetuto

<node attribute="3"/> 

... dovrebbe trasformarlo in questo nodo:

<node attribute="***"/> 

mio modello corrisponde l'attributo e lo ricrea, ma non so come impostare il valore su: il carattere '*' ripetuto tante volte quanto il valore dell'attributo originale.

<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> 

Grazie!

+0

Quale processore XSLT stai usando? – AakashM

+1

Supponiamo che possiamo farlo ... perché? '3' non è molto più facile da lavorare a livello di dati? '***' sembra avere senso solo nel livello di presentazione. – polygenelubricants

+0

Buona domanda (+1). Vedi la mia risposta per una soluzione XSLT 2.0. –

risposta

8

Un approccio abbastanza sporco, ma pragmatica sarebbe quella di effettuare una chiamata su ciò che è il numero più alto mai aspettate di vedere in attribute, quindi utilizzare

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

dove si ha il maggior numero di * s in quella stringa come quella numero massimo che ti aspetti Ma spero che ci sia qualcosa di meglio!

+0

+1 questo è l'approccio più veloce se si conosce il massimo n. di ripetizioni in anticipo. – Tomalak

+0

Cosa faccio, quindi funzionerà. –

9

generico, soluzione ricorsiva (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> 

chiamata come:

<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

Aggiungendo alle due belle risposte di @AakashM e @Tomalak, questo è fatto naturalmente in XSLT 2.0:

Questa trasformazione 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> 

se applicato sul documento XML fornito:

<node attribute="3"/> 

produce il risultato voluto:

<node attribute="***"/> 

Do atto come viene utilizzato il XPath 2.0 to operatore nell'istruzione <xsl:for-each>.

+0

+1 per fornire la risposta XSLT 2.0 obbligatoria! :-) – Tomalak

+0

Dovrò provare se il software (InDesign CS3) supporta XSLT 2.0, ma buona risposta, grazie! –

Problemi correlati