2009-07-13 20 views
9

Nel CMS è possibile creare un nuovo articolo e scegliere un'immagine da mostrare su quell'articolo. Quando viene scelta un'immagine, verrà automaticamente creata anche una miniatura dell'immagine.Rimozione degli ultimi caratteri in una stringa XSLT

Se l'immagine caricata è chiamato image.jpg, poi la miniatura corrispondente verrà automaticamente nominato image_thumbnail.jpg.

Vorrei ora utilizzare l'immagine di anteprima, in tutto il sito Web in cui è menzionato l'articolo, tranne nell'articolo stesso (dove deve essere mostrata l'immagine originale).

Ma come posso farlo?

Immagino che se ho potuto ottenere il nome originale dell'immagine, e poi dividerlo prima del suffisso (.jpg, .png, .jpeg etc.) e hardcode _thumbnail dopo il nome, allora sarebbe sufficiente.

In altre parole, voglio prendere il nome file completo e dividerlo in due parti, in modo da poter inserire la stringa _thumbnail tra le due parti.

Forse che avrebbe funzionato, ma cosa succede se l'immagine chiamato image.2horses.jpg (un file con più di un punto nel nome del file) è stato caricato? Un taglio ingenuo prima del '.' non funzionerebbe qui

C'è un modo per aggirare questo? Forse tagliando il nome del file prima degli ultimi 4 (.jpg, .png) o 5 (.jpeg) caratteri?

risposta

9

Dato nome del file dell'immagine in $ nomefile,

Se si può assumere che tutte le immagini finiranno in ".jpg" e non avranno ".jpg" altrove nel nome del file, allora questo dovrebbe funzionare:

<img src="{substring-before($filename, '.jpg')}_thumbnail.jpg" ... /> 

Se non si conosce il tipo di immagine (come, si desidera gestire GIF e PNG pure), o se si pensa l'estensione può verificarsi più volte in il nome del file ("ima ge.jpg.jpg "), poi si vuole un modello per aiutarti:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="/"> 
     <p> 
      <xsl:call-template name="image_thumbnail"> 
      <xsl:with-param name="filename" select="'image.jpg'"/> 
      </xsl:call-template> 
     </p> 

     <p> 
      <xsl:call-template name="image_thumbnail"> 
      <xsl:with-param name="filename" select="'image.09.07.11.jpg'"/> 
      </xsl:call-template> 
     </p> 

     <p> 
      <xsl:call-template name="image_thumbnail"> 
      <xsl:with-param name="filename" select="'image.gif'"/> 
      </xsl:call-template> 
     </p> 

     <p> 
      <xsl:call-template name="image_thumbnail"> 
      <xsl:with-param name="filename" select="'image with spaces.jpg'"/> 
      </xsl:call-template> 
     </p> 

     <p> 
      <xsl:call-template name="image_thumbnail"> 
      <xsl:with-param name="filename" select="'image with irregular spaces.jpg'"/> 
      </xsl:call-template> 
     </p> 

     <p> 
      <xsl:call-template name="image_thumbnail"> 
      <xsl:with-param name="filename" select="'image.jpg.again.jpg'"/> 
      </xsl:call-template> 
     </p> 

    </xsl:template> 

    <xsl:template name="image_thumbnail"> 
    <xsl:param name="filename"/> 
     <xsl:choose> 
     <xsl:when test="contains($filename, '.')"> 
      <xsl:variable name="before" select="substring-before($filename, '.')"/> 
      <xsl:variable name="after" select="substring-after($filename, '.')"/> 
      <xsl:choose> 
      <xsl:when test="contains($after, '.')"> 
       <xsl:variable name="recursive"> 
        <xsl:call-template name="image_thumbnail"> 
        <xsl:with-param name="filename" select="$after"/> 
        </xsl:call-template> 
       </xsl:variable> 
       <xsl:value-of select="concat($before, '.', $recursive)"/> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:value-of select="concat($before, '_thumbnail.', $after)"/> 
      </xsl:otherwise> 
      </xsl:choose> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:value-of select="$filename"/> 
     </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 

</xsl:stylesheet> 
+0

La tua soluzione è approssimativamente uguale alla mia, posso restituire il +1 facilmente. ;-) – Tomalak

+0

Scusate, -1 da parte mia, ipotesi come questa conducono al codice buggato. Io lavoro con strumenti che fanno molte conversioni e aggiungono semplicemente la nuova estensione alla fine, quindi potrei facilmente sperimentare qualcosa chiamato image.jpg.tif.jpg –

1

Dai un'occhiata allo XPath functions overview at W3Schools, in particolare al metodo substring-before.

+0

E se c'è un nome di file con più di un punto. Per esempio. Image.09.07.11.jpg, e ho fatto una sottostringa prima ('Image.09.07.11.jpg', '.')? Non otterrei "Immagine" e nient'altro? –

+0

