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").value $x("string(//tr[@data-place]/@data-place)")
Примеры
//div //a //*/ancestor-or-self::buttonБазовый синтаксис
Пути
. # текущий контекст.// # рекурсивный спуск (на ноль или более уровней от текущего контекста) /html/body # абсолютный путь table//a # относительный путь a # путь относительно текущего контекста //* # все в текущем контексте li/*/a # ссылки, являющиеся "внуками" для li //a|//button # ссылки и кнопки (объединение двух множеств узлов)Отношения
a/i/parent::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() # получить первый текстовый узелПозиция элемента
a # первый элемент a # последний элемент a[i] # вторая ссылка, которая содержит элемент a # Первые 3 ссылки ul # список (UL), первый элемент которого содержит значение "OK" tr # не четные элементы tr # четные элементы p/text() # второй текстовый узелАтрибуты и фильтры
Указывает на фильтрацию элементов
Input[@type=text] # атрибуты задаются с префиксом @ input[@class="OK"] # p # параграфы без атрибутов *[@style] # все элементы с атрибутом style a[. = "OK"] # ссылки со значением "OK" a/@id # идентификаторы ссылок a/@* # все атрибуты ссылок a[@id and @rel] # ссылки, которые содержат атрибуты id и rel a[@id][@rel] # то же самое a # ссылки содержат элемент или
Функции
Базовые функции Xpath - http://www.w3.org/TR/xpath/#corelib
Name() # возвращает имя элемента string(val) string(a/@id) # получить значение атрибута substring(val, from, to) substring(@id, 1, 6) # вырезать часть строки substring-after(val, from) substring-after(@id, "FROM") substring-before string-length() # возвращает число символов в строке count() # возвращает количество элементов concat() normalize-space() # аналог trim, удаляет пробелы Пример: starts-with() contains() translate("bar","abc","ABC") # BAr
Математика
//p[ position() = floor(last() div 2 + 0.5) or position() = ceiling(last() div 2 + 0.5) ] //tr position() # div # деление mod # остаток от деления ceiling() # минимальное целое floor() # максимальное целое round() sum()Группирование
(table/tbody/tr) # последняя строкаСоставные условия фильтрации
XPath используется для навигации по элементам и атрибутам XML-документа. XPath является одним из основных элементов в стандарте XSLT консорциума W3C.
1 Что такое XPath
Выражения XPath
XPath использует выражения пути для выбора отдельных узлов или набора узлов в документе XML. Эти выражения очень похожи на выражения, которые вы видите, когда работаете с традиционной файловой системой компьютера.
Стандартные функции XPath
XPath включает в себя более 100 встроенных функций. Есть функции для строковых и числовых значений, даты и времени, сравнения узлов и манипулирования QName, управления последовательностями, булевых значений, и многое другое.
XPath используется в XSLT
XPath является одним из основных элементов в стандарте XSLT. Без знания XPath вы не будете иметь возможность создавать XSLT-документы.
2 Терминология XPath
Узлы
В XPath существует семь видов узлов: элемент, атрибут, текст, пространство имён, инструкции обработки, комментарии и узлы документа. XML-документы обрабатываются в виде деревьев узлов. Верхний элемент дерева называется корневым элементом. Посмотрите на следующий документ XML:
Пример узлов в документе XML выше:
Атомарные значения
Атомарные значения являются узлами, не имеющие детей или родителей. Пример атомарных значений:
J. K. Rowling "en"
Элементы
Элементы - это атомарные значения или узлы.
3 Отношения узлов
Родитель
Каждый элемент и атрибут имеет одного родителя. В следующем примере элемент «книга» (book) является родителем элементов «название» (title), «автор» (author), «год» (year) и «цена» (price):
Потомки
Узлы элементов могут иметь ноль, один или более потомков. В следующем примере элементы «название», «автор», «год» и «цена» - они все потомки элемента книга:
Элементы одного уровня
Это узлы, которые имеют одного и того же родителя. В следующем примере элементы «название», «автор», «год» и «цена» все являются элементами одного уровня:
Предки
Родитель узла, родитель родителя узла и т.д. В следующем примере предки элемента «название» (title) - это элементы «книга» (book) и «книжный магазин» (bookstore):
Потомки
Дети узла, дети детей узла и т.д. В следующем примере потомками элемента «книжный магазин» являются элементы «книга», «название», «автор», «год» и «цена»:
4 Синтаксис XPath
XPath использует выражения пути для выбора узлов или множества узлов в документе XML. Узел можно выбрать, следуя пути или по шагам. Мы будем использовать следующий XML-документ в приведённых ниже примерах.
Выбор узлов
С помощью выражений XPath для выбора узлов в документе XML можно выбрать узел, следуя пути или шагам. Самые полезные выражения пути перечислены ниже:
В приведенной ниже таблице перечислены некоторые пути выражения и результат выполнения выражения:
Выражение XPath | Результат |
---|---|
bookstore | Выбирает все узлы с именем "bookstore" |
/bookstore | Выбирает корневой элемент книжного магазина Примечание: Если путь начинается с косой черты (/), он всегда представляет собой абсолютный путь к элементу! |
bookstore/book | Выбирает все элементы «книга» (book), которые являются потомками элемента «книжный магазин» (bookstore) |
//book | Выбирает все элементы «книга» независимо от того, где они находятся в документе |
bookstore//book | Выбирает все элементы «книга», которые являются потомком элемента «книжный магазин», независимо от того, где они находятся под элементом «книжный магазин» |
//@lang | Выбирает все атрибуты, которые называются "lang" |
Предикаты
Предикаты используются для поиска специфического узла или узла, который содержит специфическое значение. Предикаты всегда обрамляются квадратными скобками. В приведённой ниже таблице перечислены некоторые выражения пути с предикатами, и результат выражения:
Выражения XPath | Результат |
---|---|
/bookstore/book | Выбирает первый элемент «книга», который является потомком элемента «книжный магазин».
Примечание: В IE 5,6,7,8,9 первый узел имеет индекс , но в соответствии с рекомендациями W3C, это . Для решения этой проблемы в IE, задаётся опция "SelectionLanguage" для XPath: На JavaScript: xml .setProperty("SelectionLanguage", "XPath"); |
/bookstore/book | Выбирает последний элемент «книга» (book), который является дочерним элементом элемента «книжный магазин» (bookstore) |
/bookstore/book | Выбирает предпоследний элемент «книга», который является дочерним элементом элемента «книжный магазин» |
/bookstore/book | Выбор первых двух элементов «книга», которые являются потомками элемента «книжный магазин» |
//title[@lang] | Выбирает все элементы «название» (title), которые имеют атрибут с именем "lang" |
//title[@lang="en"] | Выбирает все элементы «название», которые имеют атрибут «язык» со значением "en" |
/bookstore/book | Выбирает все элементы «книга» после элемента «книжный магазин», которые имеют элемент «цена» со значением больше, чем 35.00 |
/bookstore/book/title | Выбирает все элементы «название» книги элемента «книжный магазин», которые имеют элемент «цена» со значением больше, чем 35.00 |
Выбор неизвестных узлов
Специальные символы XPath могут использоваться для выбора неизвестных XML узлов.
В приведённой ниже таблице мы перечислили некоторые пути выражения и результаты выражений:
Выбор нескольких путей
С помощью оператора | в выражениях XPath вы можете выбрать несколько путей. В таблице ниже перечислены несколько выражений путей и результаты их применения:
5 Оси XPath
Мы будем использовать следующий XML документ далее в примере.
Оси определяют наборы узлов, относительно текущего узла.
Название оси | Результат |
---|---|
ancestor | Выбирает всех предков (родителей, прародителей и т.д.) текущего узла |
ancestor-or-self | Выбирает всех предков (родителей, прародителей и т.д.) текущего узла и сам текущий узел |
attribute | |
child | |
descendant | Выбирает всех потомков (детей, внуков и т.д.) текущего узла |
descendant-or-self | Выбирает всех потомков (детей, внуков и т.д.) текущего узла и сам текущий узел |
following | Выбирает всё в документе после закрытия тэга текущего узла |
following-sibling | Выбирает все узлы одного уровня после текущего узла |
namespace | Выбирает все узлы в данном пространстве имён (namespace) текущего узла |
parent | Выбирает родителя текущего узла |
preceding | Выбирает все узлы, которые появляются перед текущим узлом в документе, за исключением предков, узлов атрибутов и узлы пространства имён |
preceding-sibling | Выбирает всех братьев и сестёр до текущего узла |
self | Выбирает текущий узел |
6 Выражения пути выборки
Путь определения местоположения может быть абсолютным или относительным. Абсолютный путь расположения начинается с косой черты (/), а относительный - нет. В обоих случаях путь выборки состоит из одного или нескольких шагов, разделённых косой чертой:
Абсолютный путь расположения:
/step/step/...
Относительный путь выборки расположения:
Step/step/...
Каждый шаг оценивается по узлам в текущем наборе узлов. Шаг состоит из:
- ось (определяет древовидную связь между выбранными узлами и текущим узлом);
- проверка узла (идентифицирует узел в пределах оси);
- ноль или более предикатов (для дальнейшего уточнения выбранного набор узлов)
Синтаксис шага выборки такой:
Axisname::nodetest имяОси::проверкаУзла[предиктор]
Пример | Результат |
---|---|
child::book | Выбирает все узлы «книга» (book), которые являются потомками текущего узла |
attribute::lang | Выбирает атрибут «язык» (lang) текущего узла |
child::* | Выбирает всех потомков текущего узла |
attribute::* | Выбирает все атрибуты текущего узла |
child::text() | Выбирает все текстовые узлы текущего узла |
child::node() | Выбирает всех ближайших потомков текущего узла |
descendant::book | Выбирает всех потомков текущего узла |
ancestor::book | Выбирает всех предков «книга» (books) текущего узла |
ancestor-or-self::book | Выбирает всех предков «книга» (book) текущего узла - и текущий узел, если он также «книга» (book) |
child::*/child::price | Выбирает все потомки «цена» (price) через один уровень от текущего узла |
7 Операторы XPath
Выражения XPath возвращают как набор узлов, строки, булевы или числовые значения. Ниже представлен список операторов, используемых в выражениях XPath:
Оператор | Описание | Пример |
---|---|---|
| | Вычисляет два набора узлов | //book | //cd |
+ | Сложение | 6 + 4 |
- | Вычитание | 6 - 4 |
* | Умножение | 6 * 4 |
div | Деление | 8 div 4 |
= | Равенство | price=9.80 |
!= | Неравенство | price!=9.80 |
< | Меньше, чем | price<9.80 |
<= | Меньше или равно | price≤9.80 |
> | Больше, чем | price>9.80 |
>= | Больше или равно | price≤9.80 |
or | Или | price=9.80 or price=9.70 |
and | И | price>9.00 and price<9.90 |
mod | Остаток от деления | 5 mod 2 |
8 Примеры XPath
Давайте рассмотрим базовый синтаксис XPath на нескольких примерах. Мы будем использовать следующий XML документ "books.xml" в примерах ниже:
Загрузка XML документа
Используйте XMLHttpRequest для загрузки XML документов, который поддерживается большинством современных браузеров:
Var xmlhttp=new XMLHttpRequest()
Код для устаревших браузеров Microsoft (IE 5 и 6):
Var xmlhttp=new ActiveXObject("Microsoft.XMLHTTP")
Выбор узлов
К сожалению, работа с XPath в Internet Explorer и в других браузерах может отличаться. В наших примерах мы будем использовать код, который должен работать в большинстве браузеров. Internet Explorer использует метод "selectNodes()" для выбора узлов XML документа:
XmlDoc.selectNodes(xpath);
Firefox, Chrome, Opera и Safari используют метод evaluate() для выбора узлов из XML документа:
XmlDoc.evaluate(xpath, xmlDoc, null, XPathResult.ANY_TYPE, null);
Выбор всех заглавий
Следующий пример выбирает все узлы заголовков:
/bookstore/book/title
Выбор заголовка первой книги
Следующий пример выбирает заголовок первого узла «книга» после элемента «книжный магазин» (bookstore):
/bookstore/book/title
Выбор всех цен
Следующий пример выбирает текст всех узлов «цена» (price):
/bookstore/book/price
Выбирает узлы с ценой >35
Следующий пример выбирает все узлы с ценами выше 35:
/bookstore/book/price
Выбор узлов заголовков с ценой >35
Следующий пример выбирает все узлы заголовков с ценой выше 35:
/bookstore/book/title
Для выбора узлов и наборов узлов в XML документе XPath использует выражения путей. Узел выбирается следуя по заданному пути или по, так называемым, шагам.
Пример XML документа
Для демонстрации синтаксиса XPath будет использоваться следующий XML документ:
Выбор узлов
Чтобы выбрать узлы в XML документе, XPath использует выражения пути. Узел выбирается следуя по заданному пути. Наиболее полезные выражения пути:
В следующей таблице приводятся некоторые выражения XPath, позволяющие сделать некоторые выборки по демонстрационному XML документу:
Выражение XPath | Результат |
---|---|
messages | Выбирает все узлы с именем "messages" |
/messages | Выбирает корневой элемент сообщений Примечание : Если путь начинается с косой черты (/), то он всегда представляет абсолютный путь к элементу! |
messages/note | Выбирает все элементы note, являющиеся потомками элемента messages |
//note | Выбирает все элементы note независимо от того, где в документе они находятся |
messages//note | Выбирает все элементы note, являющиеся потомками элемента messages независимо от того, где они находятся от элемента messages |
//@date | Выбирает все атрибуты с именем date |
Предикаты
Предикаты позволяют найти конкретный узел или узел с конкретным значением.
Предикаты всегда заключаются в квадратные скобки.
В следующей таблице приводятся некоторые выражения XPath с предикатами, позволяющие сделать выборки по демонстрационному XML документу:
Выражение XPath | Результат |
---|---|
/messages/note | Выбирает первый элемент note, который является прямым потомком элемента messages. Примечание : В IE 5,6,7,8,9 первым узлом будет , однако согласно W3C это должен быть . Чтобы решить эту проблему в IE, нужно установить опцию SelectionLanguage в значение XPath. В JavaScript: xml.setProperty("SelectionLanguage","XPath"); |
/messages/note | Выбирает последний элемент note, который является прямым потомком элемента messages. |
/messages/note | Выбирает предпоследний элемент note, который является прямым потомком элемента messages. |
/messages/note | Выбирает все элементы heading, у которых есть атрибут date |
//heading[@date="10/01/2008"] | Выбирает все элементы heading, у которых есть атрибут date со значением "10/01/2008" |
Выбор неизвестных заранее узлов
Чтобы найти неизвестные заранее узлы XML документа, XPath позволяет использовать специальные символы.
В следующей таблице приводятся некоторые выражения XPath со спецсимволами, позволяющие сделать выборки по демонстрационному XML документу:
Выбор нескольких путей
Использование оператора | в выражении XPath позволяет делать выбор по нескольким путям.
В следующей таблице приводятся некоторые выражения XPath, позволяющие сделать выборки по демонстрационному XML документу.
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-код содержит значительные ошибки в разметке пропустите его через