Язык XPath и его применение для доступа к элементам XML.
XPath (XML Path Language) — язык запросов к элементам XML-документа. Разработан для организации доступа к частям документа XML в файлах трансформации XSLT и является стандартом консорциума W3C. XPath призван реализовать навигацию по DOM в XML.
<html> <body> <div>Первый слой <span>блок текста в первом слое</span> </div> <div>Второй слой</div> <div>Третий слой <span class="text">первый блок в третьем слое</span> <span class="text">второй блок в третьем слое</span> <span>третий блок в третьем слое</span> </div> <img /> </body></html>XPath-путь /html/body/*/span[@class] (полный синтаксис имеет вид /child::html/child::body/child::*/child::span[attribute::class]) будет соответствовать в нём двум элементам исходного документа - <span class="text">первый блок в третьем слое</span> и <span class="text">второй блок в третьем слое</span>.
Путь делится на шаги адресации, которые разделяются символом "косая черта" / . Каждый шаг адресации состоит из трех частей:
§ ось (в данном примере child::), это обязательная часть;
§ условие проверки узлов (в данном примере это имена элементов документа html, body, span, а символ * означает элемент с любым именем), также обязательная часть;
§ предикат (в данном примере attribute::class), необязательная часть, заключаемая в квадратные скобки, в которой могут содержаться оси, условия проверки, функции, операторы (+, -, <, > и пр.).
Анализ ведется слева направо. Если первый символ это / , то путь адресации считается абсолютным (т.е. от корня документа). При этом за узел контекста на первом шаге берется корневой элемент (html). Контекст — это некая точка отсчета, относительно которой рассчитывается следующий шаг адресации. Поэтому на каждом шаге адресации мы получаем новый набор узлов документа, и этот набор становится контекстом для следующего шага адресации.
На втором шаге адресации (child::body) контекстом становится html элемент. Ось child:: говорит о том, что необходимо найти все непосредственные потомки элемента html, а условие проверки body говорит о том, что в формируемый набор элементов нужно включить все узлы с именем body. Третий шаг адресации: child::* . Ось child:: собирает все непосредственные потомки элемента body, а условие проверки * говорит о том, что в формируемый набор нужно включить элементы основного типа с любым именем. В ходе этого шага получаем набор узлов, состоящий из трех элементов div и одного элемента img. Четвёртый шаг адресации: child::span . Теперь контекстом является набор из четырёх элементов. И следующий набор узлов создается в четыре прохода (за четыре итерации). При первой итерации узлом контекста становится первый div. Согласно заданной оси child:: и правилу проверки span, в набор включаются непосредственные потомки div-а, имя которых равно span. При второй итерации в набор ничего добавлено не будет, так как у второго div нет потомков. Третья итерация добавит в набор сразу три элемента span, а четвёртая ничего не добавит, так как у элемента img нет потомков. Итак, в ходе проверки получен набор узлов, состоящий из четырёх элементов span. Это и будет контекстом для последующей обработки.
Следующего шага нет, поэтому будет производиться фильтрация отобранного набора. В этом и состоит отличие предикатов от шагов адресации. На каждом шаге адресации получаем новый набор, отталкиваясь от контекста, полученного на предыдущем шаге. В ходе же обработки предиката новый набор получается из текущего методом фильтрации, когда из набора исключаются узлы, не прошедшие условие проверки. В данном случае ось attribute:: говорит о необходимости проверить, если ли у узлов контекста атрибуты, а условие class требует оставить лишь те узлы, у которых задан атрибут с именем class. Фильтрация происходит за четыре итерации, но в окончательный набор попадают только два элемента span.
Оси это база языка XPath.
Ancestor:: — Возвращает множество предков. attribute:: — Возвращает множество атрибутов текущего элемента. child:: — Возвращает множество потомков на один уровень ниже. descendant:: — Возвращает полное множество потомков. parent:: — Возвращает предка на один уровень назад. self:: — Возвращает текущий элемент. И др.