«Регулярное выражение» в стиле замены в XSLT 1.0 - PullRequest
4 голосов
/ 25 июня 2009

Мне нужно выполнить поиск и замену, используя XSLT 1.0, который действительно подходит для регулярных выражений. К сожалению, они недоступны в 1.0, и я также не могу использовать какие-либо библиотеки расширений, такие как EXSLT, из-за настроек безопасности, которые я не могу изменить.

Строка, с которой я работаю, выглядит следующим образом:

19;#John Smith;#17;#Ben Reynolds;#1;#Terry Jackson

Мне нужно заменить цифры и ; # символов на ,. Например, приведенное выше изменится на:

John Smith, Ben Reynolds, Terry Jackson

Я знаю, что требуется рекурсивная строковая функция, возможно, с использованием подстроки и перевода, но я не уверен, с чего начать.

У кого-нибудь есть советы, как это решить? Вот с чего я начал:

<xsl:template name="TrimMulti">
    <xsl:param name="FullString" />
    <xsl:variable name="NormalizedString">
        <xsl:value-of select="normalize-space($FullString)" />
    </xsl:variable>
    <xsl:variable name="Hash">#</xsl:variable>
    <xsl:choose>
        <xsl:when test="contains($NormalizedString, $Hash)">
            <!-- Do something and call TrimMulti -->
        </xsl:when>
    </xsl:choose>
</xsl:template>

Ответы [ 2 ]

8 голосов
/ 25 июня 2009

Я надеюсь, что вы не слишком упростили проблему, задав вопрос по SO, потому что это не должно быть такой большой проблемой.

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

Например,

<xsl:template name="TrimMulti">
  <xsl:param name="InputString"/>
  <xsl:variable name="RemainingString" 
    select="substring-after($InputString,';#')"/>
  <xsl:choose>
    <xsl:when test="contains($RemainingString,';#')">
      <xsl:value-of 
        select="substring-before($RemainingString,';#')"/>
      <xsl:text>, </xsl:text>
      <xsl:call-template name="TrimMulti">
        <xsl:with-param 
          name="InputString"
          select="substring-after($RemainingString,';#')"/>
      </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$RemainingString"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

Я протестировал этот шаблон с помощью следующего вызова:

<xsl:template match="/">
  <xsl:call-template name="TrimMulti">
    <xsl:with-param name="InputString">19;#John Smith;#17;#Ben Reynolds;#1;#Terry Jackson</xsl:with-param>
  </xsl:call-template>
</xsl:template>

И получил следующий вывод:

John Smith, Ben Reynolds, Terry Jackson

Что, кажется, то, что вы ищете.

Объяснение того, что он делает, легко объяснить, если вы знакомы с функциональным программированием. Параметр InputString всегда имеет форму [number];#[name];#[rest of string]. Каждый вызов шаблона TrimMulti отсекает часть [number];# и печатает часть [name], а затем рекурсивно передает оставшееся выражение себе.

Базовый случай - это когда InputString имеет форму [number];#[name], в этом случае переменная RemainingString не будет содержать ;#. Поскольку мы знаем, что это конец ввода, на этот раз мы не выводим запятую.

0 голосов
/ 29 марта 2012

Если ';' и символы '#' недопустимы во входных данных, потому что они являются разделителями, тогда почему функция перевода не будет работать? Это может быть некрасиво (вы должны указать все допустимые символы во втором аргументе и повторить их в третьем аргументе), но это будет легче отладить.

translate($InputString, ';#abcdefghijklmnopqrstuvABCDEFGHIJKLMNOPQRSTUZ0123456789,- ', ', abcdefghijklmnopqrstuvABCDEFGHIJKLMNOPQRSTUZ0123456789,- ')
...