текущего документа вне зависимости от их пространств имен.
Паттерны
В языке XSLT определяется подмножество выражений языка XPath, которые называются паттернами (от англ. pattern — образец). Паттерны представляют собой упрощенные пути выборки, которые используются для определения, соответствует ли узел заданному образцу.
Чаще всего паттерны применяются в элементе
xsl:template
в атрибуте
match
. Шаблоны такого типа будут выполняться только для тех узлов, которые удовлетворяют заданному образцу. Например, следующий шаблон будет выполняться только для элементов
body
, принадлежащих элементу
html
:
<xsl:template match="html/body">
...
</xsl:template>
Кроме этого, паттерны применяются при нумерации и при определениях ключей.
Паттерны являются сильно упрощенными путями выборки. Единственные оси, которые могут использоваться в паттернах, — это
child
,
attribute
и
descendant-or-self
, причем ось навигации
descendant-or-self
может быть указана только в сокращенном виде оператором "
//
". То, что в паттернах используются только оси атрибутов и узлов-потомков, позволяет XSLT-процессорам значительно оптимизировать процесс сопоставления узла заданному образцу — ведь теперь даже в самом худшем сценарии не нужно метаться по всему документу, выбирая узлы, содержащиеся в тех или иных осях навигации. Правда, оператор "
//
" остается не менее опасным — при его проверке может понадобиться перебрать всех предков текущего узла, что может быть весьма и весьма затруднительно (хотя и проще, чем перебор всех потомков).
Хоть паттерны и выглядят как пути выборки, на самом деле механизм их работы несколько иной. Они не выбирают множество узлов, как таковое, они проверяют узлы на соответствие образцу, который они определяют. Это в принципе эквивалентно выбору множества и проверке узла на вхождение в него, но, как правило, так не делается, поскольку такая проверка потребовала бы слишком больших затрат времени. Гораздо дешевле в этом смысле воспользоваться тем фактом, что синтаксис паттернов упрощен, и осей не так много для того, чтобы создать более эффективный алгоритм проверки соответствия узлов. Например, для того чтобы проверить соответствие некоторого узла, назовем его
X
, паттерну
body/a
, совершенно необязательно вычислять путь выборки
body/a
и затем проверять, входит ли узел
X
в полученное множество. Достаточно проверить, является ли именем узла "
a
", а именем его родителя (если он, конечно, есть) — "
body
".
Образцы для сравнения могут состоять из одного или нескольких паттернов, которые перечисляются через знак "
|
". Для того чтобы соответствовать такому перечислению в целом, узел должен соответствовать хотя бы одному из паттернов, входящих в него. Здесь тоже есть определенная аналогия с множествами, оператор "
|
" означает как бы объединение: узел входит в объединение множеств,
если он входит хотя бы в одно из объединяемых множеств. Но, конечно же, и здесь упрощенный синтаксис играет свою роль для оптимизации — оперировать множествами, выбираемыми каждым из паттернов, было бы очень неэкономно.
Паттерны и их продукции описываются в спецификации самого языка XSLT, но мы приводим их в той же главе, что и выражения языка XPath, поскольку они очень похожи и имеют к тому же практические одинаковые семантические принципы. Паттерны используют также некоторые продукции языка XPath (такие, как
NodeTest
,
Predicate
и другие).
При нумерации EBNF-продукций паттернов мы будем нумеровать их с префиксом
PT
(
[PT1]
,
[PT2]
и т.д.), чтобы не путать с продукциями других языков, рассматриваемых в этой книге.
Самая общая продукция паттерна называется
Pattern
и показывает, что образец соответствия может быть как одиночным паттерном, так и перечислением нескольких паттернов с разделяющими символами "
|
". Продукция
LocationPathPattern
соответствует одиночному паттерну, показывая своим названием (англ. location path pattern — образец пути выборки) конструкционную близость к самим путям выборки.
Упростив эту продукцию, мы получим следующее правило:
LocationPathPattern ::= '/'
| RelativePathPattern
| '/' RelativePathPattern
| '//' RelativePathPattern
| IdKeyPattern
| IdKeyPattern '/' RelativePathPattern
| IdKeyPattern '//' RelativePathPattern
Если учесть, что нетерминал
RelativePathPattern
соответствует образцу относительного пути, можно легко заметить, как похожи первые четыре возможности в этом правиле на то, что мы разбирали при описании самих абсолютных и относительных путей.
□ Паттерну
'/'
соответствует только корневой узел.
□ Паттерн
RelativePathPattern
задает образец относительного пути. Например, паттерну
a/b
соответствуют элементы
b
, находящиеся в элементах
a
.
□ Паттерну
'/' RelativePathPattern
соответствуют узлы, которые соответствуют образцу относительного пути при отсчете от корневого узла. Например, паттерну