| '/' | '//' | '|' | '+' | '-'
| '=' | '!=' | '<' | '>' | '<=' | '>='
Продукция самого токена выражения имеет вид:
[ХР28] ExprToken ::= '(' | ')' | '[' | ']'
| ' . ' | ' .. ' | '@' | ' | ':: '
| NameTest
| NodeType
| Operator
| FunctionName
| AxisName
| Literal
| Number
| VariableReference
При разборе XPath-выражения оно сначала разбивается на отдельные токены, а затем из них организуются более сложные структуры. При разбивке выражения на отдельные токены, следует всегда выбирать токен с самым длинным строковым представлением.
Помимо этого, для того чтобы грамматика XPath-выражений была однозначной, в спецификации языка приводятся следующие правила разбора.
□ Если текущему токену предшествует другой токен, причем этот предшествующий токен не является символом @, ::, (, [ или нетерминалом Operator, то текущий токен, являющийся символом *, должен восприниматься как знак умножения, а токен, являющийся NCName, — как нетерминал OperatorName.
□ Если за текущим токеном вида NCName следует открывающая круглая скобка (символ "("), токен должен восприниматься или как имя функции (FunctionName), или как тип узла (NodeType).
□ Если за текущим токеном вида NCName следуют символы "::", токен должен восприниматься как имя оси навигации (AxisName).
□ Если ничего из вышеперечисленного не выполняется, токен не должен восприниматься, как MultiplyOperator, OperatorName, NodeType, FunctionName или AxisName.
Мы привели эти правила в точности так, как они описаны в спецификации языка XPath. Их довольно непросто понять в такой формулировке, поэтому мы попытаемся объяснить их другими словами.
□ Символ * является знаком умножения (MultiplyOperator) тогда и только тогда, когда ему предшествует токен, но этот токен не является токеном @, ::, (, [ или Operator.
□ Токен NCName представляет имя оператора (OperatorName) тогда и только тогда, когда ему предшествует токен, но этот токен не является токеном ::, (, [ или Operator.
□ Токен NCName является именем функции (FunctionName) или типом узла (NodeType) тогда и только тогда, когда за ним следует символ "(".
□ Токен NCName является именем оси навигации (AxisName) тогда и только тогда, когда за ним следуют символы "::".
Глава 7
Основные элементы XSLT
Основные и дополнительные элементы
Все элементы XSLT можно разделить на две группы: элементы основные и элементы дополнительные. Это разделение очень условно, ничего подобного в спецификации языка XSLT нет, однако, мы будем им пользоваться, считая основными элементами те элементы XSLT, которые непосредственно отвечают за создание узлов выходящего дерева или обеспечивают контроль над этим процессом. К дополнительным элементам мы будем относить все остальные элементы XSLT.
Таким образом, множество основных элементов будет включать в себя следующее:
□ xsclass="underline" element — создание в выходящем дереве узла элемента;
□ xsclass="underline" attribute — создание в выходящем дереве узла атрибута;
□ xsclass="underline" attribute-set — определение именованного набора атрибутов;
□ xsclass="underline" text — создание текстового узла;
□ xsclass="underline" value-of — создание текстового узла по результатам вычисления выражения;
□ xsclass="underline" comment — создание узла комментария;
□ xsclass="underline" processing-instruction — создание узла инструкции по обработке;
□ xsclass="underline" copy — копирование текущего узла вместе с его узлами пространств имен;
□ xsclass="underline" copy-of — копирование результата вычисления выражения;
□ xsclass="underline" if — условная обработка;
□ xsclass="underline" choose, xsclass="underline" when и xsclass="underline" otherwise — выбор одной из нескольких альтернатив согласно некоторым условиям;
□ xsclass="underline" for-each — итеративная обработка множества узлов.
Создание узлов элементов
В четвертой главе мы уже разобрали один из способов создания в выходящем документе узлов элементов, а именно — использование литеральных элементов результата, которые в неизменном виде копируются процессором в выходящее дерево. Этот способ прост, понятен и удобен, однако есть две основные проблемы, которые он не может решить.
□ Что, если в выходящем документе требуется создать элемент с заранее неизвестным (например, вычисляемым во время выполнения) именем?
□ Как создать элемент, принадлежащий пространству имен, известному обрабатывающему процессору?
Поясним на примерах суть и той и другой проблемы.
Представим себе входящий документ вида
<element name="a">
<element name="b"/>
</element>
который нужно преобразовать во что-нибудь наподобие
<а>
<b/>
</а>
Совершенно очевидно, что литеральными элементами тут не обойдешься — мы не знаем заранее имена элементов выходящего документа, ибо они определяются значениями атрибутов входящего.
Представим теперь, что нам в XSLT-преобразовании необходимо сгенерировать другое XSLT-преобразование. Скажем из элемента вида
<remove element="a"/>
нужно получить шаблон
<xsclass="underline" template match="a"/>
Беда в том, что литеральные элементы не могут быть использованы для создания, скажем, элемента xsclass="underline" template по той причине, что любой элемент с локальной частью имени template, принадлежащий пространству имен XSLT будет рассматриваться процессором, как элемент самого преобразования. Очевидно, что
<xsclass="underline" template match="remove">
<xsclass="underline" template match="{@element}"/>
</xsclass="underline" template>
будет некорректным определением. He поможет и смена префикса, ведь принадлежность пространству имен определяется не им.
Для того чтобы решить эти проблемы (главным образом, первую), XSLT предоставляет возможность создавать узлы элементов при помощи элемента xsclass="underline" element.
Элемент xsclass="underline" element
Синтаксическая конструкция этого элемента задается следующим образом:
<xsclass="underline" element
name="{имя}"
namespace="{пространство имен}
"use-attribute-sets="имена">
<!-- Содержимое: шаблон -->