Введение в XPath
2026-02-26 18:17 Diff

Язык разметки XML с самого первого стандарта окружает пользователей компьютеров. Таблицы в Excel, выгрузки из интернет-магазинов, RSS-ленты с новостями — все это основано на XML. Хоть визуальное отображение отличается на устройствах и в программах, но в основе всегда лежит единый формат.

Внутри XML-файла может находиться огромное количество информации, поэтому и встает вопрос о перемещении и выборке внутри документа. Как это сделать быстро? Какие средства применять, чтобы в интернет-магазине найти нужный товар из десятков тысяч других? Для навигации и поиска внутри XML используется язык запросов XPath.

В этой статье разберем:

  • для кого может быть полезен XPath
  • базовые конструкции языка для поиска информации в XML
  • чем XPath отличается от CSS-селекторов при поиске в HTML

Содержание

Синтаксис XPath

Для начала создадим базовый пример XML, с которым и будем работать весь урок. Например, список курсов по верстке на Хекслете в XML будет выглядеть так:

Это учебный пример, но для отработки навыков XPath подойдет и любой другой XML. Принципы XPath сохранятся при любой структуре файла, потому что по стандарту XML можно использовать элементы с произвольными тегами.

Для тестирования результата подойдут такие онлайн-сервисы, как:

Абсолютные пути

Самый простой запрос состоит из обращения к корневому элементу. Для этого достаточно выполнить запрос /courses. Нам вернется XML в почти таком же виде, что и в примере выше. Обратите внимание на строку <?xml version="1.0" encoding="UTF-8"?>. Она отличается, потому что элемент не внутри <courses>:

В качестве результата XPath возвращает узлы XML-документа.

Продолжим цепочку и обратимся к описанию из элемента <description>. Для этого добавим в запрос путь к description: /courses/description. Результатом выполнения станет:

Путь, который строится от корневого элемента, называется абсолютным. Используем схему из прошлого запроса и обратимся к любому элементу внутри XML.

Попробуем обратиться к имени курса. В этом случае вернется поле <name> из всех курсов. Запрос /courses/course/name вернет:

Вот список некоторых базовых запросов и их результат:

Относительные пути

Прошлые запросы строились с помощью абсолютных путей — то есть мы указывали полный путь до информации. Бывают ситуации, когда полный путь не подходит: например, мы хотим обраться к какому-то уникальному полю или не знаем полный путь. В этом случае можно использовать относительный путь — он произведет поиск по всему XML и вернет узлы, подходящие под запрос.

Чтобы записать относительный путь, нужно использовать конструкцию //. После нее можно написать любое поле и получить результат. Например, //name вернет поля <name> из всего XML:

Проблема такого подхода — уникальность полей. В документах одни и те же имена полей могут обозначать разные данные в зависимости от расположения. Поэтому используйте относительные пути только там, где уверены в возвращаемых данных. Например, в нашем примере название курса может быть заключено в <title>:

Запрос //title вернет не только имена курсов, но и узел, который находится в <courses>:

Чтобы сэкономить пару секунд, разработчики опускают корневой элемент и пользуются относительными путями. Например, вместо /courses/course/name они пишут //course/name. Для практики попробуйте прошлые примеры перевести на относительные пути с помощью такого механизма.

Несколько примеров запросов с идентичными ответами, как и в прошлой таблице:

Предикаты

В примерах запросов к именам возвращались имена всех найденных курсов. В некоторых ситуациях это может быть избыточно. Что делать, если хочется получить данные только по первому курсу в <courses>? На помощь приходят предикаты — конструкции, с помощью которых можно отфильтровать элементы по заданным условиям. 

Выберем ключевые слова первого курса по верстке. Для этого достаточно использовать запрос //course[1]/tags:

Обратите внимание на[1]. Это предикат с таким условием: «Взять элемент по индексу 1». Попробуйте сделать запрос ко второму или третьему элементу. Достаточно поменять всего одну цифру! 

В XPath индексы элементов начинаются с единицы, а не с нуля, как в принятых стандартах программирования. Если вы уже программируете, это может немного запутать.

Предикаты помогают делать точные выборки. Например, получить ссылки на русскоязычные страницы курсов. Для этого нужно получить элементы <url>, у которых атрибут lang равен ru. Делается это указанием атрибута и значения. Чтобы XPath отличил атрибут от элемента перед атрибутом указывается символ @. 

Теперь запрос будет выглядеть так: //course/url[@lang="ru"]

Иногда полезно выбрать элементы, которые имеют хоть какой-то атрибут. Для этого можно использовать конструкцию //*[@*]:

По примеру выше видно, знак * обозначает «все/любой».

Когда выбраны элементы по атрибутам, можно произвести дополнительную фильтрацию по этим значениям. Например, найдем элементы <duration> со значением атрибута value больше 9. Внутри предикатов используются операторы сравнения, знакомые по языкам программирования:

  • > — больше
  • < — меньше
  • >= — больше или равно
  • <= — меньше или равно
  • = — равно
  • != — не равно

Запрос будет выглядеть так: //course/duration[@value > 9]:

