XPath
Введение
XPath (XML Path Language) — язык адресации узлов в XML- и HTML-подобных деревьях. XPath используют в XSLT, XQuery, Schematron, в API .NET (XmlDocument.SelectNodes), Java (javax.xml.xpath), в тестах и инструментах (xmlstarlet, браузерные DevTools).
Базовый XML для примеров ниже:
<library>
<book id="1" genre="classic">
<title>Война и мир</title>
<author>Лев Толстой</author>
<price>450</price>
</book>
<book id="2" genre="novel">
<title>Мастер и Маргарита</title>
<author>Михаил Булгаков</author>
<price>380</price>
</book>
</library>
Основы XML: глава XML. Синтаксис XPath в XSLT-паттернах (match) — XSLT.
Терминология
| Термин | Описание |
|---|---|
| Узел (node) | Элемент, атрибут, текст, комментарий, PI, корень документа |
| Контекстный узел | Узел, относительно которого вычисляется выражение |
| Контекстная позиция | Порядковый номер среди узлов, отобранных предыдущим шагом |
| Контекстный размер | Общее число таких узлов |
| Шаг (step) | Ось + тест узла, например child::book |
| Путь (location path) | Цепочка шагов: /library/book/title |
| Предикат | Условие в [...], сужающее набор узлов |
| Последовательность узлов | Упорядоченный набор узлов (результат многих выражений) |
Типы узлов в XPath 1.0:
- element, attribute, text, comment, processing-instruction, namespace, root
Синтаксис путей
Абсолютный и относительный путь
| Запись | Смысл |
|---|---|
/library | От корня документа к элементу library |
book | Дочерние book контекстного элемента |
//author | Все author на любой глубине (ось descendant-or-self) |
. | Текущий контекстный узел |
.. | Родитель (parent::node()) |
@id | Атрибут id текущего элемента |
text() | Текстовые дочерние узлы |
Примеры к документу выше:
/library/book /* все книги */
/library/book[1]/title /* заголовок первой книги */
/library/book[@id='2'] /* книга с id=2 */
//author /* оба автора */
//book[price > 400]/title /* дорогие книги — заголовки */
Тесты узлов
| Тест | Пример |
|---|---|
| По имени элемента | book, title |
| По имени атрибута | @genre |
| Универсальный | * (любой элемент), @* (любой атрибут) |
| По типу узла | node(), text(), comment() |
| По локальному имени с NS | В XPath 2.0+ — QName; в 1.0 часто префиксы в документе |
Оси (axes)
Ось задаёт направление обхода дерева относительно контекстного узла.
| Ось | Сокращение | Что выбирает |
|---|---|---|
child | (по умолчанию) | Прямые дочерние элементы |
attribute | @ | Атрибуты |
descendant | Все потомки | |
descendant-or-self | // в начале шага | Узел и все потомки |
parent | .. | Родитель |
ancestor | Все предки | |
ancestor-or-self | Узел и предки | |
following-sibling | Следующие соседи | |
preceding-sibling | Предыдущие соседи | |
following | Все узлы после в документе | |
preceding | Все узлы до в документе | |
self | . | Сам контекстный узел |
namespace | Узлы пространств имён |
Полная запись шага: ось::тестузла[предикат].
/descendant::book[@genre='classic']/child::title
ancestor::library
following-sibling::book[1]
Базис: Операторы — оператор, операнд и приоритет в коде.
Операторы и выражения
Сравнение и логика
| Оператор | Пример |
|---|---|
=, != | [@id='2'], [author != ''] |
<, <=, >, >= | [price > 400] (числа — если типизировано; в 1.0 часто лексикографически) |
and, or, not() | [genre='novel' and price < 400] |
Арифметика (XPath 1.0 — над числами в выражениях)
+, -, *, div, mod — например //book[position() mod 2 = 1] (нечётные позиции).
Объединение путей
| — объединение двух наборов узлов:
//book/title | //book/author
Полезные функции (XPath 1.0)
| Функция | Назначение |
|---|---|
position() | Позиция в текущем списке |
last() | Размер списка |
count(//book) | Число узлов |
contains(s, sub) | Подстрока |
starts-with(s, p) | Префикс строки |
normalize-space(s) | Обрезка пробелов |
string(), number(), boolean() | Приведение типов |
concat(a, b, ...) | Склейка строк |
//book[contains(author, 'Толстой')]
//book[last()]/title
count(//book[@genre='novel'])
XPath 2.0/3.0 (XQuery, Saxon, современный .NET) добавляют типы, регулярные выражения, for, if, последовательности — см. справочник по XML (раздел XDM).
XPointer — адрес фрагмента в URI
XPath выбирает узлы внутри уже загруженного документа. XPointer (XML Pointer Language) решает другую задачу: указать фрагмент XML в URL — "возьми не весь chapter.xml, а элемент с id="intro"".
Схема:
https://example.com/doc.xml#xpointer(id('intro'))
https://example.com/doc.xml#xpointer(/book/chapter[3])
XPointer опирается на XPath и расширяет его термами (в ранних спецификациях W3C):
| Терм | Назначение |
|---|---|
id('name') | Элемент с атрибутом типа ID или xml:id="name" |
element(/1/2/3) | Путь по номерам дочерних элементов от корня |
xpointer(expr) | Обёртка над XPath-выражением |
xmlns(...) | Объявление префикса для XPath внутри URI |
Пример для документа с отделами:
<company>
<department id="sales">
<employee><name>Sarah Bellum</name></employee>
</department>
<department id="marketing">...</department>
</company>
| XPointer | Что выберет |
|---|---|
id('sales') | <department id="sales"> |
xpointer(//employee[1]/name) | Первый <name> среди сотрудников |
xpointer(/company/department[2]) | Второй отдел |
XInclude использует XPointer в атрибуте xpointer, когда нужен не весь включаемый файл:
<xi:include href="chapter1.xml" xpointer="xpointer(//*[@id='summary'])"/>
Современный стандарт — XPointer Framework и элементные схемы (element()); поддержка в инструментах неравномерна. Для новых проектов чаще включают целые файлы через XInclude или собирают документ в коде. Подробнее — справочник по XML, XLink.
ID и IDREF (DTD) и xml:id — простой способ пометить якорь без полного XPointer: href="doc.xml#section-3" работает, если у элемента id="section-3".
Практические примеры
| Задача | Выражение |
|---|---|
| Все идентификаторы книг | //book/@id |
| Первая книга | (//book)[1] или //book[1] * |
| Книги без цены | //book[not(price)] |
| Суммарно жанры | //book/@genre |
Заголовок родительской книги для author | //author/ancestor::book/title |
* В XPath 1.0 //book[1] — первая книга в каждом контексте предиката; для "первой в документе" надёжнее (//book)[1].
Чит-лист: cheatsheets.zip/xpath
Play ITЗагрузка интерактивного демо…
Где применяется XPath
- XSLT — атрибуты
select,match,test; - XPointer / XInclude — фрагмент документа в URI;
- XSD 1.1 — ограничения
assert; - Schematron — правила валидации;
- Тестирование API — проверка тела SOAP/XML;
- Конфигурации — Spring, Maven, MSBuild (внутренние селекторы в плагинах);
- Браузер — оценка XPath в консоли для XML/SVG.
По XML-библиотеке выше напишите запросы: (1) все цены; (2) книги дороже 400; (3) заголовок книги с id=2; (4) число книг жанра novel. Проверьте в демо на этой странице.