Xpoint
   [напомнить пароль]

Удаление лишних пробельных символов (trim)

Оглавление

Постановка задачи

Дано

<data>
  Произвольный текст
     с переводами строк и большим           количеством
        пробельных символов
</data>

Требуется получить

<data>Произвольный текст
     с переводами строк и большим           количеством
        пробельных символов</data>

то есть удалить все незначащие пробельные символы (пробелы, табуляцию, переводы строк и возврат каретки — &#x9;, &#xA, &#xD, &#x20) в начале и конце строки.

Необходимые замечания

В XPath 1.0 существует встроенная функция normalize-space(), которая на первый взгляд делает именно то, что нужно — удаляет пробелы в начале и конце строки. Однако эта функция преобразует и символы внутри строки — все подряд идущие пробельные символы заменяются на пробелы и объединяются. Таким образом применение normalize-space() даст следующий результат:

<data>Произвольный текст с переводами строк и большим количеством пробельных символов</data>

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

Решение средствами XSLT 1.0.

В тех случаях, когда нельзя предварительно обработать данные нужным образом, использовать расширения и т.п., можно использовать средства самого XSLT.

Исходный код библиотеки

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
 exclude-result-prefixes="xsl"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:variable name="whiteSpaceChars" select="' &#9;&#10;&#13;'"/>

<xsl:template name="String.ltrim">
  <xsl:param name="str"/>
  <xsl:variable name="nonWS" select="translate($str, $whiteSpaceChars, '')"/>
  <xsl:variable name="firstNonWS" select="substring($nonWS, 1, 1)"/>
  <xsl:choose>
    <xsl:when test="$nonWS = ''"/>
    <xsl:otherwise>
      <xsl:value-of select="concat($firstNonWS, substring-after($str, $firstNonWS))"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<xsl:template name="String.rtrim">
  <xsl:param name="str"/>
  <xsl:variable name="len" select="string-length($str)"/>
  <xsl:variable name="lastChar" select="substring($str, $len)"/>

  <xsl:choose>
    <xsl:when test="$len = 0 or normalize-space($str) = ''"/>
    <xsl:when test="normalize-space($lastChar) != ''">
      <xsl:value-of select="$str"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:call-template name="String.rtrim">
        <xsl:with-param name="str" select="substring($str, 1, $len - 1)"/>
      </xsl:call-template>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<xsl:template name="String.trim">
  <xsl:param name="str"/>

  <xsl:call-template name="String.rtrim">
    <xsl:with-param name="str">
      <xsl:call-template name="String.ltrim">
        <xsl:with-param name="str" select="$str"/>
      </xsl:call-template>
    </xsl:with-param>
  </xsl:call-template>
</xsl:template>

</xsl:stylesheet>

Использoвaние

Использовать это можно так:
data.xml

<?xml version="1.0" encoding="windows-1251"?>
<?xml-stylesheet type="text/xsl" href="transform.xsl"?>
<data>
  Как много нам открытий чудных
  Готовит просвещенья дух!
  И опыт, сын ошибок трудных,
  И гений, парадоксов друг...
                    А.С. Пушкин
</data>

transform.xsl

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
 exclude-result-prefixes="xsl"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:import href="lib/trim.xsl"/>

<xsl:output method="text"/>

<xsl:template match="/">
    Result (ltrim): '<xsl:call-template name="String.ltrim">
      <xsl:with-param name="str" select="string(data)"/>
    </xsl:call-template>';
    Result (rtrim): '<xsl:call-template name="String.rtrim">
      <xsl:with-param name="str" select="string(data)"/>
    </xsl:call-template>'
    Result (trim): '<xsl:call-template name="String.trim">
      <xsl:with-param name="str" select="string(data)"/>
    </xsl:call-template>'
</xsl:template>

</xsl:stylesheet>

Решение средствами XSLT 2.0

Можно использовать встроенную функцию XPath 2.0 fn:replace

Powered by POEM™ Engine Copyright © 2002-2005