【问题标题】:Removing the last characters in an XSLT string删除 XSLT 字符串中的最后一个字符
【发布时间】:2009-07-13 13:26:53
【问题描述】:

在我的 CMS 中,可以创建新文章,然后选择要在该文章上显示的图像。选择图像后,也会自动创建图像的缩略图。

如果上传的图片名为image.jpg,那么对应的缩略图会自动命名为image_thumbnail.jpg。

我现在想在网站上所有提及文章的地方使用缩略图,文章本身除外(应该显示原始大图)。

但是我该怎么做呢?

我想如果我能得到图像的原始名称,然后在后缀(.jpg、.png、.jpeg 等)之前将其拆分并在名称之后硬编码_thumbnail,那么就足够了。

也就是说,我想取完整的文件名,把它分成两部分,这样我就可以在两部分之间插入字符串_thumbnail。

也许这可行,但如果上传了名为 image.2horses.jpg 的图像(文件名中包含多个点的文件)怎么办? '.' 之前的天真削减在这里不行。

有没有办法解决这个问题?也许通过在最后 4 个(.jpg、.png)或 5 个(.jpeg)字符之前将文件名删减?

【问题讨论】:

    标签: image xslt


    【解决方案1】:

    在我的头顶:

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

    称为:

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

    产量:

    image.2horses
    

    【讨论】:

    • 您的代码运行良好 Tomalak,但我不得不将 Chris Nielsen 的答案标记为正确答案,因为它充分解决了我的问题。如果可以的话,我也会将您的标记为正确:)
    • +1;无论如何,我比我更喜欢你的通用解决方案。
    【解决方案2】:

    在 $filename 中给定图像的文件名,

    如果您可以假设所有图像都以“.jpg”结尾并且文件名中的其他地方没有“.jpg”,那么这应该可以:

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

    如果您不知道图像类型(例如,您也想处理 gif 和 png),或者您认为扩展名可能在文件名中出现多次(“image.jpg.jpg”),那么您将需要一个模板来帮助您:

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

    【讨论】:

    • 你的解决方案和我的差不多,我可以轻松返回+1。 ;-)
    • 对不起,我是-1,像这样的假设会导致代码错误。我使用进行大量转换的工具,它们只是将新扩展添加到末尾,因此我可以轻松体验名为 image.jpg.tif.jpg 的东西
    【解决方案3】:

    仅涉及标准 XSLT 的通用解决方案有些困难,因为您必须从末尾搜索字符串。您可以使用两个函数拆分文件名,substring-before-last 和 substring-after-last。不幸的是,这些函数不是 XSLT 的一部分。您可以谷歌并尝试找到implementations。假设您将这两个函数实现为 XSLT 模板,则可以使用以下模板生成缩略图名称:

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

    您可以像这样使用模板(假设变量 $file-name 包含图像的名称):

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

    【讨论】:

      【解决方案4】:

      看看XPath functions overview at W3Schools,特别是substring-before方法。

      【讨论】:

      • 如果文件名包含多个点怎么办。例如。 Image.09.07.11.jpg,我做了一个 substring-before('Image.09.07.11.jpg','.')?我不会得到“图像”,仅此而已吗?
      • 您可以通过递归或循环获得字符串中的最后一个点。见biglist.com/lists/xsl-list/archives/200102/msg00838.html
      【解决方案5】:

      我相信XPath functions operating on string 可能会对您有所帮助。我会尝试一些简单的replace 或translate。

      【讨论】:

        【解决方案6】:

        使用正则表达式的 XSLT 2 解决方案:

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

        原始答案(也是 XSLT 2): 这将删除最后一个分隔符(包括分隔符)之后的所有内容。所以在 $separatorRegexp 下面可以是 '\.jpg' 或者只是 '\.'和 $ 分隔符 '.jpg' 或 '.'在另一种情况下。

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

        最终,'_thumbnail.jpg' 可以附加 concat。

        【讨论】:

        • 当我用image.2horses.jpg(来自问题)尝试这个时,我得到image.2horses。 (可能是因为序列中只有一个项目,所以不需要进行字符串连接。)另一种 XPath 2.0 方法是 replace($filename,$separatorRegexp,concat($separator,'$1')),其中 $separatorRegexp = (\.[^\.]*)$ 和 $separator = _thumbnail。这会给你image.2horses_thumbnail.jpg 作为输出。
        • 这里是没有变量的替换:replace($filename, '(\.[^\.]*)$', concat('_thumbnail', '$1'))
        • Daniel Haley:这就是我的意图。附加 _thumbnail.jpg 已经很简单了。而且由于我的解决方案无论如何都涉及正则表达式,所以你的显然更好。
        猜你喜欢
        • 2011-12-15
        • 1970-01-01
        • 2017-08-19
        • 2016-10-11
        • 2020-12-30
        相关资源
        最近更新 更多