$nodes[self::а][@href]
Можно использовать и более сложные конструкции, например, фильтровать объединение двух множеств — присвоенного переменной nodesи возвращаемого путем выборки body/*:
($nodes|body/*)[self::a][@href]
Выражение, в котором производится фильтрация узлов, отвечает EBNF-правилу FilterExpr:
[XP20] FilterExpr ::= PrimaryExpr | FilterExpr Predicate
Если раскрыть рекурсию, которая имеется в этом правиле, его можно переписать в более простом виде:
FilterExpr ::= PrimaryExpr Predicate*
Выражение PrimaryExpr, которое используется в этой продукции, должно обязательным образом возвращать множество узлов. В противном случае процессор выдаст ошибку, потому что никакой другой тип не может быть преобразован во множество узлов.
Использование в выражениях путей выборки
Помимо того, что выражение само по себе может быть путем выборки, относительные пути можно комбинировать с другими выражениями. Например, можно выбрать все дочерние элементы узлов множества, содержащегося в переменной
$nodes/*
Для разделения шагов выборки в фильтрующих выражениях можно использовать операторы " /" и " //". Например, для того, чтобы получить всех потомков узлов из множества, присвоенного переменной, можно использовать выражение вида
$nodes//node()
Здесь node()— это тест узла, выполняющийся для всех типов узлов, а //, как и обычно, сокращение от /descendant-or-self:node()/.
Выражения, которые используют пути выборки, соответствуют продукции PathExpr:
[XP19] PathExpr ::= LocationPath
| FilterExpr
| FilterExpr '/' RelativeLocationPath
| FilterExpr '//' RelativeLocationPath
Множества могут быть объединены при помощи оператора " |". В объединение будут входить узлы, которые присутствуют хотя бы в одном из множеств, причем результат не содержит повторений. Объединять можно любые выражения, результатом вычисления которых являются множества узлов.
Пример
Множество всех элементов а, bи сдокумента может быть задано выражением //a|//b|//c.
Выражению объединения соответствует продукция UnionExpr:
[XP18] UnionExpr ::= PathExpr | UnionExpr '|' PathExpr
Теперь, когда мы изучили все типы операций XPath, можно дать синтаксическое определение выражению и выстроить все операции в порядке старшинства.
Выражению, как самой общей конструкции XPath, соответствует продукция Expr, которая определяется следующим образом:
[XP14] Expr ::= OrExpr
То есть, фактически, выражение в XPath определяется через логическое выражение. Естественно, выражения не обязаны быть логическими. Просто в иерархии синтаксических правил логическое выражение "или" находится выше всего. Верхние правила определяются через более примитивные правила и так далее. В итоге иерархия выражений выстраивается следующим образом (в скобках приведены названия EBNF-правил):
□ выражения ( Expr);
□ логические выражения "или" ( OrExpr);
□ логические выражения "и" ( AndExpr);
□ выражения равенства и неравенства ( EqualityExpr);
□ выражения сравнения ( RelationalExpr);
□ выражения сложения и вычитания ( AdditiveExpr);
□ выражения умножения и деления ( MultiplicativeExpr);
□ унарные выражения ( UnaryExpr);
□ выражения объединения множеств ( UnionExpr);
□ выражения путей выборки ( PathExpr);
□ пути выборки ( LocationPath), фильтрация множеств ( FilterExpr), относительные пути выборки ( RelativeLocationPath).
По этой схеме несложно выяснить старшинство операций — чем ниже выражение находится в этой иерархии, тем выше его приоритет. Для полной ясности, перечислим операции в порядке старшинства от старших, с большим приоритетом, к младшим, с меньшим приоритетом выполнения:
□ операции с путями выборки;
□ операция объединения множеств ( |);
□ унарная операция отрицания ( -);
□ умножение, деление и вычисление остатка от деления ( *, divи mod);
□ операции сложения и вычитания ( +и -);
□ операции сравнения ( <, >, <=, =>);
□ операции проверки равенства и неравенства ( =и !=);
□ операция "и" ( and);
□ операция "или" ( or).
Операции одного порядка имеют левую ассоциативность, как это было показано на примере с операциями сравнения ( 3 > 2 > 1равносильно (3 > 2) >1).
Читать дальше