Кроме того, каждой оси соответствует прямое или обратное направление просмотра, которое определяет, в каком порядке будут перебираться узлы, выбираемые этой осью. Оси навигации, которые содержат узлы, предшествующие в порядке просмотра документа контекстному узлу, имеют обратное направление просмотра, все остальные оси просматриваются в прямом порядке. Поскольку оси как
self
и
parent
не могут содержать более одного узла, порядок просмотра для них не играет никакого значения.
Базовые типы узлов и направление их просмотра можно свести в одну таблицу (табл. 6.1).
Таблица 6.1. Базовые типы узлов и направления просмотра
осей навигации
Ось навигации
Базовый тип узла
Направление просмотра
self
Узел элемента
Нет
child
Узел элемента
Прямое
parent
Узел элемента
Нет
descendant
Узел элемента
Прямое
descendant-or-self
Узел элемента
Прямое
ancestor
Узел элемента
Обратное
ancestor-or-self
Узел элемента
Обратное
following
Узел элемента
Прямое
following-sibling
Узел элемента
Прямое
preceding
Узел элемента
Обратное
preceding-sibling
Узел элемента
Обратное
attribute
Узел атрибута
Прямое
namespace
Узел пространства имен
Прямое
Базовый тип влияет на то, как в данном шаге выборки будет выполняться тест узла, а направление просмотра на позицию, которую будет занимать тот или иной узел в данном направлении.
Легче всего понять, какие узлы и в каком порядке содержат те или иные оси навигации, представив это графически. Рис. 6.10 иллюстрирует выбор узлов осями навигации. Здесь показано дерево документа, контекстный узел, выделенный жирной линией, и множество узлов, содержащееся в данной оси, ограниченное пунктиром. Узлы выбранного множества пронумерованы в порядке просмотра оси.
Рис. 6.10. Расположение и порядок просмотра осей навигации в документе
Приведем продукцию
AxisName
, которая описывает синтаксис осей навигации.
[XP6] AxisName ::= 'ancestor'
| 'ancestor-or-self'
| 'attribute'
| 'child'
| 'descendant'
| 'descendant-or-self'
| 'following'
| 'following-sibling'
| 'namespace'
| 'parent'
| 'preceding'
| 'preceding-sibling'
| 'self'
Оси
навигации показывают, в каком направлении следует искать узлы, — среди тех, которые предшествовали контекстному узлу, или тех, которые будут следовать за ним, родительские или дочерние элементы, узлы атрибутов или пространств имен.
При этом оси навигации могут содержать узлы разных типов и с разными именами. Следующая часть шага выборки, тест узла уточняет, что конкретно мы ищем.
Тесты узлов
Вторая часть шага выборки, тест узла, оставляет из множества, которое содержит ось навигации, только узлы, соответствующие определенному типу или имеющие определенные имена.
Продукция
NodeTest
, соответствующая тесту узла, определяется следующим образом:
[XP7] NodeTest ::= NameTest
| NodeType '(' ')'
| 'processing-instruction' '(' Literal ')'
Раскрыв продукции
NameTest
и
NodeType
, EBNF-синтаксис теста узла можно переписать в упрощенном виде:
NodeTest ::= '*'
| NCName:*
| QName
| 'comment'
| 'text'
| 'processing-instruction'
| 'processing-instruction' '(' Literal ')'
| 'node'
Рассмотрим подробно каждый случай.
□ Тест узла
'*'
выполняется для любого узла, тип которого является базовым типом оси навигации данного шага выборки. Иными словами, шаг выборки
attribute::*
или
@*
выберет все атрибуты контекстного узла, а
namespace::*
— все узлы пространств имен. Для всех остальных осей тест
*
будет выбирать узлы элементов, принадлежащих данной оси.
□ Тест узла вида
'NCName:*'
выполняется для узлов определенного пространства имен. Этот тест имеет вид
префикс:*
, где
префикс
соответствует проверяемому пространству (он должен быть определен в контексте вычисляемого шага выборки). Этот тест выполняется для всех узлов пространства имен, которое соответствует префиксу вне зависимости от локальной части имени.
□ Тест вида
QName
выполняется для узлов базового типа, которые имеют расширенные имена, равные
QName
. Если в
QName
не указан префикс, то тест будет выполняться для узлов с соответствующим именем и нулевым пространством имен. В случае, если префикс указан, узел будет удовлетворять тесту, если его пространство имен будет совпадать с пространством имен, которое соответствует префиксу, а локальная часть имени будет равна локальной части
QName
.
□ Тест
'comment'
выполняется для любого узла комментария.
□ Тест
'text'
выполняется для любого текстового узла.
□ Тест узла
'processing-instruction'
выполняется для любого узла инструкции по обработке.
□ Тест
'processing-instruction (' Literal ')'
, или, в упрощенном виде
processing-instruction(строка)
выполняется для инструкций по обработке, имеющих имя, равное строковому параметру этого теста узла.