• спецификация XPath 1.0. XPath применяется для поиска и указания определенных разделов и элементов в документах XML для дальнейшей работы с ними. www.w3.org/TR/xpath;
• требования XPath 2.0. XPath обновляется и в него включаются дополнительные средства поддержки XSLT 2.0 — в первую очередь поддержка схем XML. www.w3.org/TR/xpath20req.
Вас могут заинтересовать следующие руководства по XPath:
• http://www.zvon.org/xxl/XPathTutorial/General/examples.html;
• http://www.pro-solutions.com/tutorials/xpath/.
Рассмотренные нами до сих пор образцы выбора возвращали наборы узлов (node set), в которых можно было осуществить выбор или обработать набор в цикле, но XPath предоставляет более общие средства. Помимо наборов узлов, выражения XPath могут также возвращать числа, логические (true/false) значения и строки. Чтобы разобраться с XPath, необходимо разобраться с выражениями XPath. Только один вид выражения XPath (хотя и очень важный) возвращает наборы узлов, определяющие разделы документа. Как мы увидим, другие выражения XPath возвращают данные других видов.
Полный синтаксис выражений XPath описан в спецификации XPath, и я приведу его здесь для справки. Как и в случае образцов выбора, для формального определения выражений XPath W3C использует нотацию расширенных форм Бэкуса-Наура (РБНФ). (Описание этой грамматики вы можете найти по адресу www.w3.org/TR/REC-xml, раздел 6.) В следующем списке приведена нужная нам нотация РБНФ:
• ::= означает «определяется как»;
• + означает «один или больше»,
• * означает «ноль или больше»;
• | означает «или»;
• - означает «не»;
• ? означает «не обязательно»;
Также примите во внимание, что когда элемент заключен в одиночные кавычки, как 'ancestor' или '::', это значит, что элемент должен появиться в выражении буквально (как "ancestor::PLANET"), — такие элементы называются литералами, literals. Ниже приведено полное формальное определение выражения XPath (здесь оно называется Expr):
Expr ::= OrExpr
OrExpr ::= AndExpr | OrExpr 'or' AndExpr
AndExpr ::= EqualityExpr | AndExpr 'and' EqualityExpr
EqualityExpr ::= Relational Expr | EqualityExpr '=' Relational Expr
| EqualityExpr '!=' RelationalExpr
RelationalExpr ::= AdditiveExpr | RelationalExpr '<' AdditiveExpr
| RelationalExpr '>' AdditiveExpr | RelationalExpr '<=' AdditiveExpr
| RelationalExpr '>=' AdditiveExpr
AdditiveExpr ::= MultiplicativeExpr | AdditiveExpr '+' MultiplicativeExpr
| AdditiveExpr '-' MultiplicativeExpr
MultiplicativeExpr ::= UnaryExpr
| MultiplicativeExpr
MultiplyOperator ::= UnaryExpr
| MultiplicativeExpr 'div' UnaryExpr | MultiplicativeExpr 'mod' UnaryExpr
UnaryExpr ::= UnionExpr | '-' UnaryExpr
MultiplyOperator ::= '*'
UnionExpr ::= PathExpr | UnionExpr '|' PathExpr
PathExpr ::= LocationPath | FilterExpr
| FilterExpr '/' RelativeLocationPath | FilterExpr '//' RelativeLocationPath
LocationPath ::= RelativeLocationPath | AbsoluteLocationPath
AbsoluteLocationPath ::= '/' RelativeLocationPath? | AbbreviatedAbsoluteLocationPath
RelativeLocationPath ::= Step | RelativeLocationPath '/' Step
| AbbreviatedRelativeLocationPath
AbbreviatedAbsoluteLocationPath ::= '//' RelativeLocationPath
AbbreviatedRelativeLocationPath ::= RelativeLocationPath '//' Step
Step ::= AxisSpecifier NodeTest Predicate* | AbbreviatedStep
AxisSpecifier ::= AxisName '::' | AbbreviatedAxisSpecifier
AxisName ::= 'ancestor' | 'ancestor-or-self' | 'attribute' | 'child' | 'descendant'
| 'descendant-or-self' | 'following' | 'following-sibling' | 'namespace'
| 'parent' | 'preceding' | 'preceding-sibling' | 'self'
AbbreviatedAxisSpecifier ::= '@'?
NodeTest ::= NameTest | NodeType '(' ')'
| 'processing-instruction' '(' Literal ')'
NameTest ::= '*' | NCName '*' | QName
NodeType ::= 'comment' | 'text' | 'processing-instruction' | 'node'
Predicate ::= '[' PredicateExpr ']'
PredicateExpr ::= Expr
FilterExpr ::= PrimaryExpr | FilterExpr Predicate
PrimaryExpr ::= VariableReference | '(' Expr ')'
| Literal | Number | FunctionCall
VariableReference ::= '$' QName
Number ::= Digits ('.' Digits?)? | Digits
Digits ::= [0-9]+
FunctionCall ::= FunctionName '(' ( Argument ( Argument )* )? ')'
FunctionName ::= QName - NodeType
Argument ::= Expr
AbbreviatedStep := '.' | '..'
Как видите, спецификация весьма объемна, она включает и обращения к функциям XPath (с которыми мы познакомимся в следующей главе). Лучший способ понять, как работают выражения XPath, — рассмотреть их по возвращаемым типам данных.
Типы данных XPath
В XPath существует четыре типа данных, а не только тип набора узлов, который должны возвращать образцы выбора:
• наборы узлов;
• логические значения;
• числа;
• строки.
ФРАГМЕНТЫ РЕЗУЛЬТИРУЮЩЕГО ДЕРЕВА
В XSLT 1.0 к типам данных XPath добавляются фрагменты результирующего дерева. Как говорилось в главе 4, фрагменты результирующего дерева представляют собой просто фрагменты дерева, которые можно присваивать переменным XSLT. Их поддержка была удалена из рабочего проекта XSLT 1.1, поэтому, скорее всего, они не будут включены в XSLT 2.0. Фрагменты результирующего дерева можно рассматривать как типы данных при помощи <xsclass="underline" variable>, что мы и увидим в главе 9.
В следующих разделах мы по очереди рассмотрим эти типы данных.