□ Паттерну IdKeyPattern '/' RelativePathPattern
соответствуют узлы, которые соответствуют образцу пути RelativePathPattern
отсчитанного относительного узла, соответствующего IdKeyPattern
. Например, узел соответствует паттерну id('index5')/a/b
, если он является элементом с именем b
, его родителем является элемент а
, а его родитель в свою очередь имеет уникальный атрибут со значением "index5"
.
□ Паттерн IdKeyPattern '//' RelativePathPattern
аналогичен предыдущему: ему соответствуют узлы, которые соответствуют паттерну RelativePathPattern
, отсчитанному от любого потомка или самого узла, входящего в IdKeyPattern
. Например, паттерну id('index5')//a/b
будет соответствовать любой дочерний элемент b
элемента a
, являющегося потомком элемента, уникальный атрибут которого имеет значение index5
, или если он сам имеет такой атрибут.
Мы более подробно остановимся на ключевых паттернах, когда будем разбирать функции id
и key
, а пока обратимся к главной детали всех вышеперечисленных продукций — к образцу относительного пути, RelativePathPattern
. Его продукция записывается в следующем виде:
[PT4] RelativePathPattern
::= StepPattern
| RelativePathPattern '/' StepPattern
| RelativePathPattern '//' StepPattern
Если сравнить это правило с упрощенной продукцией RelativeLocationPath
, можно заметить совпадение с точностью до имен продукций. Образец относительного пути строится точно так же, как и обычный путь выборки — перечислением через разделяющие символы "/"
и "//"
шагов, в данном случае — шагов образца относительного пути.
Эти шаги соответствуют продукции StepPattern
, которая отличается от продукции Step
только тем, что разрешает использовать только оси child
и attribute
.
[PT5] StepPattern ::= ChildOrAttributeAxisSpecifier NodeTest
Predicate*
Продукция ChildOrAxisSpecifier
описывает дескрипторы осей child
и attribute
в полном или сокращенном виде:
[P6] ChildOrAttributeAxisSpecifier
::= AbbreviatedAxisSpecifier
| ('child' | 'attribute') '::'
Для простоты мы можем раскрыть эту продукцию, получив ее в следующем виде:
ChildOrAttributeAxisSpecifier
::= '@' ?
| 'child::'
| 'attribute::'
Тогда продукцию StepPattern
тоже можно переписать:
StepPattern ::= NodeTest Predicate*
| '@' NodeTest Predicate*
| 'child::' NodeTest Predicate*
| 'attribute::' NodeTest Predicate*
Теперь стало совершенно очевидно, что шаг паттерна это не что иное, как подмножество шагов выборки, в которых ограничено множество осей навигации.
Таким образом, синтаксически паттерны отличаются от путей выборки тем, что в них можно использовать только две оси навигации (не считая descendant-or-self
в виде оператора), но зато можно в качестве узла отсчета использовать узел, выбранный по своему уникальному атрибуту или по значению ключа.
Паттерны могут использоваться в XSLT в следующих атрибутах:
□ атрибуты count
и from
элемента xsl:number
;
□ атрибут match
элемента xsl:key
;
□ атрибут match
элемента xsl:template
.
Последние два случая паттернов отличаются от первого тем, что в них нельзя использовать переменные. Определение вида
...
будет некорректным.
Остановимся подробнее на вопросе — что же означает "соответствие узла некоторому паттерну".
Прежде всего, заметим, что любой паттерн является также и XPath-выражением. Тогда строгое определение соответствия узла паттерну можно дать следующим образом.
Узел X
соответствует паттерну P
тогда и только тогда, когда существует такой узел Y
, принадлежащий оси ancestor-or-self
узла X
, что множество, получаемое в результате вычисления выражения P
в контексте узла Y
будет содержать узел X
.
Пример
Рассмотрим это определение на примере паттерна body//а
. Строго говоря, узел будет соответствовать этому паттерну, если во множестве его предков (плюс сам узел) найдется такой узел, что множество body//а
, вычисленное в его контексте, будет содержать проверяемый узел. На практике первые два элемента а
приведенного ниже документа соответствуют этому паттерну, потому что существует элемент html
, содержащий элемент body
, потомками которого эти элементы а
являются.
Листинг 6.2
<���а>
</а>
Существует также и более простое определение соответствия. Узел X
соответствует паттерну P
тогда и только тогда, когда X
принадлежит множеству //P
. В приведенном выше примере паттерну body//а
соответствуют все узлы множества //body//а
.
Читать дальше