È possibile ottenere l'ultimo punto nella stringa tramite ricorsione o ciclo. Vedi http://www.biglist.com/lists/xsl-list/archives/200102/msg00838.html – Scoregraphic

2

Una soluzione generale che coinvolge solo XSLT standard è piuttosto difficile poiché è necessario cercare la stringa dalla fine. È possibile dividere le funzioni del nome file due funzioni, sottostringa-prima-ultima e sottostringa-dopo-ultima. Sfortunatamente, queste funzioni non fanno parte di XSLT. Puoi cercare su Google e provare a trovare implementations.Supponendo di aver queste due funzioni implementate come modelli XSLT è quindi possibile utilizzare il seguente modello per generare i nomi in miniatura:

<xsl:template name="thumbnail-name"> 
    <xsl:param name="file-name"/> 
    <xsl:call-template name="substring-before-last"> 
    <xsl:with-param name="text" select="$file-name"/> 
    <xsl:with-param name="chars" select="'.'"/> 
    </xsl:call-template> 
    <xsl:text>_thumbnail.</xsl:text> 
    <xsl:call-template name="substring-after-last"> 
    <xsl:with-param name="text" select="$file-name"/> 
    <xsl:with-param name="chars" select="'.'"/> 
    </xsl:call-template> 
</xsl:template> 

È possibile utilizzare il modello come questo (supponendo che il file-nome della variabile $ contiene il nome dell'immagine):

<img> 
    <xsl:attribute name="src"> 
    <xsl:call-template name="thumbnail-name"> 
     <xsl:with-param name="file-name" select="$file-name"/> 
    </xsl:call-template> 
    </xsl:attribute> 
</img> 
19

fuori della parte superiore della mia testa:

<xsl:template name="substring-before-last"> 
    <xsl:param name="string1" select="''" /> 
    <xsl:param name="string2" select="''" /> 

    <xsl:if test="$string1 != '' and $string2 != ''"> 
    <xsl:variable name="head" select="substring-before($string1, $string2)" /> 
    <xsl:variable name="tail" select="substring-after($string1, $string2)" /> 
    <xsl:value-of select="$head" /> 
    <xsl:if test="contains($tail, $string2)"> 
     <xsl:value-of select="$string2" /> 
     <xsl:call-template name="substring-before-last"> 
     <xsl:with-param name="string1" select="$tail" /> 
     <xsl:with-param name="string2" select="$string2" /> 
     </xsl:call-template> 
    </xsl:if> 
    </xsl:if> 
</xsl:template> 

Chiamato come:

<xsl:template match="/"> 

    <xsl:variable name="filename" select="'image.2horses.jpg'" /> 

    <xsl:variable name="basename"> 
    <xsl:call-template name="substring-before-last"> 
     <xsl:with-param name="string1" select="$filename" /> 
     <xsl:with-param name="string2" select="'.'" /> 
    </xsl:call-template> 
    </xsl:variable> 

    <xsl:value-of select="$basename" /> 

</xsl:template> 

Resa:

image.2horses 
+0

Il tuo codice ha funzionato bene anche su Tomalak, ma ho dovuto contrassegnare la risposta di Chris Nielsen come corretta, perché ha risolto il mio problema problema al massimo. Se potessi, segnerei anche il tuo come corretto :) –

+0

+1; Mi piace la tua soluzione generalizzata meglio del mio comunque. –

0

XSLT 2 soluzione con regexp:

replace($filename, '(\.[^\.]*)$', concat('_thumbnail', '$1')) 

risposta originale (anche XSLT 2): Questo rimuove tutto dopo l'ultimo separatore (incluso il separatore). Quindi sotto il $ separatorRegexp potrebbe essere '\ .jpg' o solo '\.' e $ separator ".jpg" o "." nell'altro caso.

string-join(reverse(remove(reverse(tokenize($filename, $separatorRegexp)),1)),$separator) 

Alla fine è possibile aggiungere "_thumbnail.jpg" con concat.

+0

Quando ho provato questo con 'image.2horses.jpg' (da la domanda) ottengo 'image.2horses'. (Probabilmente perché c'è un solo elemento nella sequenza quindi non c'è niente da string-join.) Un approccio diverso a XPath 2.0 sarebbe 'replace ($ filename, $ separatorRegexp, concat ($ separator, '$ 1'))' dove $ separatorRegexp = '(\. [^ \.] *) $' e $ separator = '_thumbnail'. Questo ti darebbe 'image.2horses_thumbnail.jpg' come output. –

+0

Ecco la sostituzione senza le variabili: 'replace ($ filename, '(\. [^ \.] *) $', Concat ('_ thumbnail', '$ 1'))' –

+0

Daniel Haley: Questo è quello che intendevo. L'aggiunta di _thumbnail.jpg è già banale. E poiché la mia soluzione implica comunque una regexp, quindi il tuo è apparentemente migliore. –

Problemi correlati