Использование регулярных выражений¶
Задача¶
Вы слыхали о том, что регулярные выражения – это новый мощный инструмент, появившийся в 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.