Данный документ представляет собой перевод спецификации XML Path Language (XPath) Version 1.0 (W3C Recommendation) на русский язык. При этом нормативным документом считается оригинальная спецификация на английском языке, которую можно найти по адресу
Представленный документ может содержать ошибки перевода. |
Copyright © 1999 W3C® (MIT, INRIA, Keio). Все права защищены. Документ подчиняется правилам W3C, касающимся ответственности, торговой марки, использования документов и лицензирования программного обеспечения.
XPath - это язык адресации частей XML документа, предназначенный для использования с XSLT и Xpointer.
Данный документ был рассмотрен членами W3C и другими заинтересованными сторонами и утвержден Директором в качестве Рекомендации W3C. Данный документ является окончательным и может быть использован для ссылок и цитирования в других материалах в качестве нормативного документа. Участие организации W3C в разработке данной Рекомендации заключается в привлечении внимания к представленной спецификации и содействии ее широкому распространению. Результатом этой деятельности является повышение функциональности и универсальности Сети.
Перечень ошибок, выявленных в данной спецификации, доступен по адресу http://www.w3.org/1999/11/REC-xpath-19991116-errata.
Комментарии к этой спецификации можно отправлять по адресу www-xpath-comments@w3.org, доступен архив комментариев.
Несмотря на то, что нормативную силу имеет только английская версия данной спецификации, по адресу http://www.w3.org/Style/XSL/translations.html можно обнаружить ее перевод на другие языки.
По адресу http://www.w3.org/TR можно найти перечень текущих Рекомендаций W3C и другие технические материалы.
Данная спецификация является совместным результатом деятельности рабочих групп XSL и XML Linking, а потому является частью сразу двух проектов W3C Style activity и W3C XML activity.
C Словарь (Обсуждение спецификации) |
Язык XPath является результатом попыток создать единые синтаксис и семантику для функционала, совместно используемого XSL Transformations [XSLT] и XPointer [XPointer]. Главная задача языка XPath - адресация частей в XML документе [XML]. Для достижения этой цели язык дополнительно наделен основными функциями для манипулирования строками, числами и булевыми значениями. В XPath используется компактный синтаксис, отличный от принятого в XML, облегчающий использование языка XPath при записи адресов URI и значений атрибутов XML. XPath работает не с внешним синтаксисом XML документа, а с его абстрактной логической структурой. XPath получил такое название потому, что использовался в URL для записи путей, обеспечивающих навигацию по иерархической структуре XML документа.
Язык XPath спроектирован так, что помимо поддержки адресации он обладает естественным набором элементов, которые могут использоваться для сравнения (проверки, соответствует ли узел некому шаблону). Такой порядок использования языка XPath описывается в спецификации XSLT.
XPath представляет XML документ в виде дерева узлов. Узлы бывают различных типов, например, узлы элементов, узлы атрибутов и узлы текста. Для каждого типа узлов в XPath определяется способ вычисления строкового значения. Некоторые типы узлов имеют также имя. XPath полностью поддерживает пространства имен XML [XML Names]. В результате, имя любого узла в этом языке образуется из двух частей: локальной части и URI некого пространства имен (возможно, нулевого), такая комбинация называется расширенным именем. Указанная модель данных подробно описана в главе [5 Модель данных].
Главной синтаксической конструкцией языка XPath является выражение. Любое выражение соответствует сценарию Expr. В результате обработки выражения получается объект, относящийся к одному из четырех основных типов:
Обработка выражений осуществляется, отталкиваясь от некого контекста. В спецификациях XSLT и XPointer указывается, каким образом в XSLT и XPointer, соответственно, определяется контекст для выражений XPath. Контекст образуется из:
Положение в контексте всегда меньше или равно размеру контекста.
Схема привязки переменных контекста образуется в результате отображения множества имен переменных на множество значений переменных. Значением переменной является объект, относящийся к одному из типов, допустимых для значений выражений, либо к какому-либо дополнительному типу, не описанному в спецификации.
Библиотека функций образуется в результате отображения множества названий функций на множество функций. Каждая функция имеет нуль или более аргументов и возвращает один результат. В данном документе описывается основная библиотека функций, которую должны поддерживать все реализации XPath (см. [4 Основная библиотека функций]). Для любой функции в основной библиотеке и аргументы, и результат выполнения относятся к четырем основным типам. И XSLT, и XPointer дополняют XPath, определяя дополнительные функции, часть новых функций оперирует с четырьмя основными типами, остальные - дополнительными типами данных, определенными в XSLT и XPointer.
Декларации пространства имен образуются в результате отображения множества префиксов на множество идентификаторов URI пространств имен.
Привязка переменных контекста, библиотека функций и декларации пространства имен используются для обработки отдельных частей выражения и остаются неизменными на протяжении обработки всего выражения. Узел контекста, размер контекста и положение в контексте, используемые для обработки частей выражения, иногда могут отличаться от используемых для обработки выражения в целом. Некоторые типы выражений меняют текущий узел контекста, однако размер контекста и положение в контексте могут менять только предикаты (см. [2.4 Предикаты]). Если описывается обработка некоторого типа выражений, то всегда явно указывается, когда для обработки частей выражения используется другой узел контекста, измененные размер контекста или положение в контексте. Если же об узле контекста, размере контекста или положении в контексте в описании ничего не сказано, считается, что они остаются неизменными в ходе обработки всех подвыражений в выражении указанного типа.
Выражения XPath часто используются в атрибутах XML. Описываемая в этой главе грамматика примеряется к значению атрибута после выполнения нормализации, описанной в XML 1.0. Так, если, к примеру, в грамматике используется символ <
, то в исходном XML документе его нельзя записывать просто как <
. Вместо этого, согласно правилам XML 1.0, его необходимо маскировать, например, записав как <
. Строковые значения, используемые в выражениях, заключаются в одинарные или двойные кавычки, которые используются также для записи атрибутов XML. Поэтому, чтобы символ кавычки в этом выражении не интерпретировался XML процессором как конец значения атрибута, его необходимо записывать как ссылку на символ ("
или '
). Впрочем, если атрибут XML был заключен в двойные кавычки, в выражении можно свободно использовать символы одинарных кавычек, и наоборот.
Другим важным типом выражений является путь адресации (location path). Путь адресации выбирает некое множество узлов, отталкиваясь от некоторого узла контекста. Результатом обработки выражения, соответствующего пути адресации, является множество узлов, собранных согласно этому пути. Путь адресации может рекурсивно содержать выражения, используемые для фильтрации наборов узлов. Путь адресации соответствует сценарию LocationPath.
В представленной далее грамматике используются незавершенные конструктивы QName и NCName, описанные в [XML Names], а также пробельный символ S, описанный в [XML]. Грамматика использует ту же самую нотацию EBNF, что [XML] (за исключением того, что названия грамматических конструкций всегда пишутся с заглавной буквы).
Обработка выражения начинается с его разбиения на строки символов, подлежащих преобразованию в лексемы. Затем идет разбор полученной последовательности лексем. В промежутки между лексемами могут свободно ставиться пробельные символы. Процесс преобразования в лексемы (tokenization) описан в главе [3.7 Лексическая структура].
Хотя пути адресации (location path) и не являются самой главной грамматической конструкцией языка (LocationPath - это частный случай Expr), они имеют самое большое значение, а потому будут описаны в первую очередь.
Каждый путь адресации может быть описан с помощью простого, но довольно громоздкого синтаксиса. Существует также ряд синтаксических аббревиатур для краткого обозначения основных случаев. Сперва в этой главе с помощью развернутого синтаксиса будет дано разъяснение семантики путей адресации. Затем будет показано, каким образом сокращенный синтаксис приводится к развернутому (см. [2.5 Сокращенный синтаксис]).
Ниже приводятся некоторые примеры путей адресации, использующих развернутый синтаксис:
child::para
находит элемент para
, являющийся непосредственным потомком узла контекста
child::*
собирает все элементы, являющиеся непосредственными потомками узла контекста
child::text()
собирает все текстовые узлы, являющиеся непосредственными потомками узла контекста
child::node()
собирает все непосредственные потомки текущего узла контекста независимо от типа этих узлов
attribute::name
в текущем узле контекста находит атрибут name
attribute::*
собирает все атрибуты в текущем узле контекста
descendant::para
среди потомков узла контекста находит элементы para
ancestor::div
собирает все предки div
текущего узла контекста
ancestor-or-self::div
собирает предки div
текущего узла контекста и также, если сам узел контекста тоже является элементом div
, включает в набор и его
descendant-or-self::para
среди потомков узла контекста выбирает элементы para
а также, если сам узел контекста является элементом para
, то включает в набор и его
self::para
выбирает текущий узел контекста, если это элемент para
, либо в противном случае не выбирает ничего
child::chapter/descendant::para
выбирает элементы para
среди потомков элемента chapter
, являющегося непосредственным потомком текущего узла контекста
child::*/child::para
собирает все para
, являющиеся потомками текущего узла контекста во втором поколении
/
находит корень документа (который всегда является родителем элемента документа)
/descendant::para
в документе, которому принадлежит узел контекста, находит все элементы para
/descendant::olist/child::item
находит все элементы item
, которые имеют родителем olist
и находятся в пределах документа, в котором располагается узел контекста
child::para[position()=1]
находит первый непосредственный потомок para
текущего узла контекста
child::para[position()=last()]
находит последний непосредственный потомок para
текущего узла контекста
child::para[position()=last()-1]
находит предпоследний непосредственный потомок para
текущего узла контекста
child::para[position()>1]
среди непосредственных потомков текущего узла контекста собирает все para
, за исключением первого
following-sibling::chapter[position()=1]
находит следующий chapter
, имеющий с узлом контекста общего родителя
preceding-sibling::chapter[position()=1]
находит предыдущий chapter
, имеющий с узлом контекста общего родителя
/descendant::figure[position()=42]
находит в документе сорок второй элемент figure
/child::doc/child::chapter[position()=5]/child::section[position()=2]
находит второй section
в пятом chapter
в элементе документа doc
child::para[attribute::type="warning"]
находит все непосредственные потомки para
текущего узла контекста, имеющие атрибут type
со значением warning
child::para[attribute::type='warning'][position()=5]
среди непосредственных потомков текущего узла контекста с названием para
и имеющих атрибут type
со значением warning
находит пятый элемент
child::para[position()=5][attribute::type="warning"]
среди непосредственных потомков para
узла контекста выбирает пятый элемент, при условии что он имеет атрибут type
со значением warning
child::chapter[child::title='Introduction']
среди непосредственных потомков chapter
текущего узла контекста выбирает тот, у которого в свою очередь имеется один или несколько непосредственных потомков title
со строковым значением Introduction
child::chapter[child::title]
среди непосредственных потомков текущего узла контекста chapter
находит тот, у которого имеется один или несколько непосредственных потомков title
child::*[self::chapter or self::appendix]
среди непосредственных потомков текущего узла контекста находит chapter
и appendix
child::*[self::chapter or self::appendix][position()=last()]
из множества непосредственных потомков текущего узла контекста chapter
и appendix
выбирает последний
Пути адресации бывают двух типов: относительные и абсолютные.
Относительный путь адресации состоит из последовательности одного или нескольких шагов адресации, отделенных друг от друга символом /
. Шаги в относительном пути адресации считаются слева направо. На каждом шаге осуществляется отбор узлов, отталкиваясь от некоторого узла контекста. Основная последовательность шагов образуется последовательным перечислением шагов в порядке их выполнения. Сперва, отталкиваясь от узла контекста, последовательность шагов набирает некий набор узлов. Затем каждый узел в этом наборе поочередно используется как узел контекста для следующего шага. Все наборы узлов, полученных после выполнения такого шага, опять собираются вместе. В итоге в полученном объединении будет собран набор узлов, идентифицируемых данной последовательностью шагов. Например, формула child::div/child::para
собирает все элементы para
, являющиеся непосредственными потомками элемента div
, который сам является непосредственным потомком узла контекста, или, иными словами, находит все элементы - потомки во втором поколении para
, родителями которых являются div
.
Абсолютный путь адресации состоит из символа /
, за которым может следовать относительный путь адресации. Сам символ /
находит корневой узел документа, в котором располагался текущий узел контекста. Если за этим символом последовал относительный путь адресации, то получившийся путь адресации будет собирать набор узлов так, как если бы в качестве узла контекста был выбран корневой узел того документа, которому принадлежал действительный текущий узел контекста.
[1] | LocationPath | ::= | RelativeLocationPath | |
| AbsoluteLocationPath | ||||
[2] | AbsoluteLocationPath | ::= | '/' RelativeLocationPath? | |
| AbbreviatedAbsoluteLocationPath | ||||
[3] | RelativeLocationPath | ::= | Step | |
| RelativeLocationPath '/' Step | ||||
| AbbreviatedRelativeLocationPath |
Шаги адресации (location step) состоят из трех частей:
оси (axis), указывающей дерево взаимоотношений между текущим узлом контекста и узлами, отбираемыми на данном шаге адресации,
правила проверки узлов, указывающего тип и расширенное название узлов, отбираемых на данном шаге адресации,
нуля или более предикатов, использующих произвольные выражения для дальнейшего отсева в наборе узлов, собранных на данном шаге адресации.
Синтаксис шага адресации образуется из названия оси и правила проверки узлов, отделенных друг от друга двумя символами двоеточия. За ними следует нуль или более выражений, каждое из которых заключено в квадратные скобки. Например, в выражении child::para[position()=1]
фрагмент child
- это название оси, para
- правило проверки узла, а [position()=1]
- предикат.
Набор узлов, собранных на данном шаге адресации, - это множество узлов, полученных в результате обработки ранее собранного набора узлов с учетом оси, правила проверки узлов и последующего отсева полученного набора узлов каждым из представленных предикатов.
Исходный набор узлов образуется из узлов, имеющих с текущим узлом контекста взаимосвязь, определяемую указанной осью, имеющих тип узла и расширенное имя, отвечающих представленному правилу проверки узлов. Например, шаг адресации descendant::para
находит элементы para
, являющиеся потомками текущего узла контекста: descendant
указывает, что каждый узел в первоначальном наборе должен быть потомком текущего узла контекста, а para
указывает, что каждый узел в исходном наборе должен быть элементом с названием para
. Можно использовать оси, описаные в главе [2.2 Оси]. Возможные правила проверки описаны в главе [2.3 Проверка узлов], причем смысл некоторых правил проверки меняется в зависимости от используемой оси.
Полученный исходный набор узлов фильтруется в соответствии с первым предикатом для получения нового набора узлов, затем этот новый набор фильтруется в соответствии со вторым предикатом и так далее. Окончательный набор узлов и будет тем самым набором, который получен в результате выполнения данного шага адресации. Выбранная ось оказывает влияние на обработку выражения для каждого предиката, а потому семантика предиката строится отталкиваясь от оси. См. [2.4 Предикаты].
[4] | Step | ::= | AxisSpecifier NodeTest Predicate* | |
| AbbreviatedStep | ||||
[5] | AxisSpecifier | ::= | AxisName '::' | |
| AbbreviatedAxisSpecifier |
Можно использовать следующие оси:
ось child
включает непосредственного потомка текущего узла контекста
ось descendant
состоит из потомков текущего узла контекста. Потомок - это непосредственный потомок, непосредственный потомок непосредственного потомка и так далее. Таким образом, ось потомков не содержит узлы атрибутов и узлы пространств имен.
ось parent
включает непосредственного родителя текущего узла контекста, если таковой имеется
ось ancestor
состоит из предков текущего узла контекста. Предки текущего узла контекста - это его родитель, родитель родителя и так далее. Таким образом, ось ancestor всегда будет содержать корневой узел, за исключением единственного случая, когда корневой узел является узлом контекста.
ось following-sibling
состоит из всех последующих узлов, которые с узлом контекста имеют общего родителя. Если узлом контекста является узел атрибута или узел пространства имен, ось following-sibling
будет пустой.
ось preceding-sibling
состоит из всех предшествующих узлов, которые с узлом контекста имеют общего родителя. Если узлом контекста является узел атрибута или узел пространства имен, ось preceding-sibling
будет пустой
ось following
. В документе, где располагается текущий узел контекста, находит все узлы, которые записанные после узла контекста. В число отобранных не попадают потомки текущего узла контекста, а также узлы атрибутов и пространств имен.
ось preceding
. В документе, где располагается текущий узел контекста, находит все узлы, которые предшествуют узлу контекста. В число отобранных не попадают предки текущего узла контекста, а также узлы атрибутов и пространств имен.
ось attribute
состоит из атрибутов текущего узла контекста. Если текущий узел контекста не является элементом, ось будет пустой.
ось namespace
состоит из узлов пространства имен, относящихся к текущему узлу контекста. Если текущий узел контекста не является элементом, ось будет пустой.
ось self
содержит только сам текущий узел контекста
ось descendant-or-self
образуется текущим узлом контекста и его потомками
ось ancestor-or-self
образуется текущим узлом контекста и его предками. Как результат, ось ancestor всегда будет включать корневой узел.
Замечание: Осиancestor
,descendant
,following
,preceding
иself
осуществляют разбиение документа (если игнорировать узлы атрибутов и пространств имен). При этом указанные оси не пересекаются, а все вместе задействуют все узлы документа.
Каждая ось имеет основной тип узлов (principal node type). Если ось может содержать элементы, то для такой оси основным типом узлов будут элементы. В противном случае в качестве основного берется тип тех узлов, которые эта ось может содержать. Таким образом,
Правило проверки узлов, соответствующее сценарию QName, имеет результатом true тогда и только тогда, когда тип узла (см. [5 Модель данных]) совпадает с основным типом узлов, а его расширенное имя совпадает с расширенным именем, указанным этим QName. Например, child::para
собирает элементы para
, являющиеся непосредственными потомками текущего узла контекста. Если текущий узел контекста не имеет непосредственного потомка para
, то будет получен пустой набор узлов. attribute::href
в текущем узле контекста выбирает атрибут href
. Если текущий узел контекста не имеет атрибута href
, будет получен пустой набор узлов.
QName в правиле для проверки узла, преобразуется в расширенное имя с помощью деклараций пространств имен в контексте этого выражения. Точно так же преобразуются названия типов элементов в начальных и конечных тэгах, за исключением того, что не используется пространство имен по умолчанию, декларированное с помощью xmlns
: если QName не имеет префикса, URI пространства имен будет нулевым (таким же способом обрабатываются названия атрибутов). Если QName имеет префикс, для которого в контексте выражения нет соответствующей декларации пространства имен, фиксируется ошибка.
Правило проверки узлов *
имеет результатом true для любого узла, если его тип соответствует основному. Например, child::*
найдет все элементы, являющиеся непосредственными потомками текущего узла контекста, а attribute::*
соберет все атрибуты текущего узла контекста.
Правило проверки узлов может иметь вид NCName:*
. В этом случае префикс, так же как и в случае с QName, преобразуется с помощью деклараций пространства имен в контексте. Если для этого префикса в контексте выражения не найдено соответствующей декларации пространства имен, фиксируется ошибка. Указанное правило проверки узла будет выдавать true для любого узла основного типа, чье расширенное имя имеет именно то URI пространства имен, к которому привязан указанный префикс, независимо от локальной части в названии узла.
Правило проверки узлов text()
будет давать результат true для любого текстового узла. Например, child::text()
будет собирать текстовые узлы, являющиеся непосредственными потомками текущего узла контекста. Точно так же, правило проверки узлов comment()
будет выдавать true для любого узла комментария, а правило проверки узлов processing-instruction()
- для любой инструкции обработки. Правило проверки processing-instruction()
может иметь аргумент типа Literal. В этом случае проверка будет давать true для любой инструкции проверки, чье название соответствует значению этого аргумента.
Правило проверки узлов node()
будет выдавать true для любого узла, к какому бы типу он не относится.
[7] | NodeTest | ::= | NameTest | |
| NodeType '(' ')' | ||||
| 'processing-instruction' '(' Literal ')' |
Оси делятся на прямые и обратные. Ось, содержащая лишь текущий узел контекста или те узлы, которые в документе следуют за ним, называется прямой осью (forward axis). Ось, содержащая текущий узел контекста или те узлы, которые в документе предшествуют ему, называется обратной осью (reverse axis). Таким образом, оси ancestor, ancestor-or-self, preceding и preceding-sibling являются обратными осями, а все остальные - прямыми. Поскольку ось self всегда содержит не более одного узла, то нет разницы, является ли она прямой или обратной. Положение близости (proximity position) по отношению к оси для какого-либо члена в наборе узлов определяется как положение узла в наборе, когда последний выстроен в соответствии с порядком следования узлов в документе, если ось является прямой, или в обратном порядке, если ось является обратной. Первая позиция имеет номер 1.
Для получения нового набора предикат фильтрует имеющийся набор узлов, отталкиваясь от оси. Каждый узел в исходном наборе, подлежащем фильтрации, поочередно становится узлом контекста и для него проверяется PredicateExpr. При этом в качестве размера контекста используется количество узлов в исходном наборе, а в качестве положения в контексте берется положение близости к оси. Если для данного узла PredicateExpr оценивается как true, то этот узел попадает во вновь создаваемый набор узлов, в противном случае узел туда не попадает.
Проверка PredicateExpr сводится к обработке Expr и приведению результата к булевому значению. Если результатом обработки является число, оно будет преобразовано в true, если соответствует положению узла в контексте. В противном случае оно преобразуется в false. Если же результат обработки не является числом, то он будет приведен к булевому значению как при вызове функции boolean. Таким образом, путь адресации para[3]
равнозначен para[position()=3]
.
[8] | Predicate | ::= | '[' PredicateExpr ']' | |
[9] | PredicateExpr | ::= | Expr |
Некоторые примеры путей адресации, использующих сокращенный синтаксис:
para
находит элемент para
, являющийся непосредственным потомком текущего узла контекста
*
находит все элементы, являющиеся непосредственными потомками текущего узла контекста
text()
находит все текстовые узлы, являющиеся непосредственными потомками текущего узла контекста
@name
выделяет атрибут name
в текущем узле контекста
@*
находит все атрибуты текущего узла контекста
para[1]
находит первый непосредственный потомок para
текущего узла контекста
para[last()]
находит последний непосредственный потомок para
текущего узла контекста
*/para
находит все потомки во втором поколении para
текущего узла контекста
/doc/chapter[5]/section[2]
в doc
в пятом chapter
находит второй section
chapter//para
собирает элементы para
, являющиеся потомками элемента chapter
, который является непосредственным потомком текущего узла контекста
//para
собирает все para
, являющиеся потомками корневого узла документа, то есть находит все элементы para
в том документе, где располагается текущий узел контекста
//olist/item
в документе, где располагается текущий узел контекста, находит все элементы item
, имеющие родителем olist
.
выделяет текущий узел контекста
.//para
собирает элементы para
, являющиеся потомками текущего узла контекста
..
выделяет родителя текущего узла контекста
../@lang
выделяет атрибут lang
, принадлежащий родителю текущего узла контекста
para[@type="warning"]
находит все непосредственные потомки para
текущего узла контекста, имеющие атрибут type
со значением warning
para[@type="warning"][5]
находит пятый по счету из непосредственных потомков para
текущего узла контекста, имеющих атрибут type
со значением warning
para[5][@type="warning"]
извлекает пятый непосредственный потомок para
текущего узла контекста, если этот потомок имеет атрибут type
со значением warning
chapter[title="Introduction"]
получает непосредственный потомок текущего узла контекста chapter
, который в свою очередь имеет один или несколько непосредственных потомков title
со строковым значением, равным Introduction
chapter[title]
находит непосредственный потомок chapter
текущего узла контекста, который имеет один или несколько непосредственных потомков title
employee[@secretary and @assistant]
находит все непосредственные потомки employee
данного узла контекста, которые имеют оба атрибута secretary
и assistant
Самой важной является аббревиатура child::
, которую при записи шага адресации всегда можно опустить. Фактически, child
используется как ось по умолчанию. Например, путь адресации div/para
становится сокращением для child::div/child::para
.
Аналогичные аббревиатуры имеются и для атрибутов: attribute::
может быть сокращен до @
. Например, путь адресации para[@type="warning"]
является сокращением для child::para[attribute::type="warning"]
, а следовательно, находит непосредственные потомки para
, имеющие атрибут type
, значение которого равно warning
.
//
является сокращением для /descendant-or-self::node()/
. Например, //para
- это сокращение для /descendant-or-self::node()/child::para
, а потому будет находить в документе все элементы para
(путь //para
найдет элемент para
, даже если последний является элементом документа, поскольку узел элемента документа является непосредственным потомком корневого узла). div//para
- это сокращение для div/descendant-or-self::node()/child::para
, а потому находит все потомки para
для непосредственного потомка div
.
Замечание: Путь адресации//para[1]
имеет иное значение, чем путь адресации/descendant::para[1]
. Последний отыскивает первый элемент-потомокpara
, а предыдущий находит все элементы-потомкиpara
, являющиеся для своего родителя первым непосредственным потомкомpara
.
Шаг адресации .
является сокращением для self::node()
. Особенно эта запись полезна в сочетании с //
. Например, путь адресации .//para
является сокращением для
self::node()/descendant-or-self::node()/child::para
а потому будет находить все элементы para
, являющиеся потомками текущего узла контекста.
Точно так же, шаг адресации ..
является сокращением для parent::node()
. Например, ../title
- это сокращенная запись для parent::node()/child::title
, а потому для родителя текущего узла контекста будет находить непосредственные потомки title
.
[10] | AbbreviatedAbsoluteLocationPath | ::= | '//' RelativeLocationPath | |
[11] | AbbreviatedRelativeLocationPath | ::= | RelativeLocationPath '//' Step | |
[12] | AbbreviatedStep | ::= | '.' | |
| '..' | ||||
[13] | AbbreviatedAxisSpecifier | ::= | '@'? |
VariableReference заменяется значением, которое в текущем контексте поставлено в соответствие данному имени переменной (согласно схеме привязки переменных контекста). Если же по схеме привязки переменных контекста с данным именем переменной не связано ни одно значение, фиксируется ошибка.
Для группировки выражений могут использоваться круглые скобки.
[14] | Expr | ::= | OrExpr | |
[15] | PrimaryExpr | ::= | VariableReference | |
| '(' Expr ')' | ||||
| Literal | ||||
| Number | ||||
| FunctionCall |
При обработке выражения FunctionCall используется FunctionName, позволяющее функцию в выражении сопоставить с библиотекой функций, соответствующей контексту обрабатываемого выражения, обработать каждый из аргументов, приведя к тому типу, который необходим для этой функции, и наконец вызвать саму функцию, передав ей преобразованные аргументы. Если указано неправильное количество аргументов или какой-либо аргумент не может быть приведен к требуемому типу, фиксируется ошибка. Результатом обработки выражения FunctionCall будет результат, возвращаемый соответствующей функцией.
Приведение аргумента к типу string осуществляется как при вызове функции string. Приведение к типу number осуществляется как при вызове функции number. Приведение к типу boolean осуществляется как при вызове функции boolean. Аргумент, тип которого не соответствует набору узлов, уже не может быть приведен к этому типу.
[16] | FunctionCall | ::= | FunctionName '(' ( Argument ( ',' Argument )* )? ')' | |
[17] | Argument | ::= | Expr |
В качестве выражения может использоваться путь адресации. Результатом обработки такого выражения будет набор узлов, отобранных согласно указанному пути адресации.
Оператор |
находит объединение операндов, которые должны являться наборами узлов.
Точно так же, как и в случае с путями адресации, для фильтрации выражений могут использоваться предикаты. Однако если результатом обработки выражения, подлежащего фильтрации, будет не набор узлов, фиксируется ошибка. Указанный предикат осуществляет фильтрацию набора узлов относительно оси child.
Замечание: Значение предиката решающим образом зависит от используемой оси. Например,preceding::foo[1]
возвращает первый элементfoo
, встретившийся при сканировании документа в обратном порядке, поскольку предикат[1]
относится к оси preceding. И наоборот,(preceding::foo)[1]
возвращает первый элементfoo
, обнаруженный при просмотре документа в прямом порядке, поскольку в этом случае с предикатом[1]
связана ось child.
Операторы /
и //
формируют и выражение, и относительный путь адресации. Если результатом обработки такого выражения окажется не набор узлов, фиксируется ошибка. Оператор /
образует композицию в точности так же, как символ /
, использовавшийся в пути адресации. Как и в случае с путями адресации, //
является сокращением для /descendant-or-self::node()/
.
Не существует таких типов объектов, которые можно было бы преобразовать в набор узлов.
[18] | UnionExpr | ::= | PathExpr | |
| UnionExpr '|' PathExpr | ||||
[19] | PathExpr | ::= | LocationPath | |
| FilterExpr | ||||
| FilterExpr '/' RelativeLocationPath | ||||
| FilterExpr '//' RelativeLocationPath | ||||
[20] | FilterExpr | ::= | PrimaryExpr | |
| FilterExpr Predicate |
Объект типа boolean может иметь два значения: true и false.
Обработка выражения or
сводится к обработке каждого операнда и приведению его значения к булевому типу, как если бы имел место вызов функции boolean. Если значением какого-либо из операндов будет true, то и значением всего выражения в целом тоже будет true, в противном случае это будет false. Если в результате обработки левого операнда получено true, то обработка правого операнда не производится.
Обработка выражения and
сводится к обработке каждого операнда и приведению его значения к булевому типу, как если бы имел место вызов функции boolean. Если значением обоих операндов будет true, то и значением всего выражения будет true, в противном случае это будет false. Если в результате обработки левого операнда получено false, то обработка правого операнда не производится.
Обработка EqualityExpr (который содержит не только RelationalExpr) или RelationalExpr (который содержит не только AdditiveExpr) сводится к сравнению объектов, полученных в результате обработки обоих операндов. Процедура сравнения объектов описывается в трех следующих параграфах. В первом параграфе сравнение наборов узлов определяется через сравнение более элементарных объектов. Это в равной степени относится к =
, !=
, <=
, <
, >=
и >
. Во втором параграфе описываются процедуры сравнения =
и !=
для объектов, не являющихся наборами узлов. В третьем параграфе для объектов, не являющихся наборами узлов, описываются операторы сравнения <=
, <
, >=
и >
.
Если оба сравниваемых объекта являются наборами узлов, то их сравнение будет иметь результатом true тогда и только тогда, когда и в первом и во втором наборах имеются узлы, такие что в результате сравнения строковых значений этих двух узлов имеем true. Если одним из сравниваемых объектов является набор узлов, а вторым - число, то их сравнение будет иметь результатом true тогда и только тогда, когда в представленном наборе имеется такой узел, что сравнение его строкового значения, преобразованного в число с помощью функции number, со вторым операндом даст в результате true. Если одним из сравниваемых объектов является набор узлов, а вторым строка, то в результате их сравнения true будет получаться тогда и только тогда, когда в наборе имеется такой узел, что результатом сравнения строкового значения этого узла со второй представленной строки будет true. Если одним из сравниваемых объектов является набор узлов, а вторым булево значение, то в результате их сравнения true будет получено тогда и только тогда, когда сравнение представленного булевого значения с результатом приведения набора узлов к булевому значению с помощью функции boolean также даст true.
Если ни один из объектов, подлежащих сравнению, не является набором узлов, а оператором является =
или !=
, то перед сравнением эти объекты приводятся к единому типу по следующему алгоритму: Если по крайней мере один из сравниваемых объектов имеет булевый тип, то оба сравниваемых объекта приводятся к булевому типу как при вызове функции boolean. В противном случае, если хотя бы один из сравниваемых объектов является числом, то оба объекта преобразуется в число как при вызове функции number. В остальных случаях оба сравниваемых объекта преобразуются в строки как при вызове функции string. Оператор сравнения =
будет иметь результатом true тогда и только тогда, когда оба объекта идентичны. Оператор сравнения !=
будет иметь результатом true тогда и только тогда, когда объекты неидентичны. Сравнение чисел осуществляется согласно требованиям IEEE 754 [IEEE 754]. Два булевых значения равны, если оба являются true или оба являются false. Две строки считаются равными тогда и только тогда, когда обе образованы одной и той же последовательностью UCS символов.
Замечание: Если$x
соответствует набору узлов, то выражение$x="foo"
имеет иное значение, чемnot($x!="foo")
: Первое выражение имеет результатом true тогда и только тогда, когда в$x
имеется какой-нибудь узел со строковым значениемfoo
. Второе выражение имеет результатом true когда и только тогда, когда в$x
все узлы имеют строковое значениеfoo
.
Если ни один из подлежащих сравнению объектов не является набором узлов, а оператором является <=
, <
, >=
или >
, то сравниваемые объекты сперва преобразуются в числа, а затем выполняется сравнение этих чисел в соответствии с требованиями IEEE 754. Оператор сравнения <
будет давать true тогда и только тогда, когда первое число меньше второго. Оператор сравнения <=
будет давать true тогда и только тогда, когда первое число меньше или равно второму. Оператор сравнения >
будет давать true тогда и только тогда, когда первое число больше второго. Оператор сравнения >=
будет давать true тогда и только тогда, когда первое число больше или равно второму.
Замечание: Если в XML документе встречается выражение XPath, то операторы<
и<=
должны быть маскированы в соответствии с правилами XML 1.0, например, заменой на<
и<=
соответственно. В следующем примере значением атрибутаtest
является выражение XPath:<xsl:if test="@value < 10">...</xsl:if>
[21] | OrExpr | ::= | AndExpr | |
| OrExpr 'or' AndExpr | ||||
[22] | AndExpr | ::= | EqualityExpr | |
| AndExpr 'and' EqualityExpr | ||||
[23] | EqualityExpr | ::= | RelationalExpr | |
| EqualityExpr '=' RelationalExpr | ||||
| EqualityExpr '!=' RelationalExpr | ||||
[24] | RelationalExpr | ::= | AdditiveExpr | |
| RelationalExpr '<' AdditiveExpr | ||||
| RelationalExpr '>' AdditiveExpr | ||||
| RelationalExpr '<=' AdditiveExpr | ||||
| RelationalExpr '>=' AdditiveExpr |
Замечание: Согласно представленной выше грамматике, операторы будут иметь следующий порядок приоритета (наименьший приоритет идет первым):Все указанные операторы имеют ассоциативность слева. Например, выражение
or
and
=
,!=
<=
,<
,>=
,>
3 > 2 > 1
эквивалентно выражению(3 > 2) > 1
, имеющему значение false.
Число в XPath имеет представление с плавающей точкой. Число может принимать любое значение в 64-битном формате IEEE 754 двойной точности [IEEE 754]. Сюда включены специальное значение "Not-a-Number" (NaN), положительная и отрицательная бесконечности, а также положительный и отрицательный нули. Список основных правил стандарта IEEE 754 см. в главе 4.2.3 документа [JLS]
Операнды для числовых операторов преобразуются в числа как при вызове функции number.
Оператор +
выполняет сложение.
Оператор -
осуществляет вычитание.
Замечание: поскольку язык XML допускает использование в именах символа-
, то оператору вычитания-
, как правило, должен предшествовать символ пробела. Например, записьfoo-bar
обрабатывается как набор элементов с названиемfoo-bar
, являющихся непосредственными потомками, тогда какfoo - bar
обрабатывается как разница результатов преобразования в число строковых значений элементовfoo
иbar
, также являющихся непосредственными потомками.
Оператор div
осуществляет деление чисел с плавающей точкой в соответствии с требованиями IEEE 754.
Оператор mod
возвращает остаток от усекающего деления. Например,
5 mod 2
возвращает 1
5 mod -2
возвращает 1
-5 mod 2
возвращает -1
-5 mod -2
возвращает -1
Замечание: Указанный оператор аналогичен оператору %
в Java или ECMAScript.
Замечание: Данный оператор отличается от оператора remainder из IEEE 754, который возвращает остаток округляющего деления.
[25] | AdditiveExpr | ::= | MultiplicativeExpr | |
| AdditiveExpr '+' MultiplicativeExpr | ||||
| AdditiveExpr '-' MultiplicativeExpr | ||||
[26] | MultiplicativeExpr | ::= | UnaryExpr | |
| MultiplicativeExpr MultiplyOperator UnaryExpr | ||||
| MultiplicativeExpr 'div' UnaryExpr | ||||
| MultiplicativeExpr 'mod' UnaryExpr | ||||
[27] | UnaryExpr | ::= | UnionExpr | |
| '-' UnaryExpr |
Строки образуются последовательностью из нуля и более символов, определенных в Рекомендации XML [XML]. Следовательно, в XPath каждый символ соответствует единственному абстрактному символу Unicode с единственным соответствующим скалярным значением Unicode (см. [Unicode]). Это не то же самое, что 16-битное значение кода Unicode, когда абстрактный символ со скалярным значением, большим чем U+FFFF, представляется в кодировке Unicode парой 16-битных значений (суррогатной парой). Во многих языках программирования строка представляется в виде последовательности 16-битных значений кодировки Unicode. Реализация XPath с помощью таких языков должна гарантировать, что каждая суррогатная пара обрабатывается именно как один символ XPath.
Замечание: В кодировке Unicode две строки могут считаться идентичными даже несмотря на то, что они образованы различными последовательностями абстрактных символов Unicode. Например, некоторые ударные символы могут быть представлены как в собранном (precompressed), так и в разобранном (decompressed) виде. Поэтому выражения XPath могут дать неожиданный результат, если такие символы в XPath выражении и в XML документе не были нормализованы в каноническую форму. См. документ [Character Model].
В результате лексического анализа всегда возвращается самая длинная из возможных лексем.
Для большего удобства чтения в выражения могут быть вставлены пробельные символы, даже если грамматика и не содержит на то явных указаний: в шаблонах перед любым ExprToken и после него всегда можно свободно поставить ExprWhitespace.
Чтобы устранить указанную неоднозначность грамматики ExprToken, должны применяться следующие специальные правила лексического анализа:
Если предыдущей лексемой было не @
, ::
, (
, [
, ,
или Operator, то лексема *
должна распознаваться как оператор умножения MultiplyOperator, а NCName - как OperatorName.
Если за NCName следует символ круглой скобки (
(возможно не сразу, а через ExprWhitespace), то эта лексема должна распознаваться как NodeType или FunctionName.
Если за NCName следуют два символа двоеточия ::
(возможно не сразу, а через ExprWhitespace), то данная лексема должна распознаваться как AxisName.
В остальных случаях лексема не должна распознаваться как MultiplyOperator, OperatorName, NodeType, FunctionName или AxisName.
[28] | ExprToken | ::= | '(' | ')' | '[' | ']' | '.' | '..' | '@' | ',' | '::' | |
| NameTest | ||||
| NodeType | ||||
| Operator | ||||
| FunctionName | ||||
| AxisName | ||||
| Literal | ||||
| Number | ||||
| VariableReference | ||||
[29] | Literal | ::= | '"' [^"]* '"' | |
| "'" [^']* "'" | ||||
[30] | Number | ::= | Digits ('.' Digits?)? | |
| '.' Digits | ||||
[31] | Digits | ::= | [0-9]+ | |
[32] | Operator | ::= | OperatorName | |
| MultiplyOperator | ||||
| '/' | '//' | '|' | '+' | '-' | '=' | '!=' | '<' | '<=' | '>' | '>=' | ||||
[33] | OperatorName | ::= | 'and' | 'or' | 'mod' | 'div' | |
[34] | MultiplyOperator | ::= | '*' | |
[35] | FunctionName | ::= | QName - NodeType | |
[36] | VariableReference | ::= | '$' QName | |
[37] | NameTest | ::= | '*' | |
| NCName ':' '*' | ||||
| QName | ||||
[38] | NodeType | ::= | 'comment' | |
| 'text' | ||||
| 'processing-instruction' | ||||
| 'node' | ||||
[39] | ExprWhitespace | ::= | S |
В данной главе описываются функции, которые при реализации XPath должны быть всегда внесены в библиотеку функций, используемых для обработки выражений.
Каждая функция в этой библиотеке описывается с помощью прототипа, в котором указываются тип возвращаемого значения, название функции и тип аргументов. Если за описанием типа аргумента следует знак вопроса, то данный аргумент является необязательным, в противном случае аргумент обязателен.
Функция last возвращает число, равное размеру контекста обрабатываемого выражения.
Функция position возвращает число, равное положению в контексте обрабатываемого выражения.
Функция: number count(node-set)
Функция count возвращает количество узлов в наборе, представленном в качестве аргумента.
Функция id находит элементы по их уникальному идентификатору (см. [5.2.1 Уникальные ID]). Если аргументом функции id является набор узлов, то ее результатом будет объединение узлов, полученных в результате вызова функции id для строкового значения каждого узла в наборе, указанном в качестве аргумента. Если аргумент функции id относится к какому-либо другому типу, то этот аргумент сперва преобразуется в строку как при вызове функции string. Затем полученная строка разбивается на лексемы, разделенные пробельными символами (пробельный символ - это любая последовательность символов, соответствующих сценарию S). Результатом вызова функции в этом случае является набор узлов, состоящий из элементов, относящихся к тому же документу, где находился узел контекста, и имеющих уникальный идентификатор, равный одной из лексем, представленных в этом списке.
id("foo")
находит элемент с уникальным идентификатором foo
id("foo")/child::para[position()=5]
среди непосредственных потомков элемента с уникальным идентификатором foo
находит пятый элемент para
Функция: string local-name(node-set?)
Среди набора узлов, указанного в аргументе, функция local-name находит тот узел, который в документе встретится первым, и выделяет локальную часть его расширенного имени. Если в аргументе функции представлен пустой набор узлов или первый обнаруженный узел не имеет расширенного имени, возвращается пустая строка. Если аргумент функции отсутствует, то по умолчанию используется набор, состоящий из единственного члена - узла контекста.
Функция: string namespace-uri(node-set?)
В наборе, указанном в аргументе, функция namespace-uri находит тот узел, который в документе встретится первым, и в его расширенном имени выделяет URI пространства имен. Если указанный в аргументе набор узлов пуст, первый найденный узел не имеет расширенного имени, или же URI пространства имен в расширенном имени оказался нулевым, то функция возвращает пустую строку. Если аргумент отсутствует, то по умолчанию берется набор, в котором узел контекста является единственным членом.
Замечание: Для узлов, которые не соответствуют ни элементам, ни атрибутам, функция namespace-uri возвращает пустую строку.
Функция: string name(node-set?)
В наборе, указанном в аргументе, функция name находит узел, который в документе встретится первым, и возвращает строку, содержащую QName, которое представляет расширенное имя данного узла. Указанная конструкция QName должна представлять расширенное имя, исходя из деклараций пространств имен, доступная для того узла, чье расширенное имя должно быть представлено. Как правило, это тот самый QName, который был представлен в исходном документе XML. Однако это не обязательно должно быть так в случае, когда декларации, воздействующие на данный узел, с одним и тем же пространством имен связывают несколько префиксов. Тем не менее, реализация может содержать сведения о первоначальном префиксе представляемых узлов, в таком случае может выполняться проверка с тем, чтобы возвращаемая строка была всегда такой же, как QName, используемый в исходном документе XML. Если указанный в аргументе набор узлов пуст или первый узел не имеет расширенного имени, возвращается пустая строка. Если аргумент опущен, то по умолчанию используется набор, содержащий только узел контекста.
Замечание: Для узлов, не являющихся ни элементом, ни атрибутом, строка, возвращаемая функцией name, будет той же самой, что и строка, возвращаемая функцией local-name.
Функция: string string(object?)
Функция string преобразует объект в строку следующим образом:
Набор узлов преобразуется в строку, соответствующую строковому значению того узла в этом наборе, который первым встретится в документе. Если представленный набор узлов пуст, возвращается пустая строка.
Число преобразуется в строку следующим образом
NaN преобразуется в строку NaN
положительный нуль преобразуется в строку 0
отрицательный нуль преобразуется в строку 0
положительная бесконечность преобразуется в строку Infinity
отрицательная бесконечность преобразуется в строку -Infinity
Если число целое, то оно представляется в десятичной форме Number без десятичной точки и ведущих нулей. Если число отрицательное, то его представлению предшествует знак минус (-
).
В противном случае число представляется в десятичной форме Number, включающей десятичную точку, по крайней мере одну цифру до десятичной точки и, по крайней мере, одну после. Если число отрицательное, то его представлению предшествует знак минус (-
). Десятичной точке не должны предшествовать ведущие нули, за исключением одной обязательной цифры перед десятичной точкой. После десятичной точки должна следовать хотя бы одна цифра, вообще же количество цифр после точки должно быть ровно таким, сколько необходимо, чтобы отличить это число от других чисел в формате IEEE 754, но не большим.
Булево значение false преобразуется в строку false
. Булево значение true преобразуется в строку true
.
Способ преобразования в строку объекта, не относящегося к четырем основным типам, зависит от этого типа.
Если аргумент опущен, то по умолчанию используется набор узлов, единственным членом которого является узел контекста.
Замечание: Функцияstring
не предназначена для преобразования чисел в строки для показа пользователю. Для этой цели предназначены функцияformat-number
и элементxsl:number
из [XSLT].
Функция: string concat(string, string, string*)
Функция concat возвращает объединение представленных аргументов.
Функция: boolean starts-with(string, string)
Функция starts-with возвращает true если строка второго аргумента совпадает с началом строки первого аргумента. В противном случае функция возвращает false.
Функция: boolean contains(string, string)
Функция contains возвращает true если строка второго аргумента является частью строки первого аргумента. В противном случае функция возвращает false.
Функция: string substring-before(string, string)
Функция substring-before возвращает ту часть строки первого аргумента, которая предшествует первому появлению строки второго аргумента. Если строка второго аргумента не содержится в строке первого аргумента, то функция возвращает пустую строку. Например, substring-before("1999/04/01","/")
возвратит 1999
.
Функция: string substring-after(string, string)
Функция substring-after возвращает ту часть строки первого аргумента, которая следует за первым появлением строки второго аргумента. Если строка второго аргумента не содержится в строке первого аргумента, функция возвращает пустую строку. Например, substring-after("1999/04/01","/")
возвращает 04/01
, а substring-after("1999/04/01","19")
возвращает 99/04/01
.
Функция: string substring(string, number, number?)
Функция substring возвращает ту часть строки первого аргумента, которая начинается с позиции, указанной вторым аргументом, и имеет длину, указанную в третьем аргументе. Например, substring("12345",2,3)
возвращает "234"
. Если третий аргумент не был представлен, функция возвращает подстроку, начинающуюся с позиции, указанной во втором аргументе, и продолжащуюся до конца строки. Например, substring("12345",2)
возвращает "2345"
.
Точнее выражаясь, каждый символ в строке (см. [3.6 Строки]) имеет номер позиции: позиция первого символа - 1, второго символа - 2 и т.д.
Замечание: Такой порядок отличается от принятого в Java и ECMAScript, где метод String.substring
считает позицию первого символа нулевой.
Возвращаемая подстрока содержит те символы, позиция которых больше или равна округленному значению второго аргумента, а также, если был указан третий аргумент, меньше чем сумма округленных значений второго и третьего аргументов. Использовавшиеся выше операции сравнения и сложения отвечают правилам стандарта IEEE 754, округление осуществляется как при вызове функции round. Приведенные далее примеры иллюстрируют различные нестандартные ситуации:
substring("12345", 1.5, 2.6)
возвращает "234"
substring("12345", 0, 3)
возвращает "12"
substring("12345", 0 div 0, 3)
возвращает ""
substring("12345", 1, 0 div 0)
возвращает ""
substring("12345", -42, 1 div 0)
возвращает "12345"
substring("12345", -1 div 0, 1 div 0)
возвращает ""
Функция: number string-length(string?)
Функция string-length возвращает число символов в строке (см. [3.6 Строки]). Если аргумент опущен, то по умолчанию берется узел контекста и преобразуется в строку, иными словами, берется строковое значение текущего узла контекста.
Функция: string normalize-space(string?)
Функция normalize-space возвращает строку аргумента с нормализацией пробельных символов. Сюда входит удаление начальных и завершающих пробельных символов, а также замена оставшихся последовательностей пробельных символов одиночными пробелами. Пробельными считаются символы, являющиеся таковыми согласно сценарию S в языке XML. Если аргумент опущен, то по умолчанию в строку преобразуется узел контекста, иными словами, в качестве аргумента берется строковое значение текущего узла контекста.
Функция: string translate(string, string, string)
Функция translate возвращает строку первого аргумента, в которой символы, указанные в строке второго аргумента, заменены символами строки третьего аргумента в соответствующей позиции. Например, translate("bar","abc","ABC")
возвращает строку BAr
. Если в строке второго аргумента имеется символ, для которого нет парного символа в соответствующей позиции третьей строки (поскольку строка второго аргумента длиннее строки третьего аргумента), то все экземпляры этого символа изымаются из первой строки. Например, translate("--aaa--","abc-","ABC")
возвращает "AAA"
. Если какой-либо символ встретился во второй строке несколько раз, то правило замены определяется первым встреченным экземпляром. Если строка третьего аргумента длиннее, чем строка второго, лишние символы игнорируются.
Замена: Функция translate не может обеспечить преобразование регистра для всех языков. Для преобразования регистра в будущих версии XPath могут появиться дополнительные функции.
Функция: boolean boolean(object)
Функция boolean преобразует аргумент в булево значение следующим образом:
число преобразуется в true тогда и только тогда, когда оно не является ни NaN, ни положительным или отрицательным нулем
набор узлов преобразуется в true тогда и только тогда, когда он непустой
строка преобразуется true тогда и только тогда, когда она имеет ненулевую длину
процедура преобразования в булево значение объекта, не относящегося в четырем основным типам, зависит от типа этого объекта
Функция not возвращает true тогда и только тогда, когда ее аргументом является false, и false в противном случае.
Функция true возвращает true.
Функция false возвращает false.
Функция lang возвращает true или false в зависимости от того, является ли язык узла контекста, указываемый в атрибутах xml:lang
, тем же самым языком (или подмножеством языка), что указан в строке атрибута. Язык узла контекста задается значением атрибута xml:lang
, указанного в этом узле, либо, если сам узел контекста не имеет атрибута xml:lang
, то значением атрибута xml:lang
у его ближайшего предка, имеющего такой атрибут. Если требуемый атрибут не найден, функция lang возвращает false. Если же атрибут найден, то функция lang возвращает true когда значение этого атрибута равно значению аргумента. При этом регистр игнорируется. Кроме того, если значение атрибута имеет суффикс, начинающийся с дефиса (-
), то перед сравнением такой суффикс может быть отброшен. Например, вызов функции lang("en")
возвращает true если узлом контекста является любой из пяти указанных элементов:
<para xml:lang="en"/> <div xml:lang="en"><para/></div> <para xml:lang="EN"/> <para xml:lang="en-us"/>
Функция: number number(object?)
Функция number преобразует свой аргумент в число следующим образом:
строка, образованная необязательным пробельным символом, за которым следует необязательный знак минус, Number и пробельный символ, преобразуется в число IEEE 754, ближайшее к математическому значению, представленному этой строкой (в соответствии с правилом округления IEEE 754). Любая другая строка преобразуется в NaN.
булево значение true преобразуется в 1, булево значение false преобразуется в 0
набор узлов сперва преобразуется в строку как при вызове функции string, а затем преобразуется по тому же алгоритму, что и строковый аргумент
объект, не соответствующий ни одному из четырех базовых типов, преобразуется в число по алгоритму, специально задаваемому для этого типа
Если аргумент отсутствует, то по умолчанию берется набор, содержащий только узел контекста.
Замечание: Функция number не должна использоваться для преобразования числовых данных, встреченных в каком-либо элементе XML документа, если не известно, что элемент данного типа представляет числовые данные в независимом от языка формате (обычно перед показом пользователю такой элемент переводятся в формат, соответствующий языку). Кроме того, функция number не может использоваться, если независимый от языка формат элемента не соответствует синтаксису XPath для Number.
Функция sum возвращает сумму всех узлов из набора, указанного в аргументе. Перед суммированием строковые значения узлов преобразуются в числа.
Функция floor возвращает наибольшее число (ближайшее к положительной бесконечности), которое не превышает значение представленного аргумента и является целым.
Функция: number ceiling(number)
Функция ceiling возвращает наименьшее число (ближайшее в отрицательной бесконечности), которое не меньше значения представленного аргумента и является целым.
Функция round возвращает целое число, ближайшее к значению аргумента. Если таких чисел два, то возвращается то из них, которое ближе к положительной бесконечности. Если аргументом является NaN, функция возвращает NaN. Если аргументом является положительная бесконечность, возвращается положительная бесконечность. Если аргументом является отрицательная бесконечность, возвращается отрицательная бесконечность. Если аргументом является положительный нуль, функция возвращает положительный нуль. Если аргументом является отрицательный нуль, функция возвращает отрицательный нуль. Если аргумент меньше нуля, но больше или равен -0.5, возвращается отрицательный нуль.
Замечание: В последних двух случаях вызов функции round имеет иной результат, чем добавление 0.5 и последующий вызов функции floor.
XPath обрабатывает XML документ как древовидную структуру. В этой главе описывается, как именно XPath моделирует дерево XML документа. Указанная модель носит лишь концептуальный характер и не содержит указаний для какой-либо конкретной реализации. Взаимосвязь этой модели с XML Information Set [XML Infoset] описывается в Приложении [B XML Information Set Mapping].
XML документы, обрабатываемые XPath, должны отвечать требованиям Рекомендации XML Namespaces [XML Names].
Дерево состоит из узлов. Узлы бывают семи типов:
корневые узлы
узлы элементов
узлы текста
узлы атрибутов
узлы пространства имен
узлы инструкций обработки
узлы комментариев
Для каждого типа узлов существует алгоритм определения строкового значения узла этого типа. Для некоторых типов узлов строковое значение является частью самого узла, для других типов узлов строковое значение вычисляется по строковому значению узлов - потомков.
Замечание: Для узлов элементов и корневых узлов строковое значение узла - это не та же самая строка, которую возвращает метод nodeValue
модели DOM (см. [DOM]).
Некоторые типы узлов имеют также расширенное имя, состоящее из двух частей: локальной части и URI пространства имен. Локальная часть - это строка, URI пространства имен - строка или null. В качестве URI пространства имен, указываемого в XML документе, может выступать ссылка URI, описанная в [RFC2396]. Это означает, что он может иметь идентификатор фрагмента и быть относительным. В процессе обработки пространства имен относительный URI должен преобразовываться в абсолютный - URI пространства имен для расширенного имени узла в модели данных всегда должен стать абсолютным. Два расширенных имени считаются идентичными, если они имеют одинаковую локальную часть и либо оба имеют нулевой URI пространства имен, либо имеют одинаковые ненулевые URI пространства имен.
Для всех узлов в документе определяется порядок, называемый порядком появления в документе. Он соответствует появлению узлов в XML представлении документа после расшифровки всех общих сущностей - точнее выражаясь, не самих узлов, а первых символов из XML представления соответствующего узла. Следовательно, корневой узел всегда будет первым узлом, а узлы элементов будут предшествовать своим непосредственным потомкам. Таким образом, порядок появления в документе упорядочивает узлы элементов согласно очередности появления в XML документе соответствующих открывающих тэгов (после подстановки всех сущностей). Считается, что в элементе узлы атрибутов и пространств имен всегда предшествуют непосредственным потомкам элемента. При этом узлы пространств имен предшествуют узлам атрибутов. Относительный порядок следования узлов пространства имен и относительный порядок следования узлов атрибутов зависят от реализации. Обратный порядок появления в документе - это порядок, обратный порядку появления в документе.
Корневые узлы и узлы элементов имеют упорядоченный список узлов непосредственных потомков. Узлы не могут иметь совместных непосредственных потомков: если один узел отличается от другого, то ни один узел непосредственного потомка первого узла не может совпасть с каким-либо узлом непосредственного потомка другого узла. Каждый узел, за исключением корневого, имеет ровно одного родителя, который является либо узлом элемента, либо корневым узлом. Корневой узел и узел элемента являются родителями для каждого из своих непосредственных потомков. Потомки узла - это непосредственные потомки данного узла и все потомки непосредственных потомков этого узла.
Корневой узел является корнем дерева документа. Корневой узел не может появляться нигде кроме как в корне дерева. Узел, соответствующий элементу документа, является непосредственным потомком корневого узла. Корневой узел имеет непосредственными потомками также узлы инструкций обработки, узлы комментариев для инструкций обработки и узлы комментариев, которые либо предшествуют, либо следуют за элементом документа.
Строковое значение корневого узла является объединением строковых значений всех текстовых узлов, являющихся потомками корневого узла, выстроенными согласно порядку появления в документе.
Корневой узел не имеет расширенного имени.
Для каждого элемента в документе создается узел элемента. Узел элемента имеет расширенное имя, получаемое при обработке QName этого элемента, которое, согласно рекомендации XML Namespaces [XML Names], указывается в соответствующем теге. Если QName не имеет префикса и нет пространства имен, используемого по умолчанию, то URI пространства имен для расширенного имени данного элемента будет нулевым.
Замечание: Согласно нотации в Приложении A.3 документа [XML Names], локальная часть расширенного имени соответствует атрибутуtype
в элементеExpEType
. URI пространства имен для расширенного имени соответствует атрибутуns
в элементеExpEType
и становится нулевым, если такой атрибут не был представлен.
Непосредственными потомками узла элемента могут быть узлы элементов, узлы комментариев, узлы инструкций обработки и текстовые узлы, образующие его содержание. При этом обрабатываются ссылки на внутренние и внешние сущности. Выполняется подстановка для ссылок на символы.
Строковое значение узла элемента является объединением строковых значений всех текстовых узлов, являющихся потомками данного узла элемента и предварительно отсортированных согласно порядку появления в документе.
Узел элемента может иметь уникальный идентификатор (ID). Значение этого атрибута декларируется в DTD как тип ID
. Никакие два элемента в пределах одного документа не могут иметь одинаковые уникальные идентификаторы. Если XML процессор сообщает о существовании в документе двух элементов, имеющих один и тот же уникальный идентификатор (а такое возможно только если этот документ недействителен), то из двух данных элементов тот, который встретился в документе позже, будет обрабатываться как не имеющий уникального идентификатора.
Замечание: Если документ не имеет DTD, то ни один из его элементов не будет иметь уникального идентификатора.
С каждым узлом элемента связан набор узлов атрибутов. При этом, хотя сам элемент является родителем каждого из этих узлов атрибутов, узел атрибута непосредственным потомком своего родительского элемента не является.
Замечание: В этом заключается отличие от модели DOM, где элемент, владеющий атрибутом, родителем этого атрибута не считается (см. [DOM]).
Элементы не могут совместно использовать узлы атрибутов: Если один узел элемента отличается от другого, то ни один из узлов атрибутов, относящихся к первому узлу элемента, не может совпасть ни с одним узлом атрибута, относящимся ко второму узлу элемента.
Замечание: Оператор=
проверяет, имеют ли два узла одно и то же значение, однако не проверяет, являются ли они одним и тем же узлом. Таким образом, атрибуты двух различных элементов можно сравнивать с помощью оператора=
, даже несмотря на то, что они представлены различными узлами.
Атрибут, подставляемый по умолчанию, обрабатывается точно так же, как атрибут, указанный явно. Если для данного типа элемента в DTD атрибут был декларирован со значением по умолчанию #IMPLIED
, однако в элементе этот атрибут представлен не был, считается, что в наборе атрибутов указанного элемента нет узла для этого атрибута.
Некоторые атрибуты, такие как xml:lang
и xml:space
, имеют семантику, которая распространяется на все элементы, являющиеся потомками элемента с этим атрибутом (если затем семантика не была переопределена таким же атрибутом в другом элементе, являющемся его потомком). Однако это не накладывает ограничений на местоположение узлов атрибутов в дереве документа: любой элемент имеет узлы только тех атрибутов, которые либо были явно указаны в начальном тэге или тэге пустого элемента, относящихся в этому элементу, либо были явно декларированы в DTD со значением по умолчанию.
Узел атрибута имеет расширенное имя и строковое значение. Расширенное имя получается при обработке QName, указанного в соответствующем тэге XML документа согласно Рекомендации XML Namespaces [XML Names]. Если QName атрибута не имеет префикса, URI пространства имен для имени атрибута будет нулевым.
Замечание: Согласно нотации в Приложении A.3 документа [XML Names], локальная часть расширенного имени соответствует атрибутуname
элементаExpAName
, URI пространства имен расширенного имени соответствует атрибутуns
элементаExpAName
и будет нулевым, если атрибутns
в элементеExpAName
опущен.
Узел атрибута имеет строковое значение. Строковое значение нормализовано в соответствии с Рекомендацией XML [XML]. Не предусмотрено специальной обработки для атрибута, чье нормализованное значение становится строкой нулевой длины - результатом будет узел атрибута, чьим строковым значением становится строка нулевой длины.
Замечание: во внешнем DTD или внешней сущности параметра могут декларироваться атрибуты по умолчанию. Согласно рекомендации XML, если процессор XML не является проверяющим, он не обязан читать внешние DTD и внешние параметры. Соответственно, с некоторыми непроверяющими XML процессорами могут не работать стили и другой функционал, предполагающий, что дерево XPath содержит значения атрибутов по умолчанию, декларированные во внешнем DTD или сущности параметра.
Для атрибутов, декларирующих пространства имен, соответствующих узлов атрибутов не предусмотрено (см. [XML Names]).
С каждым элементом связан набор узлов пространства имен: по одному на каждый новый префикс пространства имен, появившийся в области видимости этого элемента, (включая и перфикс xml
, явным образом декларированный Рекомендацией XML Namespaces [XML Names]), и еще один узел для пространства имен по умолчанию, если таковое имеется в области видимости элемента. Данный элемент является родителем каждого такого узла пространства имен, однако узел пространства имен непосредственным потомком соответствующего элемента родителя не становится. Элементы не могут совместно использовать узлы пространства имен: если один узел элемента отличается от другого узла элемента, то ни один из узлов пространства имен, принадлежащих одному элементу, не может совпасть с узлом пространства имен, относящихся ко второму узлу элемента. Это означает, что элемент получит узел пространства имен:
для каждого атрибута элемента, чье имя начинается с xmlns:
,
для каждого атрибута в элементе-предке, чье имя начинается с xmlns:
, при условии что данный префикс не был затем переопределен самим элементом или его более близким предком,
для атрибута xmlns
, если сам элемент или какой-либо из его предков имеют атрибут xmlns
и при этом атрибут xmlns
самого ближайшего из таких элементов не является пустым
Замечание: Атрибут xmlns=""
отменяет декларацию пространства имен по умолчанию (см. [XML Names]).
Узел пространства имен имеет расширенное имя, локальная часть которого является префиксом пространства имен (она является пустой, если данный узел относится к пространству имен по умолчанию), а идентификатор URI пространства имен всегда нулевой.
Строковое значение узла пространства имен - это URI пространства имен, связанного с данным префиксом пространства имен. Если данный URI окажется относительным, он должен обрабатываться точно так же, как URI пространства имен в расширенном имени.
Для каждой инструкции обработки создается соответствующий узел. Исключение составляют инструкции обработки, помещенные в декларацию типа документа.
Инструкция обработки имеет расширенное имя, в котором локальная часть - это адресат инструкции обработки, а URI пространства имен является нулевым. Строковое значение узла инструкции обработки - это та часть инструкции обработки, которая следует за адресатом и возможным пробельным символом. В состав строкового значения также не попадает завершающая комбинация ?>
.
Замечание: Декларация XML инструкцией обработки не является. Соответственно, ни один из узлов инструкции обработки не может соответствовать декларации XML.
Для каждого комментария создается соответствующий узел. Исключение составляют комментарии, расположенные в декларации типа документа.
Строковым значением комментария является содержимое этого комментария за исключением открывающей <!--
и закрывающей -->
комбинаций.
Узлы комментария расширенного имени не имеют.
Символьные данные группируются в узлы текста. В каждый из таких узлов помещается столько символьных данных, сколько возможно: с текстовым узлом ни до, ни после не может соседствовать какой-либо другой текстовый узел, имеющий того же родителя. Строковым значением текстового узла являются эти самые текстовые данные. Текстовый узел всегда содержит по крайней мере один символ данных.
Все символы в секции CDATA обрабатываются как символьные данные. Таким образом, запись <![CDATA[<]]>
в исходном документе будет обрабатываться так же, как и <
. Оба варианта будут иметь результатом один символ <
в текстовом узле дерева документа. Таким образом, секция CDATA обрабатывается так, словно были удалены комбинации <![CDATA[
и ]]>
, а все символы <
и &
были заменены на <
и &
соответственно.
Замечание: Если текстовый узел, содержащий символ<
, записывается как XML, сам символ<
должен маскироваться, например, с помощью<
или помещением в секцию CDATA.
Символьные данные в комментариях, инструкциях обработки и значениях атрибутов текстовых узлов не образуют. Концы строк во внешних сущностях нормализуются в #xA в соответствии с Рекомендацией XML [XML].
Текстовый узел расширенного имени не имеет.
XPath изначально создавался как компонент для использования в других спецификациях. Поэтому XPath обращается к использующим его спецификациям (таким как [XPointer] или [XSLT]) за получением критериев проверки реализаций XPath, вместо того чтобы самому формулировать критерии оценки независимых реализаций XPath.
Узлы модели данных XPath могут быть получены из информационных элементов в XML Information Set [XML Infoset] следующим образом:
Замечание: Следующая версия рабочего проекта XML Information Set, которая сменит версию от 17 мая, была близка к завершению в то время, когда была завершена подготовка текущей версии XPath. Предполагалось, что она будет реализована одновременно или чуть позже данной версии XPath. Порядок отображения дается для этой новой версии рабочего проекта XML Information Set. А пока новая версия XML Information Set еще не реализована, члены W3C могут сверяться с внутренней версией соответствующей рабочей группы по адресу http://www.w3.org/XML/Group/1999/09/WD-xml-infoset-19990915.html (только для членов).
Корневой узел получается из информационного элемента document. Непосредственный потомок корневого узла получается из свойств children и children - comments.
Узел элемента получается из информационного элемента element. Непосредственный потомок узла элемента получается из свойств children и children - comments. Атрибуты узла элемента получаются из свойства attributes. Пространства имен для узла элемента получаются из свойства in-scope namespaces. Локальная часть для расширенного имени узла элемента получается из свойства local name. URI пространства имен для расширенного имени узла элемента получается из свойства namespace URI. Уникальный идентификатор узла элемента (ID) получается из свойства children информационного элемента атрибута в свойстве attributes, в котором имеется свойство attribute type, равное ID
.
Узел атрибута получается из информационного элемента attribute. Локальная часть расширенного имени узла атрибута получается из свойства local name. URI пространства имен для расширенного имени узла атрибута получается из свойства namespace URI. Строковое значение узла получается объединением свойств character code всех членов свойства children.
Текстовый узел формируется последовательностью из одного или нескольких следующих друг за другом информационных элементов character. Строковое значение узла получается объединением свойств character code всех информационных элементов character.
Узел инструкции обработки получается из информационного элемента processing instruction. Локальная часть расширенного имени этого узла происходит из свойства target. (URI пространства имен для расширенного имени этого узла является нулевым.) Строковое значение узла получается из свойства content. Для элементов processing instruction, являющихся непосредственными потомками информационного элемента document type declaration, узлы processing instruction не создаются.
Узел комментария получается из информационного элемента comment. Строковое значение узла происходит из свойства content. Для информационных элементов comment, являющихся непосредственными потомками информационного элемента document type declaration, узлы комментариев не создаются.
Узлы пространства имен создаются из информационных элементов namespace declaration. Локальная часть расширенного имени такого узла создается из свойства prefix. (URI пространства имен для расширенного имени такого узла является нулевым.) Строковое значение узла происходит из свойства namespace URI.
Если у вас возникли какие-либо замечания, мы будем рады их получить по адресу radik_u@mail.ru.