In my CMS it is possible to create a new article, and choose an image to be shown on that article. When an image is chosen, a thumbnail of the image will automatically be cr
A general solution involving only standard XSLT is somewhat hard since you have to search the string from the end. You can split your filename usings two functions, substring-before-last and substring-after-last. Unfortunately, these functions are not part of XSLT. You can Google and try to find implementations. Assuming you have these two functions implemented as XSLT templates you can then use the following template to generate thumbnail names:
<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>
You can use the template like this (assuming the variable $file-name contains the name of the image):
<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>
Given the image's filename in $filename,
If you can assume that all images will end in ".jpg" and won't have ".jpg" elsewhere in the filename, then this should work:
<img src="{substring-before($filename, '.jpg')}_thumbnail.jpg" ... />
If you don't know the image type (like, you want to handle gif and png as well), or if you think the extension may occur multiple times in the filename ("image.jpg.jpg"), then you will want a template to help you:
<?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>
Off the top of my head:
<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>
Called as:
<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>
Yields:
image.2horses
Have a look at the XPath functions overview at W3Schools, specifically the substring-before
method.
I believe XPath functions operating on string might help you. I would try with some simple replace
or translate
.
XSLT 2 solution using regexp:
replace($filename, '(\.[^\.]*)$', concat('_thumbnail', '$1'))
Original answer (also XSLT 2): This removes all after the last separator (including the separator). So below the $separatorRegexp could be '\.jpg' or just '\.' and the $separator '.jpg' or '.' in the other case.
string-join(reverse(remove(reverse(tokenize($filename, $separatorRegexp)),1)),$separator)
Eventually the '_thumbnail.jpg' can be appended with concat.