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

Использование регулярных выражений

Задача

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

Решение

Сопоставление с текстовыми образцами

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

<!-- -->
<!-- Дата в формате May 3, 1964 -->
<xsl:template match="birthday[matches(.,'^[A-Z][a-z]+\s[0-9]+,\s[0-9]+$')]">
    <!-- ... -->
</xsl:template>

<!-- Дата в формате 1964-05-03 -->
<xsl:template match="birthday[matches(.,'^[0-9]+-[0-9]+-[0-9]+$')]">
    <!-- ... -->
</xsl:template>

<!-- Дата в формате 3 May 1964 -->
<xsl:template match="birthday[matches(.,'^[0-9]+\s[A-Z][a-z]+\s[0-9]+$')]">
    <!-- ... -->
</xsl:template>

Можно также выполнять сопоставление в командах xsl:if и xsl:choose:

<xsl:choose>
    <xsl:when test="matches($date,'^[A-Z][a-z]+\s[0-9]+,\s[0-9]+$')">
    </xsl:when>
    <xsl:when test="matches($date,'^[0-9]+-[0-9]+-[0-9]+$')">
    </xsl:when>
    <xsl:when test="matches($date,'^[0-9]+\s[A-Z][a-z]+\s[0-9]+$')">
    </xsl:when>
</xsl:choose>

Выделение лексем в стилизованном тексте

Часто регулярные выражения применяются для разбиения строки на лексемы:

(: Выделить из даты в формате ISO (YYYY-MM-DDhh:mm:ss) год, месяц и день, представив их в виде последовательности :)

tokenize($date, '-')

(: Выделить из даты в формате ISO (YYYY-MM-DDhh:mm:ss) год, месяц, день, часы, минуты и секунды представив их в виде последовательности :)

tokenize($date, '-|T|:')

(: Разбить предложение на слова :)

tokenize($text, '\W+')

Замена и расширение текста

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

(: Заменить день месяца в дате в формате ISO на 01 :)

replace($date, '\d\d$', '01')

(: Убрать из даты в формате ISO все компоненты, кроме года :)

replace($date, '-\d\d-\d\d$', '')

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

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

replace($text, '([,;:])\S', '$1 ')

Анализ текста для преобразования в формат XML

Еще более мощной, чем функции tokenize() и replace(), является появившаяся в XSLT 2.0 команда xsl:analyze-string. Она позволяет не просто выполнять подстановки в тексте, но строить на основе текста XML-содержимое.

Обсуждение

Регулярные выражения – это настолько богатый и мощный инструмент обработки текста, что им можно было бы посвятить целую книгу. И такие люди нашлись. Книга Джеффри Фридла «Регулярные выражения» (издательство «Питер», 2003) – классическое сочинение на эту тему, я ее настоятельно рекомендую.

Важность регулярных выражений проистекает из умения сопоставлять текст с образцами. Интересно, что сопоставление с образцами – это и основа мощи языка XSLT. Но если XSLT идеально приспособлен для поиска образцов в структуре XML-документа, то регулярные выражения оптимизированы для работы с произвольным текстом. Однако язык регулярных выражений сложнее языка выражений XPath, используемого внутри XSLT. Это неизбежно просто потому, что произвольному тексту недостает древовидной структуры, характерной для XML.

Ключ к овладению регулярными выражениями – практика и разумное заимствование идей из примеров выражений, написанных другими людьми. Помимо книга Фридла, примеры можно найти в книгах по языку Perl и на сайте RegExLib.com.