XPath Selectors
Начало работы
- Xpath test bed (whitebeam.org)
Протестируйте в консоли Firefox или Chrome: ``console $x(’/html/body’) $x(’//h1’) $x(’//h1’)[0].innerText $x(’//a[text()=“XPath”]’)[0].click()
### Селекторы-потомки {.col-span-2}
| Xpath | CSS |
|--------------|--------------|
| `//h1` | h1 |
| | `//div//p` | div p |
| `//ul/li` | ul > li |
| `//ul/li/a` | ul > li > a |
| | `//div/*` | div > * |
| `/` | :root |
| `/html/body` | :root > body |
{.show-header}
### Заказать селекторы {.col-span-2}
| Xpath | CSS |
|---------------------|----------------------|
| `//ul/li[1]` | ul > li:first-child |
| `//ul/li[2]` | ul > li:nth-child(2) |
| `//ul/li[last()]` | ul > li:last-child |
| `//li[@id="id"][1]` | li#id:first-child |
| | `//a[1]` | a:first-child |
| `//a[last()]` | a:last-child |
{.show-header}
### Селекторы атрибутов {.col-span-3 .row-span-2}
| Xpath | CSS |
|---------------------------------|----------------------|
| `//*[@id="id"]` | #id |
| `//*[@class="class"]` | .class |
| `//input[@type="submit"]` | input[type="submit"]|
| | `//a[@id="abc"][@for="xyz"]` | a#abc[for="xyz"] |
| | `//a[@rel]` | a[rel] |
| `//a[starts-with(@href, '/')]` | | a[href^='/'] |
| `//a[ends-with(@href, '.pdf')]` | a[href$='pdf'] |
| `//a[contains(@href, '://')]` | | a[href*='`:`//'] |
| `//a[contains(@rel, 'help')]` | | a[rel~='help'] |
{.show-header}
### Родные братья и сестры {.col-span-3}
| Xpath | CSS |
|--------------------------------------|----------|
| `//h1/following-sibling::ul` | h1 ~ ul |
| | `//h1/following-sibling::ul[1]` | h1 + ul |
| | `//h1/following-sibling::[@id="id"]` | h1 ~ #id |
{.show-header}
### jQuery {.col-span-3}
| Xpath | CSS |
|----------------------------------|----------------------------|
| | `//ul/li/...` | $('ul > li').parent() |
| `//li/ancestor-or-self::section` | $('li').closest('section') |
| `//a/@href` | $('a').attr('href') |
| | `//span/text()` | $('span').text() |
{.show-header}
### Misc селекторы {.col-span-3}
| Xpath | CSS |
|-----------------------------------|---------------------------|
| `//h1[not(@id)]` | h1:not([id])|
| `//button[text()="Submit"]` | | Text match |
| `//button[contains(text(), "Go")]` | Текст содержит (подстроку) |
| `//product[@price > 2.50]` | Арифметика |
| `//ul[*]` | Имеет дочерние элементы |
| `//ul[li]` | Имеет дочерние элементы (конкретные) |
| `//a[@name или @href]` | Или логика |
| | `//a | //div` | Объединение (объединяет результаты) |
{.show-header}
Выражения XPath
-----------
### Шаги и оси {.secondary}
<br/>
| - | - | - | - |
|------|------|------|-----------------|
| `//` | `ul` | `/` | `a[@id='link']` |
| Axis | Step | Axis | Step |
{.left-text}
### Префиксы
| Префикс | Пример | Средства |
|--------|-----------------------|----------|
| `//` | `//hr[@class='edge']` | Anywhere |
| `/` | `/html/body/div` | Корень |
| `./` | `./div/p` | Относительный |
{.show-header}
### Оси
| Ось | Пример | Средства |
|------|---------------------|------------|
| `/` | `//ul/li/a` | Child |
| `//` | `//[@id="list"]//a` | Descendant |
{.show-header}
Предикаты XPath
----------
### Предикаты
``bash
//div[true()]
//div[@class="head"]
//div[@class="head"][@id="top"]
Ограничивает набор узлов только в том случае, если некоторое условие истинно. Они могут быть соединены в цепочку.
Операторы
``bash
Сравнение
//a[@id = “xyz”] //a[@id != “xyz”] //a[@price > 25]
``bash
# Логика (и/или)
//div[@id="head" and position()=2]
//div[(x и y) или not(z)]
Использование узлов
``bash
Использование узлов внутри функций
//ul[count(li) > 2] //ul[count(li[@class=‘hide’]) > 0]
``bash
# Возвращает `<ul>`, у которого есть дочерний `<li>`.
//ul[li]
Вы можете использовать узлы внутри предикатов.
Индексирование
``bash //a[1] # первый //a[last()] # last //ol/li[2] # второй //ol/li[position()=2] # то же, что и выше //ol/li[position()>1] #:not(:first-child)
Используйте `[]` с числом, или `last()`, или `position()`.
### Порядок цепочки
``bash
a[1][@href='/']
a[@href='/'][1]
Порядок имеет значение, эти два варианта отличаются.
Вложенные предикаты
//section[.//h1[@id='hi']]
Возвращается <section>
, если у него есть потомок <h1>
с id='hi'
.
Функции XPath
Функции узлов
``bash name() # //[starts-with(name(), ‘h’)] text() # //button[text()=“Submit”] # //button/text() lang(str) namespace-uri()
``bash
count() # //table[count(tr)=1]
position() # //ol/li[position()=2]
Строковые функции
``bash contains() # font[contains(@class, “head”)] starts-with() # font[starts-with(@class, “head”)] ends-with() # font[ends-with(@class, “head”)]
``bash
concat(x,y)
substring(str, start, len)
substring-before("01/02", "/") #=> 01
substring-after("01/02", "/") #=> 02
translate()
normalize-space()
string-length()
Булевы функции
``bash not(expr) # button[not(starts-with(text(), “Submit”))]
### Преобразование типов
```bash
строка()
число()
boolean()
Оси XPath
Использование осей
``bash //ul/li # ul > li //ul/child::li # ul > li (то же самое) //ul/following-sibling::li # ul ~ li //ul/descendant-or-self::li # ul li //ul/ancestor-or-self::li # $(‘ul’).closest(’li’)
----
| | | | |
|------|------|------------|------|
| `//` | `ul` | `/child::` | `li` |
| Axis | Step | Axis | Step |
{.left-text}
Шаги выражения разделяются символом `/`, который обычно используется для выбора дочерних узлов. Это не всегда верно: с помощью `::` можно указать другую "ось".
### Дочерняя ось
``bash
# обе одинаковые
//ul/li/a
//child::ul/child::li/child::a
child::
- это ось по умолчанию. Это обеспечивает работу //a/b/c
.
``bash
оба одинаковые
это работает, потому что child::li
является истиной.
//ul[li] //ul[child::li]
``bash
# оба одинаковые
//ul[count(li) > 2]
//ul[count(child::li) > 2]
Ось “спуск-или-самостоятельность
# оба одинаковы
//div//h4
//div/descendant-or-self::h4
//
- это сокращение для оси descendant-or-self::
.
``bash
оба одинаковые
//ul//[last()] //ul/descendant-or-self::[last()]
### Другие оси {.row-span-2}
| Axis | Abbrev | Notes |
|--------------------|--------|-------|
| `ancestor` | | | |
| `ancestor-or-self` | | | |
| | `attribute` | `@` | `@href` - сокращение от `attribute::href` |
| `child` | | `div` - сокращение от `child::div` |
| | `descendant` | | | |
| | `descendant-or-self` | `//` | `//` - это сокращение от `/descendant-or-self::node()/` |
| `namespace` | | | |
| `self` | `.` | `.` - это сокращение от `self::node()` |
| | `parent` | `..` | `..` - это сокращение от `parent::node()` |
| `following` | | | |
| | `следующий-сестринский` | | | | |
| `preceding` | | | |
| | `предшествующий-брат` | | | |
{.headers}
Существуют и другие оси, которые можно использовать.
### Союзы
``bash
//a | //span
Используйте |
для соединения двух выражений.
XPath Дополнительные примеры
Примеры
``bash //* # все элементы count(//*) # подсчет всех элементов (//h1)[1]/text() # текст первого заголовка h1 //li[span] # найти с внутри # …расширяется до //li[child::span] //ul/li/… # используйте … для выбора родителя
### Найти родителя
``bash
//section[h1[@id='section-name']]
Находит <секцию>
, которая непосредственно содержит h1#section-name
.
``bash //section[//h1[@id=‘section-name’]]
Находит `<секцию>`, содержащую `h1#section-name`.
(То же самое, что и выше, но вместо child используется descendant-or-self)
### Ближайший
``bash
./ancestor-or-self::[@class="box"]
Работает аналогично jQuery’овскому $().closest('.box')
.
Атрибуты
``bash //item[@price > 2*@discount]
Находит `<item>` и проверяет его атрибуты
Также см.
--------
* [Devhints](https://devhints.io/xpath) _(devhints.io)_
* [Xpath test bed](http://www.whitebeam.org/library/guide/TechNotes/xpathtestbed.rhtm) _(whitebeam.org)_