Xpath contains примеры. Синтаксис XPath
XPath (XML Path Language) - язык запросов к элементам XML -документа. Разработан для организации доступа к частям документа XML в файлах трансформации XSLT и является стандартом консорциума W3C . XPath призван реализовать навигацию по DOM в XML . В XPath используется компактный синтаксис, отличный от принятого в XML. В 2007 году завершилась разработка версии 2.0, которая теперь является составной частью языка XQuery 1.0. В декабре 2009 года началась разработка версии 2.1, которая использует XQuery 1.1.
На данный момент, самой популярной версией является XPath 1.0. Это связано с отсутствием поддержки XPath 2.0 со стороны открытых библиотек. В частности, речь идёт о LibXML, от которой зависит поддержка языка в браузерах с одной стороны и поддержка со стороны серверного интерпретатора с другой.
XML имеет древовидную структуру. В документе всегда имеется корневой элемент (инструкция к дереву отношения не имеет). У элемента дерева всегда существуют потомки и предки, кроме корневого элемента, у которого предков нет, а также тупиковых элементов (листьев дерева), у которых нет потомков. Каждый элемент дерева находится на определенном уровне вложенности (далее - «уровень»). У элементов на одном уровне бывают предыдущие и следующие элементы.
Это очень похоже на организацию каталогов в файловой системе, и строки XPath, фактически, - пути к «файлам» - элементам.
Например, рассмотрим XHTML документ:
Первый слой блок текста в первом слое Второй слой Третий слой первый блок в третьем слое второй блок в третьем слое третий блок в третьем слое
XPath-путь /html/body/*/span[@class] (полный синтаксис имеет вид /child::html/child::body/child::*/child::span ) будет соответствовать в нём двум элементам исходного документа - первый блок в третьем слое и второй блок в третьем слое .
Путь делится на шаги адресации, которые разделяются символом «косая черта» / . Каждый шаг адресации состоит из трех частей:
- ось (в данном примере child::), это обязательная часть;
- условие проверки узлов (в данном примере это имена элементов документа html, body, span, а символ * означает элемент с любым именем), также обязательная часть;
- предикат (в данном примере attribute::class), необязательная часть, заключаемая в квадратные скобки, в которой могут содержаться оси, условия проверки, функции, операторы (+, -, и пр.).
Анализ ведется слева направо. Если первый символ это / , то путь адресации считается абсолютным (то есть от корня документа). При этом за узел контекста на первом шаге берется корневой элемент (html). Контекст - это некая точка отсчета, относительно которой рассчитывается следующий шаг адресации. Поэтому на каждом шаге адресации мы получаем новый набор узлов документа, и этот набор становится контекстом для следующего шага адресации.
На втором шаге адресации (child::body) контекстом становится html элемент. Ось child:: говорит о том, что необходимо найти все непосредственные потомки элемента html, а условие проверки body говорит о том, что в формируемый набор элементов нужно включить все узлы с именем body. В ходе второго шага адресации получаем набор узлов, состоящий всего из одного элемента body, который и становится элементом контекста для третьего шага.
Третий шаг адресации: child::* . Ось child:: собирает все непосредственные потомки элемента body, а условие проверки * говорит о том, что в формируемый набор нужно включить элементы основного типа с любым именем. В ходе этого шага получаем набор узлов, состоящий из трех элементов div и одного элемента img.
Четвёртый шаг адресации: child::span . Теперь контекстом является набор из четырёх элементов. И следующий набор узлов создается в четыре прохода (за четыре итерации). При первой итерации узлом контекста становится первый div. Согласно заданной оси child:: и правилу проверки span, в набор включаются непосредственные потомки div-а, имя которых равно span. При второй итерации в набор ничего добавлено не будет, так как у второго div нет потомков. Третья итерация добавит в набор сразу три элемента span, а четвёртая ничего не добавит, так как у элемента img нет потомков. Итак, в ходе проверки получен набор узлов, состоящий из четырёх элементов span. Это и будет контекстом для последующей обработки.
Следующего шага нет, поэтому будет производиться фильтрация отобранного набора. В этом и состоит отличие предикатов от шагов адресации. На каждом шаге адресации получаем новый набор, отталкиваясь от контекста, полученного на предыдущем шаге. В ходе же обработки предиката новый набор получается из текущего методом фильтрации, когда из набора исключаются узлы, не прошедшие условие проверки. В данном случае ось attribute:: говорит о необходимости проверить, если ли у узлов контекста атрибуты, а условие class требует оставить лишь те узлы, у которых задан атрибут с именем class. Фильтрация происходит за четыре итерации, но в окончательный набор попадают только два элемента span.
ОсиОси - это база языка XPath.
- ancestor:: - Возвращает множество предков.
- ancestor-or-self:: - Возвращает множество предков и текущий элемент.
- attribute:: - Возвращает множество атрибутов текущего элемента.
- child:: - Возвращает множество потомков на один уровень ниже.
- descendant:: - Возвращает полное множество потомков.
- descendant-or-self:: - Возвращает полное множество потомков и текущий элемент.
- following:: - Возвращает необработанное множество, ниже текущего элемента.
- following-sibling:: - Возвращает множество элементов на том же уровне, следующих за текущим.
- namespace:: - Возвращает множество, имеющее пространство имён (то есть присутствует атрибут xmlns).
- parent:: - Возвращает предка на один уровень назад.
- preceding:: - Возвращает множество обработанных элементов исключая множество предков.
- preceding-sibling:: - Возвращает множество элементов на том же уровне, предшествующих текущему.
- self:: - Возвращает текущий элемент.
Существуют сокращения для некоторых осей, например:
- attribute:: - можно заменить на «@»
- child:: - часто просто опускают
- descendant:: - можно заменить на «.//»
- parent:: - можно заменить на «..»
- self:: - можно заменить на «.»
Дополнением к базе является набор функций, которые делятся на 5 групп:
Системные функции node-set document (object, node-set?) Возвращает документ, указанный в параметре object. string format-number (number, string, string?) Форматирует число согласно образцу, указанному во втором параметре, третий параметр указывает именованный формат числа, который должен быть учтён. string generate-id (node-set?) Возвращает строку, являющуюся уникальным идентификатором. node-set key (string, object) Возвращает множество с указанным ключом (аналогично функции id для идентификаторов). string unparsed-entity-uri (string) Возвращает непроанализированный URI, если такового нет, возвращает пустую строку. boolean element-available (string) Проверяет, доступен ли элемент или множество, указанное в параметре. Параметр рассматривается как XPath. boolean function-available (string) Проверяет, доступна ли функция, указанная в параметре. Параметр рассматривается как XPath. object system-property (string) Параметры, возвращающие системные переменные, могут быть: * xsl: version - возвращает версию XSLT процессора. * xsl: vendor - возвращает производителя XSLT процессора. * xsl: vendor-url - возвращает URL, идентифицирующий производителя. Если используется неизвестный параметр, функция возвращает пустую строку. boolean lang (string) Возвращает истину, если у текущего тега имеется атрибут xml: lang, либо родитель тега имеет атрибут xml: lang и в нем указан совпадающий строке символ. Функции с множествами- * - обозначает любое имя или набор символов, @* - любой атрибут
- $name - обращение к переменной, где name - имя переменной или параметра.
- - дополнительные условия выборки
- {} - если применяется внутри тега другого языка (например HTML), то XSLT процессор рассматривает содержимое фигурных скобок как XPath.
- / - определяет уровень дерева
- or - логическое «или»
- and - логическое «и»
- = - логическое «равно»
- < ( (>) - логическое «больше»
- =) - логическое «больше либо равно»
- + - сложение
- − - вычитание
- * - умножение
- div - обычное деление (не деление нацело!)
- mod - остаток от деления
Правильно ли я понимаю, что с помощью XPath нельзя получить значение атрибута узла?
text
/root/@id
Получаем:
А получить 1 нельзя? Ведь получить text можно.
В каком смысле "где"? Это строковое значение объекта, возвращаемого при выполнении выражения XPath.
Во всяком случае Perl"овый модуль XML::LibXML и плагин XPath Tool к редактору jEdit возвращают именно это.
Понятно. В перле.
Разве XPath "где-то" работает по разному?Ага. Например,
выведут "1". Без кавычек.
Данбала[досье] Вы ничего не путаете?
System.out.println(document.getRootElement().getAttributeValue("id"));где тут xPath?
Суть то в том, что xPath выражение вида /root/@id должно вернуть по всем правилам объект типа attribute-node, который, разумеется, не есть просто текст. А уж если вы хотите с помощью xPath выражения получить текстовый узел - то, будьте добры, так ему и напишите.
Данбала[досье]
А вот "Perl"овый модуль XML::LibXML и плагин XPath Tool к редактору jEdit" выведут id="1".Да, извиняюсь, кавычки я случайно пропустил, с кавычками выведут. Но суть это не меняет.
Насчет Вы, если я правильно понимаю, ошибаетесь. Выражение Xpath вернет именно id="1" , просто потом XSLT из id="1" каким-то образом получит 1 .
А System.out.println(document.getRootElement().getAttributeValue("id")); это не XPath, это DOM , вроде?
Я же говорю о "голом" XPath, неважно, в контексте XSLT он применяется или еще где.
Суть то в том, что xPath выражение вида /root/@id должно вернуть по всем правилам объект типа attribute-node, который, разумеется, не есть просто текст. А уж если вы хотите с помощью xPath выражения получить текстовый узел - то, будьте добры, так ему и напишите. С чего бы это? А почему не результат someting.do(...).toString()?Какой такой someting.do(...).toString()? Я про XPath говорю! XPath может вернуть text(), если узел является текстовым, или node(), вне зависимости от типа. Но тип тип attribute-node не является, понятно, текстовым, соответственно, text() не работает. Вот почему не работает node() - не понимаю, но не работает.
А вы хотите ему по всем правилам выдать text-node, который также объект, т. е., разумеется, не просто текст?text-node, конечно, не текст, но это не существенно, потом уж как-нибудь прочитаем. attribute-node тоже не текст, но его мы тоже можем потом прочитать. Разница в том, что text-node содержит строго то, что мы хотели, а attribute-node - нет.
Иванов Михаил aka Ivanych[досье] Я сделал ровно вот так:
<script> testpath
В поле я ввёл соответственно: /root/@id/text() и получил значение id. Если вводить /root/@id то получается id="test" .
Иванов Михаил aka Ivanych[досье]
Какой такой someting.do(...).toString()?Примерно такой:
String xpath = ...; Node node = возвращатель_узов_по_xpath.дай_узлы(xpath); System.out.println(node.getNodeValue());
Я не знаю перл, но аналог getNodeValue() обязан в нем быть.
Иными словами, работайте не с node, а с его value.
Аааа... JavaScript... Все равно примерно также.
Что-нибудь типа:
Xxx.selectNodes(...).nodeValue
Иванов Михаил aka Ivanych[досье]
Я бы пробежался по их свойствам:
With (this.xml.documentElement){ for (var prop in selectNodes(elm.value)) alert(prop) for (var prop in selectNodes(elm.value).xml) alert(prop) }
да уже домой ухожу.
Попробую изложить мысль иначе.
text
Выражение /root вернет text-node, который в текстовом представлении будет равен text .
Выражение /root/text() вернет также text-node, который в текстовом представлении будет равен text .
Т.е. для получения содержимого текстовой ноды можно использовать оператор(или как он там называется) text() .
Выражение /root/@id вернет attribute-node, который в тестовом представлении будет равен id="1" .
Оператор text() для получения содержимого attribute-node неприменим, ибо attribute-node это не текстовая нода. Эксперимент GRAy[досье] , мне кажется, не совсем чистый, ибо я не уверен, что (elm.value) это именно текстовое представление attribute-node, а не результат последующей его обработки как в XSLT . Ну, или, может быть, MSXML действительно так делает, но у меня такого инструмента нет.
Я хочу докопаться до истины и понять, можно ли сделать так, чтобы текстовым представлением attribute-node вместо id="1" было именно 1 , по аналогии с тем, как текстовое значение text-node text можно сделать равным text при помощи оператора text().
olpa[досье]
Нет, так всё равно не выйдет.
Иванов Михаил aka Ivanych[досье]
Вы чего-то недопоняли в моём примере что и неудивительно;) - я забыл ещё один инпут, торопился...
function testpath(elm){
if (this.xml)
null;
else
this.xml = new ActiveXObject("MSXML2.DomDocument");
this.xml.load(document.getElementById("xmlf").value);
alert(this.xml.documentElement.selectNodes(elm.value).xml);
}
testpath
elm.value это текст самого xPath выражения. Можете поэкспериментировать. Хотя согласно спецификации xPath узлы атрибутов и не содержат внутри себя "настоящие" текстовые узлы, там однозначно ничего и не сказано о том, как должна вести себя функция text() в случае её применения к атрибутному узлу. Боюсь что такое поведение это инициатива MS , но мне она кажется достаточно логичной.
fetis[досье]
Я работаею с XML средствами модуля XML::LibXML (Perl). В этом модуле есть функция toString(), возвращающая текстовое значение ноды, возвращенной выражением XPath. Эта функция прекрасно работает с текстовыми узлами.
И вот возникла задача получения списка значений атрибутов. Атрибут - не текстовая нода, поэтому извлекать значение надо функцией nodeValue(), а не toString(). Соответственно, возникла мысль - а нельзя ли заставить XPath вернуть именно текстовую ноду и работать со всеми нодами единообразно.
Т.е. мой вопрос чисто академический, проблемы, повторяю, нет.
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:
Harry Potter J. K. Rowling 2005 29.99
Пример узлов в документе XML выше:
(корневой элемент) J. K. Rowling (узел) lang="en" (атрибут) Атомарные значенияАтомарные значения являются узлами, не имеющие детей или родителей. Пример атомарных значений:
J. K. Rowling "en"
ЭлементыЭлементы - это атомарные значения или узлы.
3 Отношения узлов РодительКаждый элемент и атрибут имеет одного родителя. В следующем примере элемент «книга» (book) является родителем элементов «название» (title), «автор» (author), «год» (year) и «цена» (price):
Harry Potter J K. Rowling 2005 29.99
ПотомкиУзлы элементов могут иметь ноль, один или более потомков. В следующем примере элементы «название», «автор», «год» и «цена» - они все потомки элемента книга:
Harry Potter J K. Rowling 2005 29.99
Элементы одного уровняЭто узлы, которые имеют одного и того же родителя. В следующем примере элементы «название», «автор», «год» и «цена» все являются элементами одного уровня:
Harry Potter J K. Rowling 2005 29.99
ПредкиРодитель узла, родитель родителя узла и т.д. В следующем примере предки элемента «название» (title) - это элементы «книга» (book) и «книжный магазин» (bookstore):
Harry Potter J K. Rowling 2005 29.99
ПотомкиДети узла, дети детей узла и т.д. В следующем примере потомками элемента «книжный магазин» являются элементы «книга», «название», «автор», «год» и «цена»:
Harry Potter J K. Rowling 2005 29.99
4 Синтаксис XPathXPath использует выражения пути для выбора узлов или множества узлов в документе XML. Узел можно выбрать, следуя пути или по шагам. Мы будем использовать следующий XML-документ в приведённых ниже примерах.
Harry Potter 29.99 Learning XML 39.95
Выбор узловС помощью выражений XPath для выбора узлов в документе XML можно выбрать узел, следуя пути или шагам. Самые полезные выражения пути перечислены ниже:
В приведенной ниже таблице перечислены некоторые пути выражения и результат выполнения выражения:
bookstore | Выбирает все узлы с именем "bookstore" |
/bookstore | Выбирает корневой элемент книжного магазина Примечание: Если путь начинается с косой черты (/), он всегда представляет собой абсолютный путь к элементу! |
bookstore/book | Выбирает все элементы «книга» (book), которые являются потомками элемента «книжный магазин» (bookstore) |
//book | Выбирает все элементы «книга» независимо от того, где они находятся в документе |
bookstore//book | Выбирает все элементы «книга», которые являются потомком элемента «книжный магазин», независимо от того, где они находятся под элементом «книжный магазин» |
//@lang | Выбирает все атрибуты, которые называются "lang" |
Предикаты используются для поиска специфического узла или узла, который содержит специфическое значение. Предикаты всегда обрамляются квадратными скобками. В приведённой ниже таблице перечислены некоторые выражения пути с предикатами, и результат выражения:
/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 документ далее в примере.
Harry Potter 29.99 Learning XML 39.95
Оси определяют наборы узлов, относительно текущего узла.
ancestor | Выбирает всех предков (родителей, прародителей и т.д.) текущего узла |
ancestor-or-self | Выбирает всех предков (родителей, прародителей и т.д.) текущего узла и сам текущий узел |
attribute | |
child | |
descendant | Выбирает всех потомков (детей, внуков и т.д.) текущего узла |
descendant-or-self | Выбирает всех потомков (детей, внуков и т.д.) текущего узла и сам текущий узел |
following | Выбирает всё в документе после закрытия тэга текущего узла |
following-sibling | Выбирает все узлы одного уровня после текущего узла |
namespace | Выбирает все узлы в данном пространстве имён (namespace) текущего узла |
parent | Выбирает родителя текущего узла |
preceding | Выбирает все узлы, которые появляются перед текущим узлом в документе, за исключением предков, узлов атрибутов и узлы пространства имён |
preceding-sibling | Выбирает всех братьев и сестёр до текущего узла |
self | Выбирает текущий узел |
Путь определения местоположения может быть абсолютным или относительным. Абсолютный путь расположения начинается с косой черты (/), а относительный - нет. В обоих случаях путь выборки состоит из одного или нескольких шагов, разделённых косой чертой:
Абсолютный путь расположения:
/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) через один уровень от текущего узла |
Выражения XPath возвращают как набор узлов, строки, булевы или числовые значения. Ниже представлен список операторов, используемых в выражениях XPath:
| | Вычисляет два набора узлов | //book | //cd |
+ | Сложение | 6 + 4 |
- | Вычитание | 6 - 4 |
* | Умножение | 6 * 4 |
div | Деление | 8 div 4 |
= | Равенство | price=9.80 |
!= | Неравенство | price!=9.80 |
< | Меньше, чем | price9.80 |
>= | Больше или равно | price≤9.80 |
or | Или | price=9.80 or price=9.70 |
and | И | price>9.00 and price35
Следующий пример выбирает все узлы с ценами выше 35: /bookstore/book/price Выбор узлов заголовков с ценой >35Следующий пример выбирает все узлы заголовков с ценой выше 35: /bookstore/book/title Примеры использования 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 имеет древовидную структуру. У элемента дерева всегда существуют потомки и предки, кроме корневого элемента, у которого предков нет, а также тупиковых элементов (листьев дерева), у которых нет потомков. На каждом шаге пути отбираются элементы, соответствующие условиям отбора на этом шаге, и в результате обращения по пути к документу получается множество элементов, удовлетворяющих данному пути. Функции над множествами узлов
Возвращает все узлы. Вместо этой функции часто используют заменитель "*", но, в отличие от звездочки, функция node() возвращает и текстовые узлы.
Возвращает набор текстовых узлов;
Возвращает множество из одного элемента, который является текущим. Если мы делаем обработку множества с условиями, то единственным способом дотянуться из этого условия до текущего элемента будет данная функция.
Возвращает позицию элемента в множестве. Корректно работает только в цикле
Возвращает номер последнего элемента в множестве. Корректно работает только в цикле
Возвращает количество элементов в node-set.
Возвращает полное имя первого тега в множестве.
Возвращает имя первого тега в множестве, без пространства имён.
Находит элемент с уникальным идентификатором Оси — это база языка XPath. Для некоторых осей существуют сокращённые обозначения.
Поделиться:
|