KnigaRead.com/

Алексей Валиков - Технология XSLT

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Алексей Валиков, "Технология XSLT" бесплатно, без регистрации.
Перейти на страницу:

Базовый тип влияет на то, как в данном шаге выборки будет выполняться тест узла, а направление просмотра на позицию, которую будет занимать тот или иной узел в данном направлении.

Легче всего понять, какие узлы и в каком порядке содержат те или иные оси навигации, представив это графически. Рис. 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(строка) выполняется для инструкций по обработке, имеющих имя, равное строковому параметру этого теста узла.

□ Тест узла 'node()' выполняется для любого узла. Шаг выборки вида ось::node() выберет все узлы, принадлежащие данной оси.

Примеры:

□ child::node() — выберет все дочерние узлы контекстного узла;

□ child::* — выберет дочерние элементы контекстного узла;

□ attribute::* — выберет атрибуты контекстного узла;

□ xsl:* — выберет все дочерние элементы контекстного узла, принадлежащие пространству имен с префиксом xsl;

□ xsl:template  — выберет все дочерние элементы template контекстного узла, принадлежащие пространству имен с префиксом xsl;

□ comment() — выберет все дочерние узлы комментариев;

□ self::comment() — выберет контекстный узел, если он является комментарием, или пустое множество в противном случае;

□ descendant::processing-instruction() — выберет все узлы инструкций по обработке, которые являются потомками контекстного узла;

□ following::processing-instruction('арр')— выберет все узлы инструкций по обработке с целевым приложением "app", которые следуют за контекстным узлом в порядке просмотра документа.

Тест узла показывает, какого типа узлы мы ищем. Комментарии? Текстовые узлы? Узлы с определенными именами или принадлежащие определенному пространству имен? Или подойдут любые узлы?

Итак, ось навигации позволяет указывать направления шага по дереву документа, тест узла — тип или имя выбираемого узла. Третья часть шага выборки (один или несколько предикатов) позволяет дополнять эти критерии логическими условиями, которые должны выполняться для выбираемых на данном шаге узлов.

Предикаты

При выборе узлов каждый шаг выборки может иметь один или несколько предикатов, которые будут фильтровать выбираемое множество узлов. Предикат — это логическое выражение, вычисляемое для. каждого узла выбранного множества, и только в том случае, если результатом является истина, узел остается в фильтруемом множестве.

Продукция предиката, Predicate, определяется следующим образом:

[XP8] Predicate     ::= '[' PredicateExpr ']'

[XP9] PredicateExpr ::= Expr

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

Predicate ::= '[' Expr ']'

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

Фильтрация множества узлов выполняется следующим образом.

□ Фильтруемое множество сортируется в направлении просмотра оси навигации данного шага. Для осей ancestor, ancestor-or-self, preceding, preceding-sibling фильтруемое множество сортируется в обратном порядке просмотра документа, для остальных осей — в прямом порядке просмотра.

□ Выражение предиката вычисляется для каждого узла отсортированного множества в следующем контексте.

 • Фильтруемый узел (тот, для которого в данный момент вычисляется предикат) становится контекстным узлом.

 • Количество узлов фильтруемого множества становится размером контекста.

 • Позиция фильтруемого узла в отсортированном множестве становится позицией контекста.

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

 • Если результатом вычисления является число, равное позиции контекста, булевым значением предиката будет true, в противном случае — false. Например, предикат [2] равносилен предикату [position()=2] — он обратится в истину только для второго узла фильтруемого множества.

 • Все остальные типы данных приводятся к булевому типу в соответствии со стандартными правилами (см. также раздел "Типы данных" настоящей главы).

□ Из фильтруемого множества исключаются все узлы, булевое значение предиката для которых было ложью.

□ В случае, если в шаге выборки было несколько предикатов, процедура фильтрации повторяется с каждым из них, оставляя в отфильтрованном множестве только те узлы, для которых каждый из предикатов будет истиной.

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

Примеры:

□ a[1] — выберет первый в порядке просмотра документа дочерний элемент а контекстного узла;

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*