Перейти к содержанию

Удаление заданных символов из строки

Задача

Требуется убрать из строки некоторые символы (например, пробельные).

Решение

XSLT 1.0

Воспользуйтесь функцией translate() с пустой строкой замены. Например, следующий код удаляет из строки все пробельные символы:

1
translate($input, " 	

", "")

XSLT 2.0

Применение translate оправдано и в XSLT 2.0, так как обычно эта функция работает быстрее всего. Но некоторые задачи такого рода более естественно решаются с помощью регулярных выражений и новой функции replace():

1
2
(: \s соответствует любому пробельному символу :)
replace($input, "\s", "")

Обсуждение

translate() – довольно гибкая функция, которая часто применяется для компенсации отсутствующих в XSLT 1.0 средств работы со строками. Здесь мы воспользовались тем фактом, что translate() не копирует те символы входной строки, которые есть в строке from, но отсутствуют в строке to.

Функцию translate() можно использовать также для удаления из строки всех символов, кроме заданных. Например, следующий код удаляет из исходной строки все символы, кроме цифр:

1
2
translate($string,
translate($string, '0123456789', ''), '')

Внутренний вызов translate() удаляет все интересующие нас символы (в данном случае цифры), чтобы получить параметр from для внешнего вызова, который удалит из исходной строки все символы, кроме цифр.

Иногда нужно удалять не все пробелы, а только находящиеся в начале и в конце строки, а также оставлять из нескольких подряд идущих пробелов в середине только один. В XPath для этой цели есть встроенная функция normalize-space().

А если нужно решить ту же задачу для символа, отличного от пробела, то можно воспользоваться таким кодом (в данном случае мы нормализуем вхождения символа C):

1
translate(normalize-space(translate($input,"C "," C")),"C "," C")

Однако это преобразование будет работать неправильно, если входная строка содержит другие символы пропуска, то есть знаки табуляции (#x9), конца строки (#xA) и перевода каретки (#xD). Причина в том, что это выражение переставляет местами пробел и нормализуемый символ, затем нормализует пробелы и выполняет обратную перестановку. Если после первого преобразования остается символ пропуска, отличный от пробела, то он также нормализуется, хотя вы, возможно, этого и не хотели. Впрочем, нормализация чего-либо, кроме пробелов, встречается редко. Ниже показано, как можно удалить лишние символы -:

1
2
3
4
<xsl:template match="/">
    <xsl:variable name="input" select=" '—this —is— the way we normalize non-whitespace—' "/>
    <xsl:value-of select="translate(normalize-space(translate($input,'- "," -')),'- "," -')" />
</xsl:template>

XSLT 2.0

Более универсальный способ удаления ненужных символов дает встроенная в XSLT 2.0 функция replace(), основанная на аппарате регулярных выражений. Ниже мы с помощью replace() нормализуем отличный от пробела символ без особых случаев, возникающих в решении для XSLT 1.0:

1
2
3
4
5
6
7
8
9
<xsl:template match="/">
  <xsl:variable
    name="input"
    select=" '—this —is— the way we normalize non-whitespace—' "
  />
  <xsl:value-of
    select="replace(replace($input,'-+','-'),'^-+|-+$','')"
  />
</xsl:template>

Здесь функция replace() вызывается дважды. Внутренний вызов заменяет все соседние вхождения символа одним, а внешний удаляет начальные и конечные символы.

Комментарии