Xpath. Базовый синтаксис

Категория: IT / WEB / Internet

Xpath - декларативный язык запросов к элементам xml или (x)html документа и xslt преобразований.

Полезные источники:

Полная спецификация по Xpath 1.0 на русском здесь - http://citforum.ru/internet/xpath/xpath.shtml.

Xpath Online Tester - http://www.xpathtester.com/xpath/

Использование Xpath в Firebug

Для поиска DOM элементов по Xpath в Firebug есть встроенная ф-ция:

$x(xpath [, contextNode [, resultType]])

Тип результата:

XPathResult.NUMBER_TYPE
XPathResult.STRING_TYPE
XPathResult.BOOLEAN_TYPE
XPathResult.FIRST_ORDERED_NODE_TYPE
XPathResult.UNORDERED_NODE_ITERATOR_TYPE

Пример использования XPATH запросов в Firebug:

$x('//tr[@data-place]/@data-place')[0].value
$x('string(//tr[@data-place][1]/@data-place)')

Примеры

Примеры запросов:

//*[@id="container"]
//div[contains(@class, 'CLASS') and normalize-space(text())='TEXT']
//a[normalize-space(text())='TEXT']
//*[normalize-space(text())='Купить']/ancestor-or-self::button

Пример JavaScript запроса XPath в браузере:

let modelName = '';
let xpath = '//*[@id="mod-detail-attributes"]//*[normalize-space(text())="Номер статьи"]//ancestor-or-self::td/following-sibling::td[contains(@class, "de-value")][1]';
let modelFromParamsNode = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
if (modelFromParamsNode) {
    modelName = modelFromParamsNode.textContent.trim();
}

Базовый синтаксис

Пути

.             # текущий контекст
.//           # рекурсивный спуск (на ноль или более уровней от текущего контекста)
/html/body    # абсолютный путь
table//a      # относительный путь
a             # путь относительно текущего контекста
//*           # все в текущем контексте
li/*/a        # ссылки, являющиеся "внуками" для li
//a|//button  # ссылки и кнопки (объединение двух множеств узлов)

Отношения

a/i/parent::p           # непосредственный родитель, <p>
p/ancestor::*           # все родители (http://bit.ly/1ta7mh9)
p/following-sibling::*  # все следующие братья
p/preceding-sibling::*  # все предыдущие братья 
p/following::*          # все следующие элементы кроме потомков (http://bit.ly/1ta83H5)
p/preceding::*          # все предыдущие элементы кроме предков
p/descendant-or-self::* # контекстный узел и все его потомки
p/ancestor-or-self::*   # контекстный узел и все его предки

Получение узлов

/div/text()     # получить текстовые узлы
/div/text()[1]  # получить первый текстовый узел

Позиция элемента

a[1]                     # первый элемент
a[last()]                # последний элемент
a[i][2]                  # вторая ссылка, которая содержит элемент <i>
a[position() <= 3]       # Первые 3 ссылки
ul[li[1]="OK"]           # список (UL), первый элемент которого содержит значение 'OK'
tr[position() mod 2 = 1] # не четные элементы
tr[position() mod 2 = 0] # четные элементы
p/text()[2]              # второй текстовый узел

Атрибуты и фильтры

[] - указывает на фильтрацию элементов

input[@type=text]  # атрибуты задаются с префиксом @
input[@class='OK'] # 
p[not(@*)]         # параграфы без атрибутов
*[@style]          # все элементы с атрибутом style
a[. = "OK"]        # ссылки со значением "OK"
a/@id              # идентификаторы ссылок
a/@*               # все атрибуты ссылок
a[@id and @rel]    # ссылки, которые содержат атрибуты id и rel
a[@id][@rel]       # то же самое
a[i or b]          # ссылки содержат элемент <i> или <b>

Функции

Базовые функции Xpath - http://www.w3.org/TR/xpath/#corelib

name()                         [name()='a']                 # возвращает имя элемента
string(val)                    string(a[1]/@id)              # получить значение атрибута
substring(val, from, to)       substring(@id, 1, 6)          # вырезать часть строки
substring-after(val, from)     substring-after(@id, 'FROM') 
substring-before
string-length()      [string-length(text()) > 5]        # возвращает число символов в строке
count()              # возвращает количество элементов
concat()
normalize-space()    [normalize-space(text())='SEARCH']  # аналог trim, удаляет пробелы Пример: 
starts-with()        [starts-with(text(), 'SEARCH')]
contains()           [contains(name(), 'SEARCH')]
translate("bar","abc","ABC") # BAr

Математика

//p[ position() = floor(last() div 2 + 0.5) or position() = ceiling(last() div 2 + 0.5) ]
//tr[position() mod 2 = 0]

position()  # 
div         # деление
mod         # остаток от деления
ceiling()   # минимальное целое
floor()     # максимальное целое
round()
sum()

Группирование

(table/tbody/tr)[last()]  # последняя строка <tr> из всех таблиц
(//h1|//h2)[contains(text(), 'Text')] # заголовок первого или второго уровня, который содержит "Text"

Составные условия фильтрации

Все ссылки у которых атрибут data-id совпадает с этим же атрибутом у строки таблицы:

a[//tr/@data-id=@data-id]