□ Паттерну 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//а.
Читать дальше