Чтение онлайн

ЖАНРЫ

Технология XSLT

Валиков Алексей Н.

Шрифт:

Чаще всего паттерны применяются в элементе

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 — образец пути выборки) конструкционную близость к самим путям выборки.

[PT1] Pattern ::= LocationPathPattern

| Pattern '|' LocationPathPattern

Одиночный паттерн определяется следующим образом:

[PT2] LocationPathPattern

 ::= '/' RelativePathPattern?

| IdKeyPattern (('/' | '//') RelativePathPattern)?

| '//'? RelativePathPattern

Упростив эту продукцию, мы получим следующее правило:

LocationPathPattern ::= '/'

| RelativePathPattern

| '/' RelativePathPattern

| '//' RelativePathPattern

| IdKeyPattern

| IdKeyPattern '/' RelativePathPattern

| IdKeyPattern '//' RelativePathPattern

Если учесть, что нетерминал

RelativePathPattern
соответствует образцу относительного пути, можно легко заметить, как похожи первые четыре возможности в этом правиле на то, что мы разбирали при описании самих абсолютных и относительных путей.

□ Паттерну

'/'
соответствует только корневой узел.

□ Паттерн

RelativePathPattern
задает образец относительного пути. Например, паттерну
a/b
соответствуют элементы
b
, находящиеся в элементах
a
.

□ Паттерну

'/' RelativePathPattern
соответствуют узлы, которые соответствуют образцу относительного пути при отсчете от корневого узла. Например, паттерну
/a/b
соответствуют элементы
b
, находящиеся в элементах
a
, находящихся в корне документа.

□ Паттерну

'//' RelativePathPattern
соответствуют узлы, которые соответствуют относительному пути при отсчете от любого узла документа. Например, паттерну
//a/b
соответствуют любые элементы
b
, имеющие родителем элемент с именем
а
. Фактически, этот паттерн не отличается от паттерна
a/b
(единственное различие в том, что они могут иметь разные приоритеты).

Последние три случая в правиле

LocationPathPattern
относятся к таким механизмам XSLT, как адресация по уникальным идентификаторам и ключам.

В первой главе книги, когда мы описывали синтаксис и семантику языка разметки документов XML, мы коротко остановились на уникальных атрибутах — атрибутах, которые определяются типом

ID
и значения которых должны быть уникальны внутри документа. Как мы узнали, это позволяет более эффективно обращаться к элементам в документе.

XSLT позволяет использовать уникальные атрибуты элементов при помощи функции

id
, которая возвращает множество, состоящее из узла, уникальный атрибут которого равен переданному ей значению, или пустое множество, если такого элемента нет.

Поделиться с друзьями: