XPath, XQuery

XPath — язык для навигации внутри документа Назначение XPath: выбирать из документа узлы или значения, которые нужны для совершения с ними каких-л. операций (напечатать, подсчитать, преобразовать…)

сведения

Основные понятия:

Выражение на XPath (путь) выбирает в документе последовательность узлов или атомарных значений, отвечающих заданным условиям Последовательность может состоять из 0 или 1 члена

XPath — основные элементы

Основные понятия:

XPath — выбор узлов

Выражение Описание
. (точка)Текущий узел
.. (две точки)Родительский узел
../title(путь от book/author к book/title)
*Узел с любым именем
/booklist/*все дети booklist
/booklist/*/*все внуки booklist
node()Любой узел
text()Узел с текстовым содержимым
/library/book/chapter/*выбор всех дочерних узлов любого узла chapter каждого узла book в library
//book/*выбор всех дочерних узлов всех book
/*/*/*/paragraphвыбор всех paragraph которые имеют трех родителей
//*выбор всех элементов документа

XPath - аттрибуты

Аттрибут можно выбирать по его имени или по узлу в котором он находится. Аттрибут состоит из имени и значения, например в <chapter num="5">, имя аттрибута - num, значение - 5. Для выбора аттрибута по имени используется префикс @.

@num выбирает аттрибут с именем num

//@* выбирает ВСЕ аттрибуты в документе

Для выбора аттрибута по узлу необходимо его имя с префиксом заключить в квадратные скобки:

//chapter[@num]

выбирает каждый chapter элемент в любом месте документа, который содержит аттрибут num

Выражение Описание
@Атрибут
//book/@langатрибут по имени lang
//book/@*все атрибуты
//chapter[@num]выбирает все chapter узлы с аттрибутом num
//chapter[not(@num)]выбирает все chapter узлы, которые не содержат аттрибута num
//chapter[@*]выбирает все chapter узлы, которые содержат любые аттрибуты
//chapter[not(@*)]выбирает все chapter узлы, которые не содержат аттрибутов
//chapter[@num='3']выбирает все chapter узлы с аттрибутом num равным 3
//chapter[normalize-space(@num)="3"]Функция normalize-space() используется для отсекания правых и левых пробелов в значении при сравнении

XPath - условия и выражения

Выражения с условием (предикатом)

Выражение Описание
book[2]условие на номер узла в последовательности
book[last()]условие на номер узла в последовательности
book[position()<3]условие на номер узла в последовательности
book[city="Seoul"]условие на значение дочерних элементов (путь отсчитывается от текущей позиции)
book[price>250]
book[count = 0 or count = 1]
//book[@lang="rus"]/titleусловие на значение атрибутов
book[2]/author vs. book/author[2]Условие […] применяется к тому узлу, после которого стоит
//chapter[count(section)=1]count(elem) количество выбраных узлов, selects chapters с строго одним дочернем узлом section
//*[name()='section']аналогично //section, name() возвращает имя узла
//*[starts-with(name(), 'sec')]starts-with(arg1, arg2) проверяет начинается ли arg1 с arg2
//*[contains(name(), 'ect')]contains(arg1, arg2) проверяет, содержит ли arg1 в себе arg2
XPath — операторы
Оператор Описание Пример
|Объединяет два множества//book | //cd
+сложение6 + 4
-вычитание6 - 4
*умножение6 * 4
divделение8 div 4
modостаток от деления5 mod 2
=равноprice=9.80
!=не равноprice!=9.80
andлогический оператор иprice>9.00 and price<9.90
orлогический оператор илиprice=9.80 or price=9.70
not()функция отрицанияnot(price < 9.80)
< или &lt;меньше чемprice<9.80
<= или &lt;=меньше чем или равноprice<=9.80
> или &gt;больше чемprice>9.80
>= или &gt;=больше чем или равноprice>=9.80

Замечание: value=node-set и value!=node-set могут быть истины одновременно!

XPath оси

Оси (axes, ед.ч. axis), задают направление движения в конкретном шаге. В полном виде шаг выглядит так:

... /имя_оси::узел[условие]/ ...

... /sibling::book[25]/ ...

Ось по умолчанию — child: /booklist/child::book = /booklist/book

XPath — оси (axes)
Ось Описание
ancestorпредки текущего узла
ancestor-or-selfпредки текущего узла и он сам
attribute::все аттрибуты текущего узла
childпрямой потомок текущего узла
descendantпотомки текущего узла
descendant-or-self>потомки текущего узла и он сам
followingвсе узлы после текущего узла в XML документе
following-siblingвсе узлы после текущего на этом же уровне
namespaceвсе пространства имен текущего узла
parentпрямой предок текущего узла
precedingвсе узлы перед текущим узлом в XML документе, кроме предков, аттрибутов и namespace
preceding-sibling::все узлы перед текущим узлом на этом же уровне
self::сам текущий узел
XPath — оси (axes), примеры
Пример Описание
//book/descendant::*все потомки каждого book
//book/descendant::sectionвсе потомки section каждого book
//parent::*любой элемент, являющийся родителем
//section/parent::*любой родитель узла section
//parent::chapterлюбой узел chapter который является родителем (т.е. имеет дочерние узлы)
/library/book[3]/following::*каждый узел book в библиотеке по номеру больше 3

Замечание: preceding-sibling:: и following-sibling:: неприменимы к аттрибутам и пространствам имен

XPath — оси. Сокращения/синонимы.
Пример Описание
(none)можно заменить на child::
@можно заменить на attribute::
.можно заменить на self::node()
.//Xможно заменить на self::node()/descendant-or-self::node()/child::X
..можно заменить на parent::node()
../Xможно заменить на parent::node()/child::X
//можно заменить на /descendant-or-self::node()/
//Xможно заменить на /descendant-or-self::node()/child::X

Технология XPath предназначена для адресации какой-либо части дерева XML, и, чаще всего, используется вместе с технологией XSLT. XQuery является своего рода расширением языка XPath, и позволяет строить более сложные запросы к дереву XML документа (например, к разным его веткам).

Программирование XPath и XQuery запросов является с программной точки зрения нелегкой задачей, поэтому для их создания воспользуемся freeware open source утилитой xmllint.

Практический пример

Пусть мы имеем XML документ sonnet.xml следующего содержания:

<?xml version="1.0"?>
<sonnet type="Shakespearean">
  <author>
    <lastName>Shakespeare</lastName>
    <firstName>William</firstName>
    <nationality>British</nationality>
    <yearOfBirth>1564</yearOfBirth>
    <yearOfDeath>1616</yearOfDeath>
  </author>
  <title>Sonnet 130</title>
  <lines>
    <line>My mistress' eyes are nothing like the sun,</line>
    <line>Coral is far more red than her lips red.</line>
    <line>If snow be white, why then her breasts are dun,</line>
    <line>If hairs be wires, black wires grow on her head.</line>
    <line>I have seen roses damasked, red and white,</line>
    <line>But no such roses see I in her cheeks.</line>
    <line>And in some perfumes is there more delight</line>
    <line>Than in the breath that from my mistress reeks.</line>
    <line>I love to hear her speak, yet well I know</line>
    <line>That music hath a far more pleasing sound.</line>
    <line>I grant I never saw a goddess go,</line>
    <line>My mistress when she walks, treads on the ground.</line>
    <line>And yet, by Heaven, I think my love as rare</line>
    <line>As any she belied with false compare.</line>
  </lines>
</sonnet>

Чтобы загрузить XML документ для разбора парсером, необходимо выполнить:

xmllint sonnet.xml

Если необходимо выполнить выражение XPath, необходимо воспользоваться командой

xmllint --xpath "XPath_выражение" sonnet.xml

Например, выражение

xmllint --xpath "//line/text()" sonnet.xml

Выдаст построчно содержимое сонета:

My mistress' eyes are nothing like the sun,
Coral is far more red than her lips red.
If snow be white, why then her breasts are dun,
If hairs be wires, black wires grow on her head.
I have seen roses damasked, red and white,
But no such roses see I in her cheeks.
And in some perfumes is there more delight
Than in the breat[1;5Hh that from my mistress reeks.
I love to hear her speak, yet well I know
That music hath a far more pleasing sound.
I grant I never saw a goddess go,
My mistress when she walks, treads on the ground.
And yet, by Heaven, I think my love as rare
As any she belied with false compare.

Задание на лабораторную работу

Необходимо для XML документа, созданого в первой лабораторной работе, выполнить такие запросы:

  1. Запрос на поиск любого элемента в любом месте, независимо от уровня и места нахождения.
  2. Запрос на поиск элемента, относительно корня.
  3. Запрос на поиск элемента, относительно любой (выбранной Вами) оси.
  4. Запрос на поиск элемента, у которого проверяется равенство аттрибута конкретному значению.
  5. Запрос с применением строковых функций для работы с содержимым элемента.
  6. Запрос на применение агрегирующей функции (типа avg).
  7. Любой запрос с применением оператора XQuery.

Отчет должен содержать листинги всех 7 запросов и полученных результатов выполнения запроса.

Вопросы

  1. XPath. Методы задания пути к узлам.
  2. XPath. Работа с аттрибутами.
  3. XPath. Условия выражений для элементов и аттрибутов.
  4. XPath. Оси.
  5. XPath. Функции (в т.ч. агрегирующие).
  6. XQuery. Операторы.