Мы разобрались, как выбирать одно поле — это интересная, но редкая задача. Чаще разработчики обрабатывают данные по всему файлу или нескольким полям. Попробуем одновременно использовать предикат и обратиться к другим полям. Обратите внимание на два момента:

  • Предикат необязательно должен идти в конце запроса
  • Внутри предиката могут находиться новые пути, которые нужно проверить

Мы уже знаем, как с помощью предиката отфильтровать данные по полю <duration>. Эту задачу мы выполняли с помощью конструкции duration[@value > 9]. А теперь попробуем сделать эту конструкцию предикатом для <course>. Так мы получим данные о курсах с длительностью больше 9 часов: //course[duration[@value > 9]]:

Можно продолжить этот запрос и получить только имена курсов. Тогда предикат будет в середине запроса, а не в его конце: //course[duration[@value > 9]]/name

Функции

В прошлых примерах запросы затрагивали теги и атрибуты. Сами данные мы не затрагивали, хотя это огромный пласт информации, по которой можно делать выборки. Для решения этой задачи используются встроенные в XPath функции. Они являются частью предикатов — например, @. Попробуем найти курс с названием «Основы верстки контента».

Для поиска по тексту внутри элемента используется функция text(). Ее задача — получить текстовое значение элемента и сравнить его с условием по необходимости. Вот как будет выглядеть запрос для поиска курса с нужным именем: //course[name[text()="Основы верстки контента"]]

Но что, если нам известно только часть названия? Для этого существует функция contains(), которая принимает два аргумента:

  1. Строка, где будет производиться поиск
  2. Подстрока, которая будет искаться

Для примера найдем курс, у которого в ключевых словах есть слово «Bootstrap». Функция примет текстовое значение элемента tags и найдет там слово «Bootstrap»: //course[tags[contains(text(), "Bootstrap")]]

В стандарте XPath существует еще несколько функций, но цель статьи — показать принципы работы тех или иных механизмов, а не дать исчерпывающую документацию по всему языку.

Отличия от CSS-селекторов

Если вы писали на JavaScript, то знаете, что элементы можно искать с помощью CSS-селекторов, используя методы querySelector() или querySelectorAll(). Почему же разработчики иногда ищут элементы внутри HTML именно с помощью XPath?

Дело в концепции поиска элементов. Используя CSS, можно идти только в глубину без возможности обратиться к родительским элементам. В отличие от CSS, XPath позволяет в любой момент обращаться и к дочерним, и к родительским элементам.

Если вы хотите подробнее изучить поиск по HTML с помощью XPath, рекомендуем обратиться к статье Introduction to using XPath in JavaScript.

С помощью CSS нельзя найти все элементы div, внутри которых есть ссылки — можно найти сами ссылки, но не их родителей. XPath позволяет это сделать простым сочетанием div[a]. Постепенно ситуация меняется: в CSS появился селектор :has(), но он поддерживается еще не всеми новыми версиями браузеров. Со временем это изменится, но пока реальность именно такая.

Другой пример — поиск элементов по тексту внутри них. С этой задачей CSS никогда не справится, так как такой цели у него нет. XPath, как мы изучили, умеет это делать с помощью функции text().

Кому нужен Xpath

Если коротко, Xpath нужен всем, кто работает с XML.

Чтобы разобраться подробнее, изучим несколько примеров:

SEO-специалисты. Специалисты по продвижению часто обрабатывают большие массивы данных и вытаскивают информацию со страниц сайта.

Например, для них критичны мета-теги — дополнительная информация, в которой содержатся иконки сайтов, название страницы, описание и так далее. Эту информацию SEO-специалист может автоматически парсить с помощью запросов в XPath.

Тестировщики. При работе с Front-end тестировщики часто проверяют тот или иной вывод информации на странице — для этого они выбирают отдельные элементы с нужной страницы. Это можно делать через XPath и DevTools, встроенный в браузеры на основе Chromium.

Разработчики. Они часто используют парсеры — это скрипты, которые ищут нужную информацию на страницах одного или нескольких сайтов. Например, мы хотим сравнить стоимость одного и того же товара в разных магазинах. Для такой задачи можно написать скрипт, который пройдется по всем нужным сайтам, сравнит цены и вернет данные. В этом случае для поиска информацию на странице можно использовать XPath.

Это лишь часть сценариев, в которых пригождается язык XPath — на самом деле, их десятки.

Заключение

В этой статье мы рассмотрели, где встречается XML и кому он может пригодиться. Мы научились составлять базовые запросы и изучили часто используемые конструкции XPath:

  • Абсолютные и относительные пути
  • Предикаты
  • Поиск по атрибутам
  • Операторы сравнения
  • Функции

Также теперь вы знаете, что поиск по HTML с помощью XPath может быть эффективнее поиска с помощью CSS-селекторов.

В этой статье мы постарались дать знания, которые помогут справиться с большинством задач. Но это далеко не все возможности XPath — это более глубокий язык, чем представлено в статье. Как и с другими технологиями, тут важно набить руку. Чем больше вы практикуетесь, тем более точные и полезные запросы пишете.