HTML Diff
1 added 1 removed
Original 2026-01-01
Modified 2026-02-26
1 <p>Язык разметки XML с самого первого стандарта окружает пользователей компьютеров. Таблицы в Excel, выгрузки из интернет-магазинов, RSS-ленты с новостями - все это основано на XML. Хоть визуальное отображение отличается на устройствах и в программах, но в основе всегда лежит единый формат.</p>
1 <p>Язык разметки XML с самого первого стандарта окружает пользователей компьютеров. Таблицы в Excel, выгрузки из интернет-магазинов, RSS-ленты с новостями - все это основано на XML. Хоть визуальное отображение отличается на устройствах и в программах, но в основе всегда лежит единый формат.</p>
2 <p>Внутри XML-файла может находиться огромное количество информации, поэтому и встает вопрос о перемещении и выборке внутри документа. Как это сделать быстро? Какие средства применять, чтобы в интернет-магазине найти нужный товар из десятков тысяч других? Для навигации и поиска внутри XML используется<strong>язык запросов XPath</strong>.</p>
2 <p>Внутри XML-файла может находиться огромное количество информации, поэтому и встает вопрос о перемещении и выборке внутри документа. Как это сделать быстро? Какие средства применять, чтобы в интернет-магазине найти нужный товар из десятков тысяч других? Для навигации и поиска внутри XML используется<strong>язык запросов XPath</strong>.</p>
3 <p>В этой статье разберем:</p>
3 <p>В этой статье разберем:</p>
4 <ul><li>для кого может быть полезен<em>XPath</em></li>
4 <ul><li>для кого может быть полезен<em>XPath</em></li>
5 <li>базовые конструкции языка для поиска информации в XML</li>
5 <li>базовые конструкции языка для поиска информации в XML</li>
6 <li>чем XPath отличается от CSS-селекторов при поиске в HTML</li>
6 <li>чем XPath отличается от CSS-селекторов при поиске в HTML</li>
7 </ul><h2>Содержание</h2>
7 </ul><h2>Содержание</h2>
8 <ul><li><a>Синтаксис XPath</a></li>
8 <ul><li><a>Синтаксис XPath</a></li>
9 <li><a>Отличия от CSS-селекторов</a></li>
9 <li><a>Отличия от CSS-селекторов</a></li>
10 <li><a>Кому нужен Xpath</a></li>
10 <li><a>Кому нужен Xpath</a></li>
11 <li><a>Заключение</a></li>
11 <li><a>Заключение</a></li>
12 </ul><h2>Синтаксис XPath</h2>
12 </ul><h2>Синтаксис XPath</h2>
13 <p>Для начала создадим базовый пример XML, с которым и будем работать весь урок. Например, список курсов по верстке на Хекслете в XML будет выглядеть так:</p>
13 <p>Для начала создадим базовый пример XML, с которым и будем работать весь урок. Например, список курсов по верстке на Хекслете в XML будет выглядеть так:</p>
14 <p>Это учебный пример, но для отработки навыков<em>XPath</em>подойдет и любой другой XML. Принципы<em>XPath</em>сохранятся при любой структуре файла, потому что по стандарту XML можно использовать элементы с произвольными тегами.</p>
14 <p>Это учебный пример, но для отработки навыков<em>XPath</em>подойдет и любой другой XML. Принципы<em>XPath</em>сохранятся при любой структуре файла, потому что по стандарту XML можно использовать элементы с произвольными тегами.</p>
15 <p>Для тестирования результата подойдут такие онлайн-сервисы, как:</p>
15 <p>Для тестирования результата подойдут такие онлайн-сервисы, как:</p>
16 <ul><li><a>Code Beautify</a></li>
16 <ul><li><a>Code Beautify</a></li>
17 <li><a>XPather</a></li>
17 <li><a>XPather</a></li>
18 </ul><h3>Абсолютные пути</h3>
18 </ul><h3>Абсолютные пути</h3>
19 <p>Самый простой запрос состоит из обращения к корневому элементу. Для этого достаточно выполнить запрос /courses. Нам вернется XML в почти таком же виде, что и в примере выше. Обратите внимание на строку &lt;?xml version="1.0" encoding="UTF-8"?&gt;. Она отличается, потому что элемент не внутри &lt;courses&gt;:</p>
19 <p>Самый простой запрос состоит из обращения к корневому элементу. Для этого достаточно выполнить запрос /courses. Нам вернется XML в почти таком же виде, что и в примере выше. Обратите внимание на строку &lt;?xml version="1.0" encoding="UTF-8"?&gt;. Она отличается, потому что элемент не внутри &lt;courses&gt;:</p>
20 <p>В качестве результата<em>XPath</em>возвращает узлы XML-документа.</p>
20 <p>В качестве результата<em>XPath</em>возвращает узлы XML-документа.</p>
21 <p>Продолжим цепочку и обратимся к описанию из элемента &lt;description&gt;. Для этого добавим в запрос путь к description: /courses/description. Результатом выполнения станет:</p>
21 <p>Продолжим цепочку и обратимся к описанию из элемента &lt;description&gt;. Для этого добавим в запрос путь к description: /courses/description. Результатом выполнения станет:</p>
22 <p>Путь, который строится от корневого элемента, называется<strong>абсолютным</strong>. Используем схему из прошлого запроса и обратимся к любому элементу внутри XML.</p>
22 <p>Путь, который строится от корневого элемента, называется<strong>абсолютным</strong>. Используем схему из прошлого запроса и обратимся к любому элементу внутри XML.</p>
23 <p>Попробуем обратиться к имени курса. В этом случае вернется поле &lt;name&gt; из всех курсов. Запрос /courses/course/name вернет:</p>
23 <p>Попробуем обратиться к имени курса. В этом случае вернется поле &lt;name&gt; из всех курсов. Запрос /courses/course/name вернет:</p>
24 <p>Вот список некоторых базовых запросов и их результат:</p>
24 <p>Вот список некоторых базовых запросов и их результат:</p>
25 <h3>Относительные пути</h3>
25 <h3>Относительные пути</h3>
26 <p>Прошлые запросы строились с помощью абсолютных путей - то есть мы указывали полный путь до информации. Бывают ситуации, когда полный путь не подходит: например, мы хотим обраться к какому-то уникальному полю или не знаем полный путь. В этом случае можно использовать<strong>относительный путь</strong>- он произведет поиск по всему XML и вернет узлы, подходящие под запрос.</p>
26 <p>Прошлые запросы строились с помощью абсолютных путей - то есть мы указывали полный путь до информации. Бывают ситуации, когда полный путь не подходит: например, мы хотим обраться к какому-то уникальному полю или не знаем полный путь. В этом случае можно использовать<strong>относительный путь</strong>- он произведет поиск по всему XML и вернет узлы, подходящие под запрос.</p>
27 <p>Чтобы записать относительный путь, нужно использовать конструкцию //. После нее можно написать любое поле и получить результат. Например, //name вернет поля &lt;name&gt; из всего XML:</p>
27 <p>Чтобы записать относительный путь, нужно использовать конструкцию //. После нее можно написать любое поле и получить результат. Например, //name вернет поля &lt;name&gt; из всего XML:</p>
28 <p>Проблема такого подхода - уникальность полей. В документах одни и те же имена полей могут обозначать разные данные в зависимости от расположения. Поэтому используйте относительные пути только там, где уверены в возвращаемых данных. Например, в нашем примере название курса может быть заключено в &lt;title&gt;:</p>
28 <p>Проблема такого подхода - уникальность полей. В документах одни и те же имена полей могут обозначать разные данные в зависимости от расположения. Поэтому используйте относительные пути только там, где уверены в возвращаемых данных. Например, в нашем примере название курса может быть заключено в &lt;title&gt;:</p>
29 <p>Запрос //title вернет не только имена курсов, но и узел, который находится в &lt;courses&gt;:</p>
29 <p>Запрос //title вернет не только имена курсов, но и узел, который находится в &lt;courses&gt;:</p>
30 <p>Чтобы сэкономить пару секунд, разработчики опускают корневой элемент и пользуются относительными путями. Например, вместо /courses/course/name они пишут //course/name. Для практики попробуйте прошлые примеры перевести на относительные пути с помощью такого механизма.</p>
30 <p>Чтобы сэкономить пару секунд, разработчики опускают корневой элемент и пользуются относительными путями. Например, вместо /courses/course/name они пишут //course/name. Для практики попробуйте прошлые примеры перевести на относительные пути с помощью такого механизма.</p>
31 <p>Несколько примеров запросов с идентичными ответами, как и в прошлой таблице:</p>
31 <p>Несколько примеров запросов с идентичными ответами, как и в прошлой таблице:</p>
32 <h3>Предикаты</h3>
32 <h3>Предикаты</h3>
33 <p>В примерах запросов к именам возвращались имена всех найденных курсов. В некоторых ситуациях это может быть избыточно. Что делать, если хочется получить данные только по первому курсу в &lt;courses&gt;? На помощь приходят<strong>предикаты</strong>- конструкции, с помощью которых можно отфильтровать элементы по заданным условиям. </p>
33 <p>В примерах запросов к именам возвращались имена всех найденных курсов. В некоторых ситуациях это может быть избыточно. Что делать, если хочется получить данные только по первому курсу в &lt;courses&gt;? На помощь приходят<strong>предикаты</strong>- конструкции, с помощью которых можно отфильтровать элементы по заданным условиям. </p>
34 <p>Выберем ключевые слова первого курса по верстке. Для этого достаточно использовать запрос //course[1]/tags:</p>
34 <p>Выберем ключевые слова первого курса по верстке. Для этого достаточно использовать запрос //course[1]/tags:</p>
35 <p>Обратите внимание на[1]. Это предикат с таким условием: "Взять элемент по индексу 1". Попробуйте сделать запрос ко второму или третьему элементу. Достаточно поменять всего одну цифру! </p>
35 <p>Обратите внимание на[1]. Это предикат с таким условием: "Взять элемент по индексу 1". Попробуйте сделать запрос ко второму или третьему элементу. Достаточно поменять всего одну цифру! </p>
36 <p>В<em>XPath</em>индексы элементов начинаются с единицы, а не с нуля, как в принятых стандартах программирования. Если вы уже программируете, это может немного запутать.</p>
36 <p>В<em>XPath</em>индексы элементов начинаются с единицы, а не с нуля, как в принятых стандартах программирования. Если вы уже программируете, это может немного запутать.</p>
37 <p>Предикаты помогают делать точные выборки. Например, получить ссылки на русскоязычные страницы курсов. Для этого нужно получить элементы &lt;url&gt;, у которых атрибут lang равен ru. Делается это указанием атрибута и значения. Чтобы<em>XPath</em>отличил атрибут от элемента перед атрибутом указывается символ @. </p>
37 <p>Предикаты помогают делать точные выборки. Например, получить ссылки на русскоязычные страницы курсов. Для этого нужно получить элементы &lt;url&gt;, у которых атрибут lang равен ru. Делается это указанием атрибута и значения. Чтобы<em>XPath</em>отличил атрибут от элемента перед атрибутом указывается символ @. </p>
38 <p>Теперь запрос будет выглядеть так: //course/url[@lang="ru"]</p>
38 <p>Теперь запрос будет выглядеть так: //course/url[@lang="ru"]</p>
39 <p>Иногда полезно выбрать элементы, которые имеют хоть какой-то атрибут. Для этого можно использовать конструкцию //*[@*]:</p>
39 <p>Иногда полезно выбрать элементы, которые имеют хоть какой-то атрибут. Для этого можно использовать конструкцию //*[@*]:</p>
40 <p>По примеру выше видно, знак * обозначает "все/любой".</p>
40 <p>По примеру выше видно, знак * обозначает "все/любой".</p>
41 <p>Когда выбраны элементы по атрибутам, можно произвести дополнительную фильтрацию по этим значениям. Например, найдем элементы &lt;duration&gt; со значением атрибута value больше 9. Внутри предикатов используются<strong>операторы сравнения</strong>, знакомые по языкам программирования:</p>
41 <p>Когда выбраны элементы по атрибутам, можно произвести дополнительную фильтрацию по этим значениям. Например, найдем элементы &lt;duration&gt; со значением атрибута value больше 9. Внутри предикатов используются<strong>операторы сравнения</strong>, знакомые по языкам программирования:</p>
42 <ul><li>&gt; - больше</li>
42 <ul><li>&gt; - больше</li>
43 <li>&lt; - меньше</li>
43 <li>&lt; - меньше</li>
44 <li>&gt;= - больше или равно</li>
44 <li>&gt;= - больше или равно</li>
45 <li>&lt;= - меньше или равно</li>
45 <li>&lt;= - меньше или равно</li>
46 <li>= - равно</li>
46 <li>= - равно</li>
47 <li>!= - не равно</li>
47 <li>!= - не равно</li>
48 </ul><p>Запрос будет выглядеть так: //course/duration[@value &gt; 9]:</p>
48 </ul><p>Запрос будет выглядеть так: //course/duration[@value &gt; 9]:</p>
49 <p>Мы разобрались, как выбирать одно поле - это интересная, но редкая задача. Чаще разработчики обрабатывают данные по всему файлу или нескольким полям. Попробуем одновременно использовать предикат и обратиться к другим полям. Обратите внимание на два момента:</p>
49 <p>Мы разобрались, как выбирать одно поле - это интересная, но редкая задача. Чаще разработчики обрабатывают данные по всему файлу или нескольким полям. Попробуем одновременно использовать предикат и обратиться к другим полям. Обратите внимание на два момента:</p>
50 <ul><li>Предикат необязательно должен идти в конце запроса</li>
50 <ul><li>Предикат необязательно должен идти в конце запроса</li>
51 <li>Внутри предиката могут находиться новые пути, которые нужно проверить</li>
51 <li>Внутри предиката могут находиться новые пути, которые нужно проверить</li>
52 </ul><p>Мы уже знаем, как с помощью предиката отфильтровать данные по полю &lt;duration&gt;. Эту задачу мы выполняли с помощью конструкции duration[@value &gt; 9]. А теперь попробуем сделать эту конструкцию предикатом для &lt;course&gt;. Так мы получим данные о курсах с длительностью больше 9 часов: //course[duration[@value &gt; 9]]:</p>
52 </ul><p>Мы уже знаем, как с помощью предиката отфильтровать данные по полю &lt;duration&gt;. Эту задачу мы выполняли с помощью конструкции duration[@value &gt; 9]. А теперь попробуем сделать эту конструкцию предикатом для &lt;course&gt;. Так мы получим данные о курсах с длительностью больше 9 часов: //course[duration[@value &gt; 9]]:</p>
53 - <p>Можн продолжить этот запрос и получить только имена курсов. Тогда предикат будет в середине запроса, а не в его конце: //course[duration[@value &gt; 9]]/name</p>
53 + <p>Можно продолжить этот запрос и получить только имена курсов. Тогда предикат будет в середине запроса, а не в его конце: //course[duration[@value &gt; 9]]/name</p>
54 <h3>Функции</h3>
54 <h3>Функции</h3>
55 <p>В прошлых примерах запросы затрагивали теги и атрибуты. Сами данные мы не затрагивали, хотя это огромный пласт информации, по которой можно делать выборки. Для решения этой задачи используются встроенные в<em>XPath</em>функции. Они являются частью предикатов - например, @. Попробуем найти курс с названием "Основы верстки контента".</p>
55 <p>В прошлых примерах запросы затрагивали теги и атрибуты. Сами данные мы не затрагивали, хотя это огромный пласт информации, по которой можно делать выборки. Для решения этой задачи используются встроенные в<em>XPath</em>функции. Они являются частью предикатов - например, @. Попробуем найти курс с названием "Основы верстки контента".</p>
56 <p>Для поиска по тексту внутри элемента используется функция text(). Ее задача - получить текстовое значение элемента и сравнить его с условием по необходимости. Вот как будет выглядеть запрос для поиска курса с нужным именем: //course[name[text()="Основы верстки контента"]]</p>
56 <p>Для поиска по тексту внутри элемента используется функция text(). Ее задача - получить текстовое значение элемента и сравнить его с условием по необходимости. Вот как будет выглядеть запрос для поиска курса с нужным именем: //course[name[text()="Основы верстки контента"]]</p>
57 <p>Но что, если нам известно только часть названия? Для этого существует функция contains(), которая принимает два аргумента:</p>
57 <p>Но что, если нам известно только часть названия? Для этого существует функция contains(), которая принимает два аргумента:</p>
58 <ol><li>Строка, где будет производиться поиск</li>
58 <ol><li>Строка, где будет производиться поиск</li>
59 <li>Подстрока, которая будет искаться</li>
59 <li>Подстрока, которая будет искаться</li>
60 </ol><p>Для примера найдем курс, у которого в ключевых словах есть слово "Bootstrap". Функция примет текстовое значение элемента tags и найдет там слово "Bootstrap": //course[tags[contains(text(), "Bootstrap")]]</p>
60 </ol><p>Для примера найдем курс, у которого в ключевых словах есть слово "Bootstrap". Функция примет текстовое значение элемента tags и найдет там слово "Bootstrap": //course[tags[contains(text(), "Bootstrap")]]</p>
61 <p>В стандарте<em>XPath</em>существует еще несколько функций, но цель статьи - показать принципы работы тех или иных механизмов, а не дать исчерпывающую документацию по всему языку.</p>
61 <p>В стандарте<em>XPath</em>существует еще несколько функций, но цель статьи - показать принципы работы тех или иных механизмов, а не дать исчерпывающую документацию по всему языку.</p>
62 <h2>Отличия от CSS-селекторов</h2>
62 <h2>Отличия от CSS-селекторов</h2>
63 <p>Если вы писали на JavaScript, то знаете, что элементы можно искать с помощью CSS-селекторов, используя методы querySelector() или querySelectorAll(). Почему же разработчики иногда ищут элементы внутри HTML именно с помощью<em>XPath</em>?</p>
63 <p>Если вы писали на JavaScript, то знаете, что элементы можно искать с помощью CSS-селекторов, используя методы querySelector() или querySelectorAll(). Почему же разработчики иногда ищут элементы внутри HTML именно с помощью<em>XPath</em>?</p>
64 <p>Дело в концепции поиска элементов. Используя CSS, можно идти только в глубину без возможности обратиться к родительским элементам. В отличие от CSS,<em>XPath</em>позволяет в любой момент обращаться и к дочерним, и к родительским элементам.</p>
64 <p>Дело в концепции поиска элементов. Используя CSS, можно идти только в глубину без возможности обратиться к родительским элементам. В отличие от CSS,<em>XPath</em>позволяет в любой момент обращаться и к дочерним, и к родительским элементам.</p>
65 <p>Если вы хотите подробнее изучить поиск по HTML с помощью<em>XPath</em>, рекомендуем обратиться к статье<a>Introduction to using XPath in JavaScript</a>.</p>
65 <p>Если вы хотите подробнее изучить поиск по HTML с помощью<em>XPath</em>, рекомендуем обратиться к статье<a>Introduction to using XPath in JavaScript</a>.</p>
66 <p>С помощью CSS нельзя найти все элементы div, внутри которых есть ссылки - можно найти сами ссылки, но не их родителей.<em>XPath</em>позволяет это сделать простым сочетанием div[a]. Постепенно ситуация меняется: в CSS появился селектор :has(), но он поддерживается еще не всеми новыми версиями браузеров. Со временем это изменится, но пока реальность именно такая.</p>
66 <p>С помощью CSS нельзя найти все элементы div, внутри которых есть ссылки - можно найти сами ссылки, но не их родителей.<em>XPath</em>позволяет это сделать простым сочетанием div[a]. Постепенно ситуация меняется: в CSS появился селектор :has(), но он поддерживается еще не всеми новыми версиями браузеров. Со временем это изменится, но пока реальность именно такая.</p>
67 <p>Другой пример - поиск элементов по тексту внутри них. С этой задачей CSS никогда не справится, так как такой цели у него нет.<em>XPath</em>, как мы изучили, умеет это делать с помощью функции text().</p>
67 <p>Другой пример - поиск элементов по тексту внутри них. С этой задачей CSS никогда не справится, так как такой цели у него нет.<em>XPath</em>, как мы изучили, умеет это делать с помощью функции text().</p>
68 <h2>Кому нужен Xpath</h2>
68 <h2>Кому нужен Xpath</h2>
69 <p>Если коротко, Xpath нужен всем, кто работает с XML.</p>
69 <p>Если коротко, Xpath нужен всем, кто работает с XML.</p>
70 <p>Чтобы разобраться подробнее, изучим несколько примеров:</p>
70 <p>Чтобы разобраться подробнее, изучим несколько примеров:</p>
71 <p><strong>SEO-специалисты</strong>. Специалисты по продвижению часто обрабатывают большие массивы данных и вытаскивают информацию со страниц сайта.</p>
71 <p><strong>SEO-специалисты</strong>. Специалисты по продвижению часто обрабатывают большие массивы данных и вытаскивают информацию со страниц сайта.</p>
72 <p>Например, для них критичны<strong>мета-теги</strong>- дополнительная информация, в которой содержатся иконки сайтов, название страницы, описание и так далее. Эту информацию SEO-специалист может автоматически парсить с помощью запросов в<em>XPath</em>.</p>
72 <p>Например, для них критичны<strong>мета-теги</strong>- дополнительная информация, в которой содержатся иконки сайтов, название страницы, описание и так далее. Эту информацию SEO-специалист может автоматически парсить с помощью запросов в<em>XPath</em>.</p>
73 <p><strong>Тестировщики</strong>. При работе с Front-end тестировщики часто проверяют тот или иной вывод информации на странице - для этого они выбирают отдельные элементы с нужной страницы. Это можно делать через<em>XPath</em>и DevTools, встроенный в браузеры на основе<em>Chromium</em>.</p>
73 <p><strong>Тестировщики</strong>. При работе с Front-end тестировщики часто проверяют тот или иной вывод информации на странице - для этого они выбирают отдельные элементы с нужной страницы. Это можно делать через<em>XPath</em>и DevTools, встроенный в браузеры на основе<em>Chromium</em>.</p>
74 <p><strong>Разработчики</strong>. Они часто используют<strong>парсеры</strong>- это скрипты, которые ищут нужную информацию на страницах одного или нескольких сайтов. Например, мы хотим сравнить стоимость одного и того же товара в разных магазинах. Для такой задачи можно написать скрипт, который пройдется по всем нужным сайтам, сравнит цены и вернет данные. В этом случае для поиска информацию на странице можно использовать<em>XPath</em>.</p>
74 <p><strong>Разработчики</strong>. Они часто используют<strong>парсеры</strong>- это скрипты, которые ищут нужную информацию на страницах одного или нескольких сайтов. Например, мы хотим сравнить стоимость одного и того же товара в разных магазинах. Для такой задачи можно написать скрипт, который пройдется по всем нужным сайтам, сравнит цены и вернет данные. В этом случае для поиска информацию на странице можно использовать<em>XPath</em>.</p>
75 <p>Это лишь часть сценариев, в которых пригождается язык<em>XPath</em>- на самом деле, их десятки.</p>
75 <p>Это лишь часть сценариев, в которых пригождается язык<em>XPath</em>- на самом деле, их десятки.</p>
76 <h2>Заключение</h2>
76 <h2>Заключение</h2>
77 <p>В этой статье мы рассмотрели, где встречается XML и кому он может пригодиться. Мы научились составлять базовые запросы и изучили часто используемые конструкции<em>XPath</em>:</p>
77 <p>В этой статье мы рассмотрели, где встречается XML и кому он может пригодиться. Мы научились составлять базовые запросы и изучили часто используемые конструкции<em>XPath</em>:</p>
78 <ul><li>Абсолютные и относительные пути</li>
78 <ul><li>Абсолютные и относительные пути</li>
79 <li>Предикаты</li>
79 <li>Предикаты</li>
80 <li>Поиск по атрибутам</li>
80 <li>Поиск по атрибутам</li>
81 <li>Операторы сравнения</li>
81 <li>Операторы сравнения</li>
82 <li>Функции</li>
82 <li>Функции</li>
83 </ul><p>Также теперь вы знаете, что поиск по HTML с помощью<em>XPath</em>может быть эффективнее поиска с помощью CSS-селекторов.</p>
83 </ul><p>Также теперь вы знаете, что поиск по HTML с помощью<em>XPath</em>может быть эффективнее поиска с помощью CSS-селекторов.</p>
84 <p>В этой статье мы постарались дать знания, которые помогут справиться с большинством задач. Но это далеко не все возможности<em>XPath</em>- это более глубокий язык, чем представлено в статье. Как и с другими технологиями, тут важно набить руку. Чем больше вы практикуетесь, тем более точные и полезные запросы пишете.</p>
84 <p>В этой статье мы постарались дать знания, которые помогут справиться с большинством задач. Но это далеко не все возможности<em>XPath</em>- это более глубокий язык, чем представлено в статье. Как и с другими технологиями, тут важно набить руку. Чем больше вы практикуетесь, тем более точные и полезные запросы пишете.</p>