Примеры xpath-запросов к html. Применение оси preceding. Стандартные функции XPath
Примеры использования xpath из практики парсинга информации с сайтов. Приведены участки кода xpath.
Получить текст заголовока h1
//h1/text()
Получить текст заголовока с классом produnctName
//h1[@class="produnctName"]/text()
Получить значение определенного span по классу
//span[@class="price"]
Получить значение атрибута title у кнопки с классом addtocart_button
//input[@class="addtocart_button"]/@title
//a/text()
//a/@href
Изображение src
//img/@src
Изображение сразу за определенным элементом в DOM, ось following
//h1[@class="produnctName"]//following::div/img/@src
Изображение в 4 div по счету
//div/img/@src
XPath (XML Path Language) — язык запросов к элементам XML-документа. Разработан для организации доступа к частям документа XML в файлах трансформации XSLT и является стандартом консорциума W3C. XPath призван реализовать навигацию по DOM в XML.
XML имеет древовидную структуру. У элемента дерева всегда существуют потомки и предки, кроме корневого элемента, у которого предков нет, а также тупиковых элементов (листьев дерева), у которых нет потомков.
На каждом шаге пути отбираются элементы, соответствующие условиям отбора на этом шаге, и в результате обращения по пути к документу получается множество элементов, удовлетворяющих данному пути.
Функции над множествами узлов
- * — обозначает любое имя или набор символов по указанной оси, например: * — любой дочерний узел; @* — любой атрибут.
- $name — обращение к переменной, где name — имя переменной или параметра.
- — дополнительные условия выборки или, что то же самое, предикат шага адресации. Должен содержать логическое значение. Если содержит числовое, считается что это порядковый номер узла, что эквивалентно приписыванию перед этим числом выражения «position()=»
- {} — если применяется внутри тега другого языка (например HTML), то XSLT процессор рассматривает содержимое фигурных скобок как XPath.
- / — определяет уровень дерева, то есть разделяет шаги адресации
- | — объединяет результат. То есть, можно написать несколько путей разбора через знак | и в результат такого выражения войдёт всё, что будет найдено любым из этих путей.
- node-set node ()
Возвращает все узлы. Вместо этой функции часто используют заменитель "*", но, в отличие от звездочки, функция node() возвращает и текстовые узлы.
- string text ()
Возвращает набор текстовых узлов;
- node-set current ()
Возвращает множество из одного элемента, который является текущим. Если мы делаем обработку множества с условиями, то единственным способом дотянуться из этого условия до текущего элемента будет данная функция.
- number position ()
Возвращает позицию элемента в множестве. Корректно работает только в цикле
- number last ()
Возвращает номер последнего элемента в множестве. Корректно работает только в цикле
- number count (node-set)
Возвращает количество элементов в node-set.
- string name (node-set?)
Возвращает полное имя первого тега в множестве.
- string namespace-uri (node-set?)
- string local-name (node-set?)
Возвращает имя первого тега в множестве, без пространства имён.
- node-set id (object)
Находит элемент с уникальным идентификатором
Оси — это база языка XPath. Для некоторых осей существуют сокращённые обозначения.
- ancestor:: — Возвращает множество предков.
- ancestor-or-self:: — Возвращает множество предков и текущий элемент.
- attribute:: — Возвращает множество атрибутов текущего элемента. Это обращение можно заменить на «@»
- child:: — Возвращает множество потомков на один уровень ниже. Это название сокращается полностью, то есть его можно вовсе опускать.
- descendant:: — Возвращает полное множество потомков (то есть, как ближайших потомков, так и всех их потомков).
- descendant-or-self:: — Возвращает полное множество потомков и текущий элемент. Выражение «/descendant-or-self::node()/» можно сокращать до «//» . С помощью этой оси, например, можно вторым шагом организовать отбор элементов с любого узла, а не только с корневого: достаточно первым шагом взять всех потомков корневого. Например, путь «//span» отберёт все узлы span документа, независимо от их положения в иерархии, взглянув как на имя корневого, так и на имена всех его дочерних элементов, на всю глубину их вложенности.
- following:: — Возвращает необработанное множество, ниже текущего элемента.
- following-sibling:: — Возвращает множество элементов на том же уровне, следующих за текущим.
- namespace:: — Возвращает множество, имеющее пространство имён (то есть присутствует атрибут xmlns).
- parent:: — Возвращает предка на один уровень назад. Это обращение можно заменить на «..»
- preceding:: — Возвращает множество обработанных элементов исключая множество предков.
- preceding-sibling:: — Возвращает множество элементов на том же уровне, предшествующих текущему.
- self:: — Возвращает текущий элемент. Это обращение можно заменить на «.»
Xpath - это язык запросов к элементам xml или xhtml документа. Также как SQL, xpath является декларативным языком запросов. Чтобы получить интересующие данные, необходимо всего лишь создать запрос, описывающий эти данные. Всю «черную» работу за вас выполнит интерпретатор языка xpath.
Очень удобно, не правда ли? Давайте посмотри какие возможности предлагает xpath для доступа к узлам веб-страниц.
Создание запроса к узлам веб-страниц
Предлагаю вашему вниманию небольшую лабораторную работу, в ходе которой я продемонстрирую создание xpath запросов к веб-странице. Вы сможете повторить приведенные мной запросы и, самое главное, попробуете выполнить свои. Я надеюсь, что благодаря этому статья будет одинаково интересна новичкам и программистам знакомым с xpath по xml.Для лабораторной нам понадобятся:
- веб-страница xhtml;
- браузер Mozilla Firefox с дополнениями;
- firebug ;
- firePath ;
(вы можете использовать любой другой браузер с визуальной поддержкой xpath)
- немного времени.
В качестве веб-страницы для проведения эксперимента предлагаю главную страницу сайта консорциума всемирной паутины ("http://w3.org "). Именно эта организация разрабатывает языки xquery(xpath), спецификацию xhtml и многие другие стандарты интернета.
Задача
Получить из xhtml-кода главной страницы w3.org информацию о конференциях консорциума при помощи запросов xpath.Приступим к написанию xpath запросов.
Первый Xpath запрос
Открываем закладку Firepath в FireBug, выделяем с селектором элемент для анализа, нажимаем: Firepath создал xpath запрос к выбранному элементу.Если вы выделили заголовок первого события, то запрос будет таким:
После удаления лишних индексов запрос станет соответствовать всем элементам типа «заголовок».
Firepath подсвечивает элементы, которые соответствуют запросу. Вы можете в реальном времени увидеть, какие узлы документа соответствуют запросу.
Запрос для получения информации о местах проведения конференций:
.//*[@id="w3c_home_upcoming_events"]/ul/li/div/p
Так мы получим список спонсоров:
.//*[@id="w3c_home_upcoming_events"]/ul/li/div/p
Синтаксис xpath
Давайте вернемся к созданным запросам и разберемся в том, как они устроены.Рассмотрим подробно первый запрос
В этом запросе я выделил три части для демонстрации возможностей xpath. (Деление на части уловное)
Первая часть
.//
- рекурсивный спуск на ноль или более уровней иерархии от текущего контекста. В нашем случае текущий контекст это корень документа
Вторая часть
*
- любой элемент,
[@id="w3c_home_upcoming_events"]
– предикат, на основе которого осуществляем поиск узла, имеющего атрибут id равным "w3c_home_upcoming_events". Идентификаторы элементов XHTML должны быть уникальны. Поэтому запрос «любой элемент с конкретным ID» должен вернуть единственный искомый нами узел.
Мы можем заменить *
на точное имя узла div
в этом запросе
div[@id="w3c_home_upcoming_events"]
Таким образом, мы спускаемся по дереву документа до нужного нам узла div[@id="w3c_home_upcoming_events"]. Нас абсолютно не волнует, из каких узлов состоит DOM-дерево и сколько уровней иерархии осталось выше.
Третья часть
/ul/li/div/p/a
–xpath-путь до конкретного элемента. Путь состоит из шагов адресации и условия проверки узлов (ul, li и т.д.). Шаги разделяются символом " /"(косая черта).
Коллекции xpath
Не всегда удается получить доступ к интересующему узлу с помощью предиката или шагов адресации. Очень часто на одном уровне иерархии находится насколько узлов одинакового типа и необходимо выбрать «только первые» или «только вторые» узлы. Для таких случаев предусмотрены коллекции.Коллекции xpath позволяют получить доступ к элементу по его индексу. Индексы соответствуют тому порядку, в котором элементы были представлены в исходном документе. Порядковый номер в коллекциях отсчитывается от единицы.
Исходя из того, что «место проведения» всегда второй параграф после «названия конференции», получаем следующий запрос:
.//*[@id="w3c_home_upcoming_events"]/ul/li/div/p
Где p – второй элемент в наборе для каждого узла списка /ul/li/div.
Аналогично список спонсоров мы можем получить запросом:
.//*[@id="w3c_home_upcoming_events"]/ul/li/div/p
Некоторые функции хpath
В хpath существует множество функций для работы с элементами внутри коллекции. Я приведу только некоторые из них.last():
Возвращает последний элемент коллекции.
Запрос ul/li/div/p - возвратит последние параграфы для каждого узла списка «ul».
Функция first() не предусмотрена. Для доступа к первому элементу используйте индекс «1».
text():
Возвращает тестовое содержание элемента.
.//a – получаем все ссылки с текстом «Archive».
position() и mod:
position() - возвращает позицию элемента в множестве.
mod - остаток от деления.
Комбинацией данных функций можем получить:
- не четные элементы ul/li
- четные элементы: ul/li
Операции сравнения
- < - логическое «меньше»
- > - логическое «больше»
- <= - логическое «меньше либо равно»
- >= - логическое «больше либо равно»
Самостоятельно
Попробуйте получить:- четные URL ссылки из левого меню «Standards»;
- заголовки всех новостей, кроме первой с главной страницы w3c.org.
Xpath в PHP5
$dom = new DomDocument(); $dom->loadHTML($HTMLCode); $xpath = new DomXPath($dom); $_res = $xpath->query(".//*[@id="w3c_home_upcoming_events"]/ul/li/div/p/a"); foreach($_res => $obj) { echo "URL: ".$obj->getAttribute("href"); echo $obj->nodeValue; }В заключение
На простом примере мы увидели возможности xpath для доступа к узлам веб-страниц.Xpath является отраслевым стандартом для доступа к элементам xml и xhtml, xslt преобразований.
Вы можете применять его для парсинга любой html-страницы. В случае если исходный html-код содержит значительные ошибки в разметке пропустите его через
Сокращенный синтаксис XPath
Сокращения синтаксиса XPath могут быть весьма удобными. Ниже приведены правила:
Self::node() может быть сокращено как. ;
Parent::node() может быть сокращено как.. ;
Child::childname может быть сокращено как childname ;
Attribute::childname может быть сокращено как @childname ;
/descendant-or-self::node()/ может быть сокращено как // .
Например, путь расположения.//PLANET - сокращение для self::node()/descendant-or-self::node()/child::PLANET . Можно также сократить выражение предиката как , как и т.д. Работать с путями расположения XPath при помощи сокращенного синтаксиса значительно проще. В следующем списке перечислен ряд примеров путей расположения с использованием сокращенного синтаксиса:
PLANET возвращает дочерние элементы
* возвращает все дочерние элементы контекстного узла;
Text() возвращает все дочерние текстовые узлы контекстного узла;
@UNITS возвращает атрибут UNITS контекстного узла;
@* возвращает все атрибуты контекстного узла;
PLANET возвращает третьего ребенка
PLANET возвращает последнего ребенка
*/PLANET возвращает всех внуков
/PLANETS/PLANET/NAME возвращает второй элемент //PLANET возвращает всех потомков PLANETS//PLANET возвращает элементы-потомки //PLANET/NAME возвращает все элементы Возвращает сам контекстный узел; .//PLANET возвращает элементы-потомки Возвращает родителя контекстного узла; ../@UNITS возвращает атрибут UNITS родителя контекстного узла; .//.. возвращает всех родителей потомка контекстного узла и родителя контекстного узла; PLANET возвращает детей PLANET возвращает детей PLANET[@UNITS="days"] возвращает всех детей PLANET[@UNITS="days"] возвращает шестого ребенка PLANET[@COLOR and @UNITS] возвращает всех детей " //PLANET " выбирает все элементы * выбирает любой элемент *[@UNITS] выбирает первых пятерых детей контекстного узла, у которых есть атрибут UNITS . Сокращенный синтаксис
Для образцов существует два правила сокращения осей: child::childname может быть сокращено как childname; attribute::childname может быть сокращено как @childname.В следующем списке перечислен ряд примеров образцов с сокращенным синтаксисом; в конце главы вы увидите Сокращенный синтаксис предикатов
Выражения предикатов можно сокращать, опуская "position()=". Например, становится , становится и т.д. С использованием сокращенного синтаксиса применять выражения XPath в предикатах становится существенно проще. Вот ряд Числа XPath
В XPath числа хранятся в формате чисел с плавающей точкой двойной точности. В соответствии с формальным определением, числа XPath должны храниться в формате 64-разрядных чисел с плавающей точкой двойной точности IEEE 754, и все числа хранятся как числа с плавающей точкой Применение осей XPath
К этому моменту мы рассмотрели три части шагов расположения - ось, условие узла и предикат. Вы должны быть знакомы с этими элементами по проделанной нами работе с образцами выбора, но обратите внимание на ось в предыдущем примере - preceding-sibling. До сих пор Проверка выражений XPath
В пакет Xalan входит удобная программа-пример, ApplyXPath.java, позволяющая применить выражение XPath к документу и посмотреть на результат, что очень помогает при тестировании. Для запуска этого примера вам нужно будет скомпилировать ApplyXPath.java в ApplyXPath.class при Xpath - это язык запросов к элементам xml или xhtml документа. Также как SQL, xpath является декларативным языком запросов. Чтобы получить интересующие данные, необходимо всего лишь создать запрос, описывающий эти данные. Всю «черную» работу за вас выполнит интерпретатор языка xpath. Для лабораторной нам понадобятся: В качестве веб-страницы для проведения эксперимента предлагаю главную страницу сайта консорциума всемирной паутины ("http://w3.org "). Именно эта организация разрабатывает языки xquery(xpath), спецификацию xhtml и многие другие стандарты интернета. Если вы выделили заголовок первого события, то запрос будет таким: После удаления лишних индексов запрос станет соответствовать всем элементам типа «заголовок». Firepath подсвечивает элементы, которые соответствуют запросу. Вы можете в реальном времени увидеть, какие узлы документа соответствуют запросу. Запрос для получения информации о местах проведения конференций: Так мы получим список спонсоров: В этом запросе я выделил три части для демонстрации возможностей xpath. (Деление на части уловное) Первая часть Вторая часть Мы можем заменить *
на точное имя узла div
в этом запросе Таким образом, мы спускаемся по дереву документа до нужного нам узла div[@id="w3c_home_upcoming_events"]. Нас абсолютно не волнует, из каких узлов состоит DOM-дерево и сколько уровней иерархии осталось выше. Третья часть Коллекции xpath позволяют получить доступ к элементу по его индексу. Индексы соответствуют тому порядку, в котором элементы были представлены в исходном документе. Порядковый номер в коллекциях отсчитывается от единицы. Исходя из того, что «место проведения» всегда второй параграф после «названия конференции», получаем следующий запрос: Аналогично список спонсоров мы можем получить запросом: last():
text():
position() и mod:
Комбинацией данных функций можем получить: Операции сравнения
Примеры xpath-запросов к html
Очень удобно, не правда ли? Давайте посмотри какие возможности предлагает xpath для доступа к узлам веб-страниц. Создание запроса к узлам веб-страниц
Предлагаю вашему вниманию небольшую лабораторную работу, в ходе которой я продемонстрирую создание xpath запросов к веб-странице. Вы сможете повторить приведенные мной запросы и, самое главное, попробуете выполнить свои. Я надеюсь, что благодаря этому статья будет одинаково интересна новичкам и программистам знакомым с xpath по xml.
- веб-страница xhtml;
- браузер Mozilla Firefox с дополнениями;
- firebug ;
- firePath ;
(вы можете использовать любой другой браузер с визуальной поддержкой xpath)
- немного времени.Задача
Получить из xhtml-кода главной страницы w3.org информацию о конференциях консорциума при помощи запросов xpath.
Приступим к написанию xpath запросов.Первый Xpath запрос
Открываем закладку Firepath в FireBug, выделяем с селектором элемент для анализа, нажимаем: Firepath создал xpath запрос к выбранному элементу.
.//*[@id="w3c_home_upcoming_events"]/ul/li/div/p
.//*[@id="w3c_home_upcoming_events"]/ul/li/div/p Синтаксис xpath
Давайте вернемся к созданным запросам и разберемся в том, как они устроены.
Рассмотрим подробно первый запрос
.//
- рекурсивный спуск на ноль или более уровней иерархии от текущего контекста. В нашем случае текущий контекст это корень документа
*
- любой элемент,
[@id="w3c_home_upcoming_events"]
– предикат, на основе которого осуществляем поиск узла, имеющего атрибут id равным "w3c_home_upcoming_events". Идентификаторы элементов XHTML должны быть уникальны. Поэтому запрос «любой элемент с конкретным ID» должен вернуть единственный искомый нами узел.
div[@id="w3c_home_upcoming_events"]
/ul/li/div/p/a
–xpath-путь до конкретного элемента. Путь состоит из шагов адресации и условия проверки узлов (ul, li и т.д.). Шаги разделяются символом " /"(косая черта).Коллекции xpath
Не всегда удается получить доступ к интересующему узлу с помощью предиката или шагов адресации. Очень часто на одном уровне иерархии находится насколько узлов одинакового типа и необходимо выбрать «только первые» или «только вторые» узлы. Для таких случаев предусмотрены коллекции.
.//*[@id="w3c_home_upcoming_events"]/ul/li/div/p
Где p – второй элемент в наборе для каждого узла списка /ul/li/div.
.//*[@id="w3c_home_upcoming_events"]/ul/li/div/p Некоторые функции хpath
В хpath существует множество функций для работы с элементами внутри коллекции. Я приведу только некоторые из них.
Возвращает последний элемент коллекции.
Запрос ul/li/div/p - возвратит последние параграфы для каждого узла списка «ul».
Функция first() не предусмотрена. Для доступа к первому элементу используйте индекс «1».
Возвращает тестовое содержание элемента.
.//a – получаем все ссылки с текстом «Archive».
position() - возвращает позицию элемента в множестве.
mod - остаток от деления.
- не четные элементы ul/li
- четные элементы: ul/li
ul/li , ul/li - элементы списка начиная с 3го номера и наоборот. Самостоятельно
Попробуйте получить:
- четные URL ссылки из левого меню «Standards»;
- заголовки всех новостей, кроме первой с главной страницы w3c.org. Xpath в PHP5
$dom = new DomDocument();
$dom->loadHTML($HTMLCode);
$xpath = new DomXPath($dom);
$_res = $xpath->query(".//*[@id="w3c_home_upcoming_events"]/ul/li/div/p/a");
foreach($_res => $obj) {
echo "URL: ".$obj->getAttribute("href");
echo $obj->nodeValue;
}
В заключение
На простом примере мы увидели возможности xpath для доступа к узлам веб-страниц.
Xpath является отраслевым стандартом для доступа к элементам xml и xhtml, xslt преобразований.
Вы можете применять его для парсинга любой html-страницы. В случае если исходный html-код содержит значительные ошибки в разметке пропустите его через