Удаление последних символов в строке XSLT

В моей CMS можно создать новую статью и выбрать изображение, которое будет отображаться в этой статье. Когда изображение выбрано, миниатюра изображения также будет создана автоматически.

Если загруженное изображение называетсяimage.jpgтогда соответствующая миниатюра будет автоматически названаimage_thumbnail.jpg.

Теперь я хотел бы использовать уменьшенное изображение везде на веб-сайте, где упоминается статья, за исключением самой статьи (где должно быть показано исходное большое изображение).

Но как я могу это сделать?

Я представляю, смогу ли я получить оригинальное имя изображения, а затем разделить его до суффикса (.jpg, .png, .jpeg и т. д.) и жесткий код_thumbnail после имени этого будет достаточно.

Другими словами, я хочу взять полное имя файла и разрезать его на две части, чтобы я мог вставить строку_thumbnail между двумя частями.

Может быть, это будет работать, но что, если изображение называетсяimage.2horses.jpg (файл с более чем одной точкой в имени файла) загружен? Наивный разрез перед "." не будет работать здесь.

Есть ли способ обойти это? Возможно, вырезав имя файла перед последними 4 (.jpg, .png) или 5 (.jpeg) персонажи?

Ответы на вопрос(6)

Решение Вопроса

Если вы можете предположить, что все изображения будут заканчиваться на & quot; .jpg & quot; и не будет иметь & quot; .jpg & quot; в другом месте в имени файла, это должно работать:

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

Если вы не знаете тип изображения (например, вы также хотите обрабатывать gif и png), или если вы думаете, что расширение может встречаться в имени файла несколько раз (& quot; image.jpg.jpg & quot;), тогда вы узнаете хочу шаблон, чтобы помочь вам:

<?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>
 14 июл. 2009 г., 14:19
Ваше решение примерно равно моему, я могу легко вернуть +1. ;-)
 29 мая 2017 г., 12:57
Извините, -1 от меня, такие предположения приводят к ошибочному коду. Я работаю с инструментами, которые делают много конверсий, и они просто добавляют новое расширение в конец, чтобы я мог легко испытать то, что называется image.jpg.tif.jpg

Функции XPath, работающие со строкой может помочь тебе Я хотел бы попробовать с некоторыми простымиreplace или жеtranslate.

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

Оригинальный ответ (также XSLT 2): Это удаляет все после последнего разделителя (включая разделитель). Поэтому ниже $ separatorRegexp может быть & apos; \. Jpg & apos; или просто "." и разделитель $ ".jpg" или '.' в другом случае.

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

В конце концов '_thumbnail.jpg & apos; может быть добавлен с конкат.

, concat('_thumbnail', '$1'))

Оригинальный ответ (также XSLT 2): Это удаляет все после последнего разделителя (включая разделитель). Поэтому ниже $ separatorRegexp может быть & apos; \. Jpg & apos; или просто "." и разделитель $ ".jpg" или '.' в другом случае.

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

В конце концов '_thumbnail.jpg & apos; может быть добавлен с конкат.

 02 июн. 2017 г., 10:11
Даниэль Хейли: Это то, что я хотел. Добавление _thumbnail.jpg уже тривиально. И так как мое решение в любом случае включает в себя регулярное выражение, то вы, очевидно, лучше.
 02 июн. 2017 г., 00:51
Вот замена без переменных:replace($filename, '(\.[^\.]*)$', concat('_thumbnail', '$1'))
 02 июн. 2017 г., 00:43
Когда я попробовал это сimage.2horses.jpg (из вопроса) я получаюimage.2horses, (Возможно, потому что в последовательности есть только один элемент, поэтому нет ничего для объединения строк.) Другой подход XPath 2.0 будетreplace($filename,$separatorRegexp,concat($separator,'$1')) где $ separatorRegexp =(\.[^\.]*)$ и $ separator =_thumbnail, Это даст вамimage.2horses_thumbnail.jpg в качестве выхода.

включающее только стандартный XSLT, довольно сложно, так как вам нужно искать строку с конца. Вы можете разделить ваше имя файла с помощью двух функций: substring-before-last и substring-after-last. К сожалению, эти функции не являются частью XSLT. Вы можете Google и попытаться найтиреализации, Предполагая, что эти две функции реализованы в виде шаблонов 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>

<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
 14 июл. 2009 г., 13:52
+1; В любом случае, мне нравится ваше обобщенное решение лучше, чем мое.
 Kim Andersen14 июл. 2009 г., 10:24
Ваш код работал так же, Томалак, но мне пришлось пометить ответ Криса Нильсена как правильный, потому что он полностью решил мою проблему. Если бы я мог, я бы тоже отметил вас как правильный :)

Обзор функций XPath в W3Schoolsконкретноsubstring-before метод.

 13 июл. 2009 г., 15:53
Вы можете получить последнюю точку в строке с помощью рекурсии или цикла. Увидетьbiglist.com/lists/xsl-list/archives/200102/msg00838.html
 Kim Andersen13 июл. 2009 г., 15:36
Что делать, если есть имя файла с более чем одной точкой. Например. Image.09.07.11.jpg, и я создал подстроку перед («Image.09.07.11.jpg», «.»)? Я бы не получил «изображение» и больше ничего?

Ваш ответ на вопрос