Кафедра «ОСУ» Весенний семестр 2010/2011 уч. года Языки описания информации Лекция 4. XPath Описание взаимосвязи между XMLдокументами • Языки разметки описывают информацию, одним из свойств которой является сильная связанность. • Содержание одного XML-документа может быть связано с содержанием большого количества других XML-документов. • При этом разные документы могут размещаться на разных узлах компьютерной сети. • Таким образом множество XML-документов может образовывать сложную сеть документов, описывающих информацию об окружающем мире. • Широко известным примером такой сети является World Wide Web (Web-сеть), которая содержит множество связанных между собой HTML-документов (web-страниц) расположенных на разных компьютерах Интернет сети. Языки взаимосвязи между документами • Для описания взаимосвязей между документами разработан набор языков, таких, как XPath, XPointer и XLink. • Эти языки используются совместно и каждый из них имеет свое назначение: – язык XPath предназначен для идентификации отдельных частей XML-документа, чтобы можно было на них ссылаться; – язык XPointer используется для описания ссылок из одного XML-документа на некоторую часть другого XMLдокумента, который расположен в локальной или глобальной компьютерной сети; для составления ссылок используются выражения на языке XPath; – язык XLink предназначен для встраивания в XMLдокументы ссылок на другие XML-документы (при этом используется язык XPointer). • Эти языки предоставляют возможность связывания XML-документов. • То, как эти связи (ссылки) реально используются, зависит от программ, обрабатывающих эти XML-документы (XMLпроцессоров). Язык XPath (XML Path Language) Язык XPath • Язык XML Path Language (XPath) предназначен для описания указателей (или поисковых запросов) на части XML-документов. • Он использует синтаксис, отличный от синтаксиса языка XML. • С его помощью можно записывать выражения, ссылающиеся на некоторый конкретный элемент или на группу элементов XML-документа. • XPath позволяет задавать части документа (элементы, атрибуты, комментарии и т.п.) по их абсолютному или относительному положению в документе, а также на основе их типа, их содержимого или других критериев. • В настоящее время есть две стандартизированные организацией W3C версии языка XPath: 1.0 и 2.0. XPath Versions • • • • XPath 1.0 became a W3C Recommendation November 16, 1999. XPath 2.0 became a W3C Recommendation January 23, 2007. XPath 2.0 is a language derived from XPath 1.0 and XQuery. The XPath 2.0 and XQuery 1.0 are generated from a common source, sharing much of the same syntax, and much of the text is identical. • W3C XSL Specifications and Timeline Specification Draft / Proposal XPath 1.0 XPath 2.0 Requirements Recommendation 16. Nov 1999 03. Jun 2005 XPath 2.0 Language 23. Jan 2007 XPath 2.0 Functions 23. Jan 2007 XPath 2.0 Data Model 23. Jan 2007 XPath 2.0 Semantics 23. Jan 2007 XPointer 16. Aug 2002 Использование языка XPath • Описания частей XML-документов с помощью языка XPath могут использоваться с разными целями: – в языке XPointer для задании адресов, которые указывают на определенную точку или часть XMLдокумента, которые используются в ссылках языка XLink; – на языке XSLT для отбора (в качестве шаблона правил) определенных элементов входного документа для их обработки или копирования в выходной документ; – на языках XSLT и XQuery запросов для выборки требуемых данных из XML-документов. Иерархическая структура XML- документа • Языка XPath рассматривает XML-документ, как иерархическую структуру (дерево), состоящую из узлов, следующих семи типов: 1. узел документа – включает весь XML-документ, помимо корневого элемента также и комментарии, записанные вне его; 2. узлы элементов – включают элементы документа (начиная с открывающего тэга и заканчивая закрывающим тэгом); 3. узлы атрибутов – пара «имя_атрибута=значение_атрибута»; 4. текстовые узлы – текстовое содержание элементов и атрибутов; 5. узлы пространств имен; 6. узлы инструкций обработки; 7. узлы комментариев. Пример XML документа <?xml version="1.0"?> <?xml-stylesheet type="text/xsl" href="people.xsl"?> <!DOCTYPE people [ <!ATTLIST homepage xlink:type CDATA #FIXED "simple” xmlns:xlink CDATA #FIXED "http://www.w3.org/1999/xlink"> <!ATTLIST person id ID #IMPLIED> ]> <people> <person born="1912" died="1954" id="p342"> <name> <first_name>Алан</first_name> <last_name>Тьюринг</last_name> </name> <!-- Существовало ли понятие «специалист по информатике» во времена Тьюринга? --> <profession>специалист по информатике</profession> <profession>математик</profession> <profession>криптограф</profession> <homepage xlink:href="http://www.turing.org.uk/"/> </person> <person born="1918" died="1988" id="p4567"> <name> <first_name>Ричард</first_name> <middle_initial>&#x4D;</middle_initial> <last_name>Фейнман</last_name> </name> <profession>физик</profession> <hobby>Игра на бонгах</hobby> </person> </people> Древовидная структура XML документа • В этом списке нет таких конструкций, как – секции CDATA, – ссылки на сущности и – объявления типа документа. • XPath работает с XML-документом уже после того, как эти конструкции уже объединены с документом. • Некоторые узлы могут содержать другие узлы. • Узел документа, в конечном счете, включает в себя все остальные узлы. • Язык XPath позволяет идентифицировать (выбирать) узлы и наборы узлов этого иерархического дерева документа. Особенности модели данных XPath 1. Корневой узел не совпадает с корневым элементом. – Корневой узел дерева содержит в себе весь документ, в том числе • • • корневой элемент, комментарии инструкции обработки (перед начальным тегом корневого элемента или после конечного тега корневого элемента). 2. Модель данных XPath включает не все, что есть в документе. – Например: XML-объявление и DTD не доступны через XPath. 3. Если DTD предоставляет значения по умолчанию для каких-либо атрибутов, XPath распознает эти атрибуты. Взаимосвязи между узлами • Parent (родитель) – узел «родителя» содержит под-узлы «ребенка». • Children (ребенок) • Siblings (братья) – под-узлы имеющие одного «родителя». • Descendants (потомки) – все под-узлы ниже по иерархии текущего узла. • Ancestors (предки) – все под-узлы выше по иерархии текущего узла. Parent (родитель) • Каждый элемент и атрибут имеет одного «родителя» • Например: <book> <title>Harry Potter</title> <author>J K. Rowling</author> <year>2005</year> <price>29.99</price> </book> • Элемент “book” является родителем узлов: title, author, year и price. Children (ребенок) • Элемент может не иметь, либо иметь одного или несколько «детей» (children). • Например: <book> <title>Harry Potter</title> <author>J K. Rowling</author> <year>2005</year> <price>29.99</price> </book> • Элементы title, author, year и price являются «детьми» (children) элемента book. Siblings (братья) • Узлы, которые имеют одного и того же «родителя» (parent). • Например: <bookstore> <book> <title>Harry Potter</title> <author>J K. Rowling</author> <year>2005</year> <price>29.99</price> </book> </bookstore> • Все элементы title, author, year и price являются «братьями» (siblings). Ancestors (предки) • Узлы «родители», их «родители» и т.д. • Например: <bookstore> <book> <title>Harry Potter</title> <author>J K. Rowling</author> <year>2005</year> <price>29.99</price> </book> </bookstore> • предками элемента title являются элементы book bookstore. Descendants (потомки) • Узлы «ребенок», их «дети» и т.п. • Например: <bookstore> <book> <title>Harry Potter</title> <author>J K. Rowling</author> <year>2005</year> <price>29.99</price> </book> </bookstore> • потомками элемента bookstore являются элементы: book, title, author, year и price. Пути доступа • На языке XPath можно записывать разные виды выражений. • Наиболее часто используемым выражением языка XPath является путь доступа (маршрутом поиска или path-выражением). • Путь доступа задает шаблон для отбора узлов XMLдокумента. • Выбираемая с помощью пути доступа последовательность узлов может быть пустой, содержать один узел или множество узлов. • Можно отметить, что пути доступа во многом сходны с путями к файлам, которые используются в файловых системах для указания местонахождения файла или папки. Контекст • Важным понятием при рассмотрении путей доступа является контекст. • Контекст – это некая точка отсчета, относительно которой записывается путь доступа. • Контекст может включать набор узлов, а также узел, который называется текущим узлом. • Изменение контекста, а также текущего узла, выполняется программой, которая обрабатывает XML-документ (например, XSLTпроцессор, программа пользователя). Виды путей доступа • В языке XPath имеются два вида путей доступа: – абсолютный путь – он начинается от корневого узла дерева документа (запись такого пути начинается со знака «слэш» - ‘/’); – относительный путь – он начинается с текущего (контекстного) узла дерева документа. • Каждый путь записывается в виде набора шагов, разделенных слэшем (/). • Каждый шаг это правило выбора узлов из результата (последовательности) полученной на предыдущем шаге. – Например запрос ‘books/book/name’, проходит по иерархии документа вплоть до элемента <name>. – Результатом является последовательность элементов типа name. Структура пути доступа • В полной форме, каждый шаг пути состоит из трех частей: axis::nodetest[predicate] • где – axis – ось – направление перемещения по иерархической структуре; – nodetest – критерий выбора узлов; – predicate – предикат –дальнейшее уточнение списка узлов-кандидатов. Оси (axis) • Ось, определяет направление перемещения по иерархической структуре между узлом контекста и узлами, которые будут проверяться на данном шаге доступа. • Ось задает общее направление, в котором выполняется шаг доступа по отношению к узлу контекста. • Если ось не задана (при краткой записи пути доступа), то по умолчанию предполагается, что перемещение выполняется по оси дочерних элементов «child::». Критерий узлов • nodetest – критерий узлов, определяет – тип узлов, – либо развернутое имя узлов (шаблон), которые будут выбираться на данном шаге доступа. • В первую очередь проверка узла определяет, какие из всех узлов на указанной оси являются кандидатами, – потенциально подходящими узлами для шага доступа. Предикат • predicate – предикат, задает условие (фильтр), которое должно выполняться для дальнейшего уточнения списка узловкандидатов. • Если для рассматриваемого кандидата условие заданное предикатом выполняется то он отбирается в текущий контекст. • Если предикат не задается, то квадратные скобки ([ ]) не пишутся. Анализ пути доступа • Анализ пути доступа выполняется слева направо. • Если в пути доступа первым символом является слэш (/), то путь адресации считается абсолютным, то есть начинается с узла документа. – В этом случае за узел контекста на первом шаге берется узел документа. • Контекст – это некая точка отсчета, относительно которой рассчитывается следующий шаг адресации. • Поэтому на каждом шаге адресации получается новая последовательность узлов обрабатываемого документа, которая становится контекстом для следующего шага адресации. Пояснение • Для лучшего понимания концепции контекста нужно представить дерево, содержащее узлы. • Запрос всех узлов X из корня дерева возвратит один набор результатов, в то время, как запрос таких же узлов из ветви дерева возвратит другой набор результатов. • Результат выражения зависит от контекста, к которому оно обращается при выполнении. Список допустимых осей № Ось 1 ancestor:: 2 ancestor-orself:: Описание элементов, включаемых в оси Содержат все родительские узлы вплоть до корня дерева. Содержат все родительские узлы вплоть до корня дерева включая текущий узел. 3 attribute:: Содержит только атрибуты (текущий узел должен быть элементом). 4 child:: Содержит все прямые дочерние узлы без атрибутов и пространств имен. 5 descendant:: Содержит все дочерние узлы со всеми вложенными узлами без атрибутов и пространств имен (все потомки) descendantor-self:: Содержит все дочерние узлы включая текущий узел со всеми вложенными узлами без атрибутов и пространств имен. 6 7 following:: Содержит все узлы, следующие за текущим в порядке просмотра дерева. Не содержит дочерних узлов текущего, пространств имен и атрибутов. Список допустимых осей (2) № Ось Описание элементов, включаемых в оси following8 sibling:: Содержит все узлы, следующие за текущим в порядке просмотра дерева (но на том же уровне вложения от корня). Не содержит дочерних узлов текущего, пространств имен и атрибутов. 9 namespace:: Содержит узлы пространств имен документа. 10 parent:: Содержит один родительский узел. 11 preceding:: Содержит все узлы, предшествующие текущиму в порядке просмотра дерева. Не содержит дочерних узлов текущего, пространств имен и атрибутов. preceding12 sibling:: Содержит все узлы, предшествуюшие текущиму в порядке просмотра дерева (но на том же уровне вложения от корня). Не содержит дочерних узлов текущего, пространств имен и атрибутов. 13 self:: Содержит только текущий узел. Краткая форма записи путей доступа • В краткой форме записи путей доступа оси не указываются. • В основном используется оператор «дочерний элемент», который выбирает непосредственные дочерние элементы последовательности, указанной слева. (т.е. используется ось child::). • Например: – путь доступа author/first-name выделяет все элементы <first-name> внутри элемента <author> текущего узла контекста. • Таким образом краткая форма записи путей доступа позволяет перемещаться по следующим осям: – оси дочерних узлов (child), – оси родительских узлов (parent), – собственной оси (self), – оси атрибутов (attribute) и – оси потомков с включением контекстного узла (descendant-or-self). Операторы, используемые для описания путей доступа Оператор Пояснение / Оператор «дочерний элемент»: выбирает непосредственные дочерние элементы последовательности, указанной слева. Если этот оператор пути стоит в начале шаблона, будут выбраны дочерние элементы корневого узла (ось child::). // Рекурсивный спуск; поиск заданного элемента на любой глубине. Если этот оператор пути стоит в начале шаблона, рекурсивный спуск будет вестись из корневого узла. (ось descendant::) () Оператор группировки операций для явного задания порядка их выполнения. [] Предикат шага доступа. [] Оператор индексирования элементов последовательности. Операторы, используемые для описания выражений языка XPath Оператор Пояснение + Операция сложения. - Операция вычитания. div * mod Операция деления с плавающей запятой. Операция умножения. Операция возврата остатка от целочисленного деления. Данная таблица не включает логические операторы и операторы над множествами, которые будут рассмотрены далее. Приоритеты операций путей доступа Приоритет Символ Назначение 1 () Группирование 2 [] Предикаты 3 / и // Операции с путями Специальные символы записи пути доступа Оператор Пояснение . Указание на текущий контекст (ось self::node()). .. Родитель узла текущего контекста (ось parent::). * Символ подстановки; выбирает все элементы независимо от их имени. @ Атрибут; префикс имени атрибута (ось attribute::). @* Символ подстановки для атрибута; выбирает все атрибуты независимо от имени. Текущий контекст • Выражение с префиксом в виде точки и косой черты (./) явным образом указывает на использование текущего контекста. • Например, выражение ‘./author’ ссылается на все элементы <author> внутри текущего контекста. • Однако, следует запомнить, что это выражение эквивалентно следующей краткой записи пути доступа: author. Корневой элемент • Выражение, использующее косую черту и звездочку (/*), использует в качестве контекста корневой элемент. • Например, выражение ‘/*’ находит корневой элемент документа. Рекурсивный спуск • Выражение, использующее двойную косую черту (//), указывает на поиск, по всем нижележащим уровням иерархии. • Если двойная косая черта (//) в начале задается, то поиск выполняется с корневого элемента (он является контекстом поиска). • Например, путь ‘//author’ ссылается на все элементы <author> внутри в любом месте внутри текущего документа. Конкретные элементы • Выражение, которое начинается с имени элемента, ссылается на запрос конкретного элемента, который начинается от текущего узла контекста. • Например, путь доступа ‘bookstore/book’ ссылается на последовательность элементов <book> внутри элементов <bookstore> в текущего узле контекста. Использование операторов пути • С помощью операторов пути (/ и //) описываются последовательности элементов требуемого типа. – принимают в качестве аргументов последовательность «с левой стороны», из которой производится выбор, – и критерий узлов «с правой стороны» как инструкцию, указывающую, какие элементы нужно выбирать. • Оператор «дочерний элемент» (/) производит выбор из непосредственных дочерних элементов левой последовательности, • Оператор «потомок» (//) производит выбор из всех потомков последовательности с левой стороны. • Оператор // можно рассматривать как подстановку для одного или нескольких уровней иерархии. • Операторы пути изменяют контекст по мере выполнения запроса. • Последовательно соединяя несколько операторов пути, пользователи могут выполнять обход всего дерева документа. Примеры использования операторов путей доступа Выражение Результат author/first-name Все элементы <first-name> внутри элемента <author> текущего узла контекста. bookstore//title Все элементы <title> на первом или более глубоких уровнях элемента <bookstore>(наследники произвольного уровня). Следует отметить отличие от следующего шаблона: bookstore/*/title (описан ниже). bookstore/*/title Все элементы <title>, являющие дочерними у дочерних элементов <bookstore> (т.е. внуков). bookstore//book/exc Все элементы <emph> в любом месте внутри элементов erpt//emph <excerpt>, дочерних по отношению к элементам <book>, находящимся в любом месте внутри элемента <bookstore>. .//title Все элементы <title> на первом или более глубоких уровнях текущего контекста. Следует учесть, что только в этой ситуации требуется нотация с использованием точек. Предикаты • Каждый шаг в пути доступа может иметь предикат, который делает выбор из текущего на данном шаге выражения списка узлов. • Предикат содержит логическое выражение, которое проверяется для каждого узла в контекстном списке узлов. • Если выражение истинно, то этот узел включается в последовательность, в противном случае – не включается. Пример XML документа <?xml version="1.0"?> <?xml-stylesheet type="text/xsl" href="people.xsl"?> <!DOCTYPE people [ <!ATTLIST homepage xlink:type CDATA #FIXED "simple” xmlns:xlink CDATA #FIXED "http://www.w3.org/1999/xlink"> <!ATTLIST person id ID #IMPLIED> ]> <people> <person born="1912" died="1954" id="p342"> <name> <first_name>Алан</first_name> <last_name>Тьюринг</last_name> </name> <!-- Существовало ли понятие «специалист по информатике» во времена Тьюринга? --> <profession>специалист по информатике</profession> <profession>математик</profession> <profession>криптограф</profession> <homepage xlink:href="http://www.turing.org.uk/"/> </person> <person born="1918" died="1988" id="p4567"> <name> <first_name>Ричард</first_name> <middle_initial>&#x4D;</middle_initial> <last_name>Фейнман</last_name> </name> <profession>физик</profession> <hobby>Игра на бонгах</hobby> </person> </people> Примеры использования предикатов • Если требуется найти все элементы profession, которые имеют значение «физик», то можно использовать следующее выражение //profession[.="физик"]. – Здесь точка обозначает строковое значение текущего узла. • Выражение //person [profession="физик"] позволяет выбирать все элементы person, имеющих дочерний элемент profession со значением «физик». • Для выбора элементов person с id, равным p4567, то нужно поместите перед именем атрибута символ @, как, например, в выражении //person[@id="p4567"]. • Выражение //name[middle_initial] будет выбирать все элементы name, а затем будет проверяет каждый из них на наличие дочернего элемента middle_initial. • Сохраняются только те элементы, в которых есть такой дочерний элемент. • В языке XPath кроме знака равенства поддерживает полный набор операторов сравнения, в том числе <, >, >=, <= и !=. – Например, выражение //person[@born<=1976] ищет в документе все элементы person с атрибутом born, числовое значение которого меньше или равно 1976. • Следует помнить, что если < или <= используются внутри XML-документа, необходимо заменять знак «меньше» на &lt; – например "//person[@born &lt;= 1976]". Логические операторы • В языке XPath также имеются логические операторы and и or для логического объединения выражений. – Например, выражение XPath //person[@born<=1920 and @born>=1910] выбирает все элементы person, значения атрибутов born которых находятся между 1910 и 1920 включительно. – Выражение //name[first_name="Ричард" or first_name="Дик"] выбирает все элементы name, имеющие дочерние элементы first_name со значением Ричард или Дик. Примеры использования предикатов в путях доступа Выражение Результат book[excerpt] Все элементы <book>, которые содержат хотя бы один дочерний элемент <excerpt>. book[excerpt]/title Все элементы <title>, дочерние по отношению к элементам <book> и содержащие хотя бы один дочерний элемент <excerpt>. book[excerpt]/author Все элементы <author>, содержащие, по крайней мере, один дочерний элемент <degree> и являющиеся дочерними для [degree] элементов <book>, содержащих, по крайней мере, один элемент <excerpt>. book[author/degree] Все элементы <book>, имеющие дочерние элементы <author>, у которых, в свою очередь, есть хотя бы один дочерний элемент <degree>. author[degree][awar Все элементы <author>, которые содержат хотя бы один элемент <degree> и хотя бы один элемент <award>. d] Примеры использования предикатов в путях доступа (2) Выражение author[(degree or award) and publication] Результат Все элементы <author>, которые содержат хотя бы один дочерний элемент <degree> или <award> и хотя бы один дочерний элемент <publication>. author[degree and Все элементы <author>, содержащие по крайней мере not(publication)] один дочерний элемент <degree> и не содержащие дочерних элементов <publication>. author[not(degree or award) and publication] Все элементы <author>, содержащие по крайней мере один дочерний элемент <publication> и не содержащие ни элементов <degree>, ни элементов <award>. author[last_name = Все элементы <author>, которые содержат хотя бы один "Bob"] дочерний элемент <last_name> со значением Bob. Символ подстановки • Элементы или атрибуты могут использоваться, без указания их имени, с помощью символа подстановки (*). • Данный символ обозначает все элементы, являющиеся дочерними для текущего контекста, независимо от имени тега. Примеры использования символа подстановки в путях доступа Выражение author/* Результат Все дочерние элементы элементов <author>. book/*/last_name Все элементы <last_name>, являющиеся «внуками» элементов <book> (т.е. находятся через один уровень иерархии ниже данных элементов). */* Все элементы – "внуки" текущего контекста. myns:book Элемент <book> из пространства имен myns. myns:* Все элементы из пространства имен myns. Работа с атрибутами • В XPath имена атрибутов задаются с помощью символом @, за которым следует имя нужного атрибута. • Атрибуты и дочерние элементы обрабатываются одинаково, и эти два типа считаются эквивалентными везде, где это возможно. • Например, выражение XPath @born выбирает атрибут born контекстного узла. • К атрибутам нельзя применять индексы, поскольку их порядок по определению считается не заданным. Примеры использования атрибутов Выражение Результат @style Атрибут style текущего контекста. *[@specialty] Все элементы с атрибутом specialty. price/@exchange Атрибут exchange элементов <price> в текущем контексте. price/@exchange/t Возвращает пустой набор узлов, потому что атрибуты не otal содержат дочерних элементов. Такое выражение не запрещено синтаксисом языка XPath, но, строго говоря, не является допустимым. book[@style] Все элементы <book> с атрибутами style в текущем контексте. book/@style Атрибут style для всех элементов <book> в текущем контексте. @* Все атрибуты контекста текущего элемента. Работа с комментариями и текстовым содержанием • Так как узлы комментариев и текстовые узлы не имеют имен, то для их задания в пути доступа используются следующие функции – comment() соответствует узлам комментарий, являющиеся непосредственным дочерним узлом контекстного узла; – text() соответствуют узлам текста, являющиеся непосредственным дочерним узлом контекстного узла. • Каждый комментарий является отдельным узлом комментария. • Каждый текстовый узел содержит максимально возможный непрерывный отрезок текста, не прерванный тегом. Работа инструкциями обработки • Функция processing-instruction() без аргументов выбирает все дочерние инструкции обработки контекстного узла. • Если аргумент указан, она выбирает только дочерние инструкции обработки, имеющие данную цель. • Например, выражение processinginstruction('xml-styles-heet') выбирает все дочерние инструкции обработки контекстного узла, целью которых является xml-stylesheet. Последовательности языка XPath • Пути доступа возвращают последовательности, в которых сохраняется порядок следования элементов (а также атрибуты и значения) заданных в обрабатываемом документе. Индексирование в последовательности • Выражения XPath позволяют легко получать конкретный узел в последовательности. • Для этого нужно задать порядковый номер индекса в квадратных скобках (т.е. индексы относятся к фильтру). • Первый элемент последовательности имеет номер 1 (хотя некоторые процессоры используют 0 для указания на первый элемент последовательности). • Как пояснялось ранее, операция [ ] имеют более высокий приоритет, чем операции / и //. • Атрибуты по определению являются неупорядоченными, поэтому для них нельзя использовать индексы. Примеры выбора элементов последовательности Выражение Результат author[1] Первый элемент <author> в текущем узле контекста. author[first_name][3] Третий элемент <author>, имеющий дочерний элемент <first_name>. author[last_name[1] = "Bob"] Все элементы <author>, первый дочерний элемент <last_name>, которых имеет значение Bob. Заметьте, что это эквивалентно выражению в следующей строке. author[last_name [position()=1]= "Bob"] Все элементы <author>, первый дочерний элемент <last_name> которых имеет значение Bob. Примеры выбора элементов последовательности Выражение Результат p/text()[2] Второй текстовый узел в каждом элементе <p> узла контекста. ancestor::book[1] Ближайший элемент <book>, предком узла контекста. который является ancestor::book[author][1] Ближайший элемент <book>, который является предком узла контекста и содержит дочерний элемент <author>. ancestor::author[parent:: Ближайший элемент <author>, который является book][1] предком в текущем контексте и является дочерним элементом для элемента <book>. Примеры выбора элементов последовательности • Фрагмент XML-документа: <x> <y/><y/> </x> <x> <y/><y/> </x> Выражение x/y[1] Результат Первый элемент <y> внутри каждого элемента <x>. x/y[position() = Первый дочерний элемент <y> каждого элемента <x>. 1] (x/y)[1] Первый элемент <y> из всего набора элементов <y> внутри элементов <x>. x[1]/y[2] Второй элемент <y> внутри первого элемента <x>. • Приведенные в табл. примеры являются краткими записями путей доступа, в которых используется неявно ось “child::”. – Например, путь доступа: “x/y[1]” эквивалентен пути “x/child::y[1]”. – Оба выражения означают «для каждого элемента <x> выбирать первый дочерний элемент с именем <y>. • Для этой оси последовательность дочерних элементов индексируется в прямом порядке документа. • Для других осей, например “ancestor::”, в полном пути доступа следует явно указать имя оси. • Для данной оси последовательность предков индексируется в обратном порядке документа. – Например, путь доступа “x/ancestor::y[1]” – выбирает для каждого элемента <x> первого его предка (в обратном порядке документа) с именем <y>. – Синтаксис такой же, но порядок обратный. Поиск последнего элемента в последовательности • Функция last() возвращает значение true для последнего элемента в последовательности. • Следует обратить внимание, что функция last() относится к родительскому узлу. • Примеры выбора последнего элемента последовательности приведены в табл. Выражение Результат book[last()] Последний элемент <book>. book/author[last()] Последний дочерний элемент <author> внутри каждого элемента <book> в текущем узле контекста. (book/author)[last()] Последний элемент <author> из всего набора элементов <author> дочерних по отношению к элементам <book> в текущем узле контекста. Группирование • С помощью круглых скобок операторы пути доступа можно группировать для уточнения, либо в случае, если для выражения операции не подходит обычный приоритет. • Операторы группировки можно использовать в любых выражениях предикатов. – Например: author[(degree or award) and publication]. • Их также можно использовать в выражениях шага более высокого уровня. – Например: (book|magazine) или (author/degree | book/award). • Их нельзя применять к выражениям шага более низкого уровня. – Например, выражение author/(degree | award) недопустимо. Примеры группировки операторов пути доступа Выражение Результат (book/author) Все элементы <author>, которые являются дочерними элементами любого элемента <book> из текущего узла контекста. author[(degree or award) and publication] Все элементы <author>, которые содержат хотя бы один элемент <degree> или <award> и хотя бы один элемент <publication>. Сравнение сокращенных и полных маршрутов поиска • В сокращенном маршруте поиска ось и критерий узла объединены вместе. • В полном маршруте они разделяются двумя двоеточиями “::”. – Например, сокращенный маршрут поиска “people/person/@id” состоит из трех шагов. • Первый шаг выбирает узлы элементов people по оси дочерних узлов, • Второй шаг – выбираются узлы элементов «person» по оси дочерних узлов, • Третий шаг – выбираются узлы атрибутов id по оси атрибутов. – Если переписать это выражение в полной форме, тот же маршрут поиска будет выглядеть следующим образом: “child::people/child::person/attribute::id”. Сравнение сокращенных и полных маршрутов поиска (2) • Полные маршруты поиска, как и сокращенные, могут быть абсолютными, если начинаются с корневого узла. – Например, полная форма “/child::people/child::person” – эквивалентна сокращенной форме “/people/person”. Сравнение сокращенных и полных маршрутов поиска (3) • Полные маршруты поиска также могут иметь предикаты. – Например, сокращенный маршрут “/people/person[@born < 1950]/name[first_name="Алан"]” – в полной форме превратится в “/child::people/child::person[@born<1950]/child::name[ first_name="Алан"]” Сравнение сокращенных и полных маршрутов поиска (4) • В общем случае, полная форма очень многословна и не часто используется на практике. • Она не допускается в масках атрибута match в XSLT. • Достоинство полных маршрутов: они является единственным способом обращения к большинству осей, по которым выражения XPath позволяют выбирать узлы. Другие выражения языка XPath • Кроме путей доступа на языке XPath могут быть записаны выражения, которые выполняют вычисления и возвращают результат некоторого типа. • Например: – – – – – – 3,141529; 2+2; 'Tim Berners-Lee'; true(); 32,5<76,2E-21; position()=last(). • Выражения такого вида могут включаться в предикаты путей доступа или использоваться самостоятельно. • Языке XPath предоставляет возможности для работы с – числовыми данными, – строками и – логическими значениями. Операции для работы с числовыми данными • Для работы с числовыми данными в общих выражений в языке XPath могут использоваться пять обычных арифметических операций: – “+” – сложение; – “–” – вычитание; – “*” – умножение; – “div” – деление; – “mod” – получение остатка. Строковые данные • Язык XPath также предоставляет возможности для работы со строками , которые могут заключаться либо в одинарные (‘), либо в двойные (“) кавычки, как вам удобно. • Сами кавычки не являются частью строки. • Единственное ограничение, которое XPath накладывает на строковый литерал, это то, что он не может содержать тот тип кавычек, который служит в качестве его ограничителя. • Если в строке встречаются одинарные кавычки, она должна быть заключена в двойные, и наоборот. • Проверку строк на равенство можно осуществлять с помощью операторов сравнения = и !=. • Операторы отношения <, >, <= и >= также можно использовать для сравнения строк, однако, если обе строки явно не представляют собой числа (например, –7,5 или 54,2), результат обычно не имеет смысла. Логические значения • Логические значения, которые могут быть равными только true (истина) или false (ложь), обычно создаются в результате сравнения других объектов. • В языке XPath имеются операторы – сравнения (=, !=, <, >, >= и <=), – логические операторы (and и or). • Логические значения часто используются в предикатах путей доступа. – Например, в пути доступа //person[profession="физик"] логическим выражением является profession="физик". Функции XPath • В предикатах путей доступа и в других выражениях языка XPath можно использовать встроенные функции. • Функции можно узнать по скобкам после имени функции. • При вызове функций им могут передаваться аргументы. • В языках XPath 2.0, XQuery 1.0 и XSLT 2.0 используется одинаковый набор функции. • Список основных встроенных функций приведен в приложении 1 пособия. Группировка функций • Все функции языка делятся на следующие основные группы: 1. 2. 3. 4. функции для наборов узлов; числовые функции; строковые функции; булевые функции. • Любая функция XPath возвращает значение, относящееся к одному из четырех типов: – – – – набор (последовательность) узлов; числовое значение; строка; логическое значение. • Эти типы часто используются в качестве аргументов функции независимо от того, какой тип данных требуется, и процессор (обрабатывающая программа) по возможности выполняет преобразование данных. • Если передать булевое значение там, где требуется строка, процессор заменит его одной из строк, true или false. • Единственным исключением являются функции, которым требуются наборы узлов. • Язык XPath не позволяет преобразовывать строки, булевые или числовые значения в наборы узлов. Примеры функций для наборов узлов • Функции для наборов узлов либо используют, либо возвращают информацию о наборах узлов – упорядоченных последовательностей узлов. • К таким функциям относятся: – функция position() – возвращает номер текущего узла в обрабатываемой последовательности; – функция last() возвращает количество узлов в контекстном наборе, которое совпадает с позицией последнего узла набора; – функция count(), которая возвращает количество узлов своего аргумента, а не контекстного списка. • Например, count(//name) подсчитывает, сколько элементов name присутствует в документе; • функция id() принимает в качестве аргумента строку, состоящую из одного или более ID, разделенных пробельными символами, и возвращает набор узлов, который содержит все узлы документа, имеющие указанные ID. – Это узлы, атрибуты которых объявлены в DTD как принадлежащие к типу ID, но они не обязательно имеют имя ID или id. • Функция id() чаще всего используется в сокращенном синтаксисе XPath. Она позволяет формировать абсолютные маршруты поиска, начинающиеся не от корня. • Например, id('p342')/name ссылается на элемент name независимо от его расположения в документе; • функция local-name() принимает в качестве аргумента набор узлов, чаще всего содержащий только один узел, и возвращает локальное имя первого узла набора. – Если аргумент не задается, то в этом случае рассматривается контекстный узел; • функция namespace-uri() принимает в качестве аргумента набор узлов и возвращает URI пространства имен для первого узла набора; • функция name() принимает в качестве аргумента набор узлов и возвращает полное имя первого узла набора. Примеры строковых функций • XPath включает функции для основных операций со строками, таких как определение длины строки или замена регистра символов. • Функция string() преобразует аргумент любого типа в строку. – Логические значения преобразуются в строку true или false. – Наборы узлов преобразуются в строковое значение первого узла набора. – Это значение аналогично значению вычисляемому элементами языка XSLT xsl:value-of. Примеры строковых функций (2) • Строковое значение элемента – это полный текст элемента после разрешения всех ссылок на сущности и отбрасывания тегов, комментариев и инструкций обработки. • Числа преобразуются в строки в формате, понятном большинству языков программирования, например «1987», «299792500», «2.71828» или «2.998E+10». • функция starts-with() требует двух строковых аргументов. Возвращает true, если строка первого аргумента начинается со строки второго аргумента. • Например, starts-with('Ричард', 'Рич') возвращает true, starts-with('Ричард', 'Рик') – false. • функция contains() также принимает два строковых аргумента. – Возвращает true, если строка первого аргумента содержит строку второго, т. е. если второй аргумент является подстрокой первого аргумента, независимо от позиции. • Например, contains('Ричард', 'ар') возвращает true, contains('Ричард', 'арт') – false. • функция substring-before() принимает два строковых аргумента и возвращает подстроку первого аргумента, предшествующую первому вхождению строки второго аргумента. – Если вторая строка отсутствует в первой, substring-before() возвращает пустую строку. • Например, sub-string-before('MM/DD/YYYY','/') равно 'MM'. • функция substring-after() также принимает два строковых аргумента, но возвращает подстроку первого аргумента, следующую за первым вхождением второго аргумента. – Если вторая строка отсутствует в первой, substringafter() возвращает пустую строку. • Например, substring-after('MM/DD/YYYY','/') возвращает 'DD/YYYY', substring-before(substring-after('MM/DD/YYYY','/'),'/') возвращает DD, substring-after(substring-after('MM/DD/YYYY','/'),'/') – YYYY. • функцией substring() принимает три аргумента: – строку, из которой копируется подстрока, – позицию в строке, от которой начинается извлечение, – количество символов, копируемых из подстроки. (может быть опущен, в этом случае подстрока содержит все символы, начиная с указанной стартовой позиции и заканчивая концом строки). – Например, substring('MM/DD/YYYY', 1, 2) возвращает MM; substring('MM/DD/YYYY', 4, 2) возвращает DD; а substring('MM/DD/YYYY', 7) возвращает YYYY. • функция string-length() возвращает число, равное длине строкового значения ее аргумента или контекстного узла, если аргумент не указывается. Примеры булевых функции • Булевые функции возвращают логическое значение истина или ложь: • функция true() всегда возвращает истину; используется вместо логического литерала true; • функция false() всегда возвращает ложь; используется вместо логического литерала false; • функция not() преобразует из true в false и наоборот; Примеры булевых функции (2) • функция boolean() преобразует свой единственный аргумент в логическое значение и возвращает результат преобразования. – Если аргумент опущен, преобразуется контекстный узел. – Числа преобразуются в ложь, если они равны нулю; все остальные числа являются истиной. – Наборы узлов ложны, если они пусты, и истинны, если содержат хотя бы один узел. – Строки ложны, если имеют нулевую длину, и истинны – в противном случае. – В соответствии с этим правилом строка “false” является истинной. Примеры числовых функций • Числовые функции позволяют выполнять действия с числами, как это делается в универсальных языках программирования. • Примерами числовых функций являются: • Функция number() принимает аргумент любого типа и преобразует его в число. – Если аргумент отсутствует, преобразуется контекстный узел. – Логические значения преобразуются в 1, если истинны, и в 0, если ложны. – Строки преобразуются по возможности наиболее правдоподобным образом. • Например, строка «7.5» преобразуется в число 7.5, а строка «8.5E2» – в число 8500. • Строка «Fred» преобразуется в NaN. – Наборы узлов сначала преобразуются в строку, а затем эта строка результата преобразуется в число. – Если преобразуемый объект невозможно интерпретировать как число, функция number() возвращает значение NaN. Примеры числовых функций (2) • Функция floor(х) принимают в качестве аргумента одно число и возвращает максимальное целое, меньшее или равное своему аргументу. • Функция ceiling(х) возвращает наименьшее целое, большее или равное аргументу. Примеры числовых функций (3) • Функция round() возвращает свой аргумент, округленный до ближайшего целого. – При округлении таких чисел, как 1.5 и –3.5, одинаково близких к двум целым числам, round() возвращает наибольшее. • Функция sum() требует в качестве аргумента набор узлов. – Она преобразует каждый узел набора в его строковое значение, – затем каждая из этих строк преобразуется в число, и, наконец, складывает эти числа и возвращает их сумму. Работа с последовательностями • В языке XPath 2.0 были добавлены новые выражения для работы с последовательностями, такие, как: – циклы for; – кванторы every и some; – условия if. Выражение цикла for • Выражение for, предназначено для организации цикла по элементам последовательности. • Синтаксис цикла for практически аналогичен синтаксису цикла for в языках программирования (например, C#). • Например, цикл подсчитывающий общую сумму заказа для каждой строки заказа. for $line in /po:PurchaseOrder/po:OrderLines/po:Line return $line/po:Price * $line/po:Quantity • В данном примере for является ключевым словом, обозначающим, что необходимо перебрать всю последовательность строк и присвоить каждую из них переменной $line. – Для выбора последовательности используется путь доступа: po:PurchaseOrder/po:OrderLines/po:Line. • Далее следует ключевое слово return, которое динамически создает последовательность. • Затем на каждой итерации цикла к ней добавляется ноль, один или более элементов, после чего последовательность возвращается в качестве результата. • Использование последовательностей в качестве результатов имеет важное значение, потому что это позволяет организовать их дальнейшую обработку при помощи XPath. – Например, можно следующим образом подсчитать общую сумму заказа, передав показанную выше последовательность в функцию sum(). fn:sum(for $line in /po:PurchaseOrder/po:OrderLines/po:Line return $line/po:Price * $line/po:Quantity) Условный переход if • В языке XPath 2.0 также имеется выражение для условного перехода if. – Например: if(/po:PurchaseOrder/po:Seller = 'Bookstore') then 'ok' else 'ko' • В данном выражении в зависимости от истинности выражения в скобках, вычисляется либо раздел then, либо раздел else. Кванторы • Кванторы (или квантифицированные выражения – quantified expressions) – это проверки, выполняющиеся над последовательностью в целом. • Существуют два квантора, обозначающиеся ключевыми словами every (каждый) и some (какой-то). • Различие между циклом и квантором заключается в том, что результатом вычисления цикла является последовательность, результатом вычисления квантора является булевое значение. • Значением квантора every является true, если все элементы последовательности удовлетворяют условию. • Значение квантор some является истинным, если условие выполняется хотя бы для одного элемента. Пример использования квантора • Например, следующее выражение использует квантор every. every $line in /po:PurchaseOrder/po:OrderLines/po:Line satisfies $line/po:Code • Оно состоит из двух частей: – вначале значение последовательности присваивается переменной (аналогично тому, как это делается в цикле), – а затем указывается условие, которому должны удовлетворять элементы последовательности. • Результатом вычисления выше приведенного выражения будет false, так как четвертая строка не содержит элемент po:Code. • Если же заменить квантор every на some, то результатом будет true, ввиду того, что элемент po:Code содержится как минимум в одной строке. • Выражения над последовательностями можно комбинировать, создавая тем самым сложные запросы. – Например, подсчет общей суммы заказа только по тем строкам, которые включают атрибут кода продукта (po:Code) можно выполнить с помощью следующего выражения: fn:sum(for $line in /po:PurchaseOrder/po:OrderLines/po:Line return if($line/po:Code) then $line/po:Price * $line/po:Quantity else ()) – В выражение цикла for добавлено условное выражение if, которое возвращающее пустую последовательность в том случае, если отсутствия атрибут кода продукта.