XPath — язык для навигации внутри документа Назначение XPath: выбирать из документа узлы или значения, которые нужны для совершения с ними каких-л. операций (напечатать, подсчитать, преобразовать…)
Основные понятия:
Выражение на XPath (путь) выбирает в документе последовательность узлов или атомарных значений, отвечающих заданным условиям Последовательность может состоять из 0 или 1 члена
XPath — основные элементы
Основные понятия:
Выражение | Описание |
---|---|
. (точка) | Текущий узел |
.. (две точки) | Родительский узел |
../title | (путь от book/author к book/title) |
* | Узел с любым именем |
/booklist/* | все дети booklist |
/booklist/*/* | все внуки booklist |
node() | Любой узел |
text() | Узел с текстовым содержимым |
/library/book/chapter/* | выбор всех дочерних узлов любого узла chapter каждого узла book в library |
//book/* | выбор всех дочерних узлов всех book |
/*/*/*/paragraph | выбор всех paragraph которые имеют трех родителей |
//* | выбор всех элементов документа |
Аттрибут можно выбирать по его имени или по узлу в котором он находится. Аттрибут состоит из имени и значения, например в <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() используется для отсекания правых и левых пробелов в значении при сравнении |
Выражения с условием (предикатом)
Выражение | Описание |
---|---|
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 |
Оператор | Описание | Пример |
---|---|---|
| | Объединяет два множества | //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) |
< или < | меньше чем | price<9.80 |
<= или <= | меньше чем или равно | price<=9.80 |
> или > | больше чем | price>9.80 |
>= или >= | больше чем или равно | price>=9.80 |
Замечание: value=node-set и value!=node-set могут быть истины одновременно!
Оси (axes, ед.ч. axis), задают направление движения
в конкретном шаге.
В полном виде шаг выглядит так:
... /имя_оси::узел[условие]/ ...
... /sibling::book[25]/ ...
Ось по умолчанию — child: /booklist/child::book = /booklist/book
Ось | Описание |
---|---|
ancestor | предки текущего узла |
ancestor-or-self | предки текущего узла и он сам |
attribute:: | все аттрибуты текущего узла |
child | прямой потомок текущего узла |
descendant | потомки текущего узла |
descendant-or-self | >потомки текущего узла и он сам |
following | все узлы после текущего узла в XML документе |
following-sibling | все узлы после текущего на этом же уровне |
namespace | все пространства имен текущего узла |
parent | прямой предок текущего узла |
preceding | все узлы перед текущим узлом в XML документе, кроме предков, аттрибутов и namespace |
preceding-sibling:: | все узлы перед текущим узлом на этом же уровне |
self:: | сам текущий узел |
Пример | Описание |
---|---|
//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:: неприменимы к аттрибутам и пространствам имен
Пример | Описание |
---|---|
(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 документа, созданого в первой лабораторной работе, выполнить такие запросы:
Отчет должен содержать листинги всех 7 запросов и полученных результатов выполнения запроса.