2009-07-13 13 views
9

En mi CMS, es posible crear un nuevo artículo y elegir una imagen para mostrar en ese artículo. Cuando se elige una imagen, también se creará automáticamente una miniatura de la imagen.Eliminación de los últimos caracteres en una cadena XSLT

Si la imagen cargada se llama imagen.jpg, a continuación, la miniatura correspondiente será automáticamente nombrado image_thumbnail.jpg.

ahora me gustaría utilizar la imagen en miniatura, en todas partes en el sitio web donde se menciona el artículo, excepto en el propio artículo (donde la imagen original debe ser grande se muestra).

Pero, ¿cómo puedo hacer eso?

Me imagino que si pudiera conseguir el nombre original de la imagen, y luego dividirlo antes del sufijo (.jpg, .png, .jpeg etc.) y codificar _thumbnail después del nombre, entonces eso sería suficiente.

En otras palabras, quiero tomar el nombre completo del archivo y cortarlo en dos partes para poder insertar la cadena _thumbnail entre las dos partes.

Quizás eso funcione, pero ¿qué ocurre si se carga una imagen llamada image.2horses.jpg (un archivo con más de un punto en el nombre de archivo)? Un corte ingenuo antes del '.' no funcionaria aqui

¿Hay alguna forma de evitar esto? Tal vez al cortar el nombre del archivo antes de los últimos 4 (.jpg, .png) o 5 (.jpeg) caracteres?

Respuesta

9

Teniendo en cuenta el nombre de archivo de la imagen en $ archivo,

Si se puede suponer que todas las imágenes terminan en ".jpg" y no tendrán ".jpg" en otros lugares en el nombre del archivo, entonces esto debería funcionar:

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

Si usted no sabe el tipo de imagen (como, desea manejar gIF y PNG también), o si cree que la extensión puede aparecer varias veces en el nombre del archivo ("ima ge.jpg.jpg "), entonces usted va a querer una plantilla para ayudarle a:

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

Su solución es más o menos igual a la mía, puedo devolver el +1 fácilmente. ;-) – Tomalak

+0

Lo siento, -1 de mí, supuestos como este conducen al código erróneo. Trabajo con herramientas que hacen muchas conversiones y simplemente agregan la nueva extensión al final, para que pueda experimentar fácilmente algo llamado image.jpg.tif.jpg –

1

Tener un vistazo a la XPath functions overview at W3Schools, específicamente el método substring-before.

+0

¿Qué sucede si hay un nombre de archivo con más de un punto? P.ej. Image.09.07.11.jpg, e hice una subcadena-before ('Image.09.07.11.jpg', '.')? ¿No obtendré "Imagen" y nada más? –

+0

Puede obtener el último punto de la cadena por recursión o por un bucle. Ver http://www.biglist.com/lists/xsl-list/archives/200102/msg00838.html – Scoregraphic

2

Una solución general que involucra solo XSLT estándar es algo difícil ya que tiene que buscar la cadena desde el final. Puede dividir su nombre de archivo utilizando dos funciones, subserie-anterior y subserie-posterior-última. Desafortunadamente, estas funciones no son parte de XSLT. Puede buscar en Google e intentar encontrar implementations.Suponiendo que ha estas dos funciones implementadas como plantillas XSLT a continuación, puede utilizar la siguiente plantilla para generar nombres 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> 

Usted puede utilizar la plantilla como esto (suponiendo que la variable $ nombre de archivo contiene el nombre de la imagen):

<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

de la parte superior de mi cabeza:

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

llamado como:

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

Rendimiento:

image.2horses 
+0

Tu código también funcionó Tomalak, pero tuve que marcar la respuesta de Chris Nielsen como la correcta, porque resolvió mi problema problema al máximo. Si pudiera, marcaría el suyo como correcto también :) –

+0

+1; Me gusta su solución generalizada mejor que la mía de todos modos. –

0

XSLT 2 solución usando expresiones regulares:

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

Respuesta original (también XSLT 2): Esto elimina toda después del último separador (incluido el separador). Por lo tanto, debajo de $ separatorRegexp podría ser '\ .jpg' o simplemente '\'. y el $ separador '.jpg' o '.' en el otro caso.

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

Eventualmente el '_thumbnail.jpg' se puede agregar con concat.

+0

Cuando probé esto con 'image.2horses.jpg' (de la pregunta) obtengo 'image.2horses'. (Probablemente porque solo hay un elemento en la secuencia, por lo que no hay nada para juntar). Un enfoque diferente de XPath 2.0 sería 'replace ($ filename, $ separatorRegexp, concat ($ separator, '$ 1'))' where $ separatorRegexp = '(\. [^ \.] *) $' y $ separator = '_thumbnail'. Esto le daría 'image.2horses_thumbnail.jpg' como resultado. –

+0

Aquí está el reemplazo sin las variables: 'replace ($ filename, '(\. [^ \.] *) $', Concat ('_ thumbnail', '$ 1'))' –

+0

Daniel Haley: Eso es lo que pretendía. Agregar el _thumbnail.jpg ya es trivial. Y como mi solución implica una expresión regular de todos modos, entonces aparentemente es mejor. –

Cuestiones relacionadas