Oc-windows.ru

IT Новости из мира ПК
1 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Xml xpath php

XPath + PHP – примеры использования запросов и функций

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

В начале, предоставлю вам два типа документов: DTD и XML, на примере которых мы рассмотрим функционирование PHP DOM XPath. Вот как они выглядят:

Основные XPath запросы

Простой синтаксис XPath позволяет обращаться к элементам XML документа. Наиболее простым способом, можно прописать путь к желаемому элементу. Используя XML документ, поданный выше, следующий XPath запрос возвратит коллекцию текущих элементов, находящихся в элементе book:

//library/book

Вот так! Два слеша впереди определяют корневой элемент документа, а один слеш производит переход к дочернему элементу book. Это просто и быстро, не так ли?

Но что, если вы хотите выбрать определенный элемент book из множества? Давайте предположим, что вам нужны книги «Определенного автора». XPath запрос для этого будет следующим:

//library/book/author[text() = «An Author»]/..

Вы можете использовать text() в квадратных скобках для сравнения значения узла. Также «/..» означает, что мы хотим использовать родительский элемент (т. е. возвращаемся на один узел выше).

XPath запросы осуществляются с помощью одной или двух функций: query() и evaluate(). Обе формируют запрос, но разница в возвращаемом результате. query() всегда будет возвращать DOMNodeList, в отличии evaluate() будет возвращать текстовый результат, если это возможно. Для примера, если ваш XPath запрос будет возвращать количество книг написанных определенным автором, тогда query() возвратит пустой DOMNodeList, evaluate() просто возвратит число, вы можете использовать это непосредственно для получения данных из узла.

Код и преимущества скорости XPath

Давайте рассмотрим простой пример, который будет возвращать количество книг написанных конкретным автором. Первый метод мы рассмотрим так, как мы всегда делаем, без использования XPath. Сейчас вы поймете, как это делается без XPath и насколько это проще делать с XPath.

Следующий метод возвращает такой же результат, но используется XPath для выбора тех книг, которые написанные определенным автором.

Заметьте, нам не нужно повторно проверять значение каждого элемента, чтобы определить, каким автором написана каждая книга. Но мы можем более упростить код, используя XPath функцию count(), чтобы подсчитать содержимое элементов этого пути.

Мы можем получить информацию, которую нам нужно, с помощью одной строки XPath запроса. Нет необходимости создавать множество PHP фильтров. Это наиболее простой и быстрый способ написать этот функционал!

Заметьте, что evaluate() использовался в последнем примере. Это потому что функция count() возвращает текстовый результат. Используя query(), возвратиться DOMNodeList, но он будет пустым.

XPath стоит использовать, не только потому что это делает ваш PHP код проще, это также дает преимущество в скорости выполнения кода. Я заметил, что первая версия была на 30% быстрее в среднем, по сравнению со второй. Но третья на 10% быстрее первой. Конечно же, это зависит от вашего сервера и запросов, которые используете. Использование XPath в его чистом виде, дает величайшие результаты в скорости и простоте написания кода.

XPath Функции

Вот несколько функций, которые могут использоваться с XPath. Также вы найдете множество ресурсов, которые детально рассматривают каждую доступную функцию. Если вам нужно вычислять DOMNodeList или сравнивать nodeValue (значение узла), можно найти подходящую XPath функцию, которая исключит использование лишнего PHP кода.

Вы уже это знаете на примере count() функции. Давайте воспользуемся функцией id(), для получение названий книг с заданными ISBN. Для этого нужно использовать следующее XPath выражение:

id(«isbn1234 isbn1235»)/title

Заметьте, значения, которые вы ищете не стоит заключать в скобки, только разделите их пробелами. Также не вздумайте влепить запятую:

Обработка сложных функций в XPath невероятно проста.

Читать еще:  Install index php

Использование PHP функций совместно с XPath

Иногда вам необходимо будет больше функциональности, которую не могут предоставить стандартные функции XPath. К счастью, PHP DOM позволяет взаимодействовать собственным функциям PHP с XPath запросами.

Давайте рассмотрим пример, который возвращает количество слов в названии книги. В этой простейшей функции, мы напишем следующее:

Но, мы также можем включить функцию str_word_count() непосредственно в XPath запрос. Это можно сделать с помощью нескольких шагов. Прежде всего, нам нужно зарегистрировать namespase с XPath объектом. PHP функции в XPath запросах вызываются с помощью строки «php:functionString», после чего прописывается имя желаемой функции. Также, namespace более подробно рассматривается на http://php.net/xpath. Другие значения namespace будут выдавать ошибку. После этого нам нужно вызвать registerPHPFunctions(). Эта функция сообщает PHP, что когда идет обращение через namespace «php:», этот вызов будет обрабатывать именно PHP.

Примерный синтаксис вызова функций будет следующим:

php:functionString(«nameoffunction», arg, arg. )

Давайте совместим все это вместе в следующем примере функции getNumberOfWords():

Заметьте, что вам не нужно вызывать XPath функцию text() чтобы получить текст узла. Метод registerPHPFunctions() делает это автоматизированным. Хотя, следующий пример строки кода также будет валидным:

php:functionString(‘str_word_count’,(//library/book[@isbn = ‘$isbn’]/title[text()]))

Регистрирование PHP функций не ограничено для функций, которые включены в PHP. Вы можете определить свои собственные функции и использовать их внутри XPath. Единственное отличие в том, что придется использовать «php:function» вместо «php:functionString».

Давайте напишем функцию, которая будет за пределами класса, для демонстрации базовой функциональности. Функция, которую мы будем использовать, возвращает книги автора «George Orwell». Она должна возвращать true для каждого узла, который вы хотите включить в запрос.

Аргумент, который передается в функцию, является массивом DOM элементов. Эта функция проходит по массиву и определяет нужные элементы, после чего включает их в DOMNodeList. В этом примере, испытываемый узел был /book, также мы использовали /author для определения нужных элементов.

Теперь мы можем создать функцию getGeorgeOrwellBooks():

Если функция compare() статическая, тогда вам нужно внести поправку в XPath запрос:

//library/book[php:function(‘Library::compare’, author)]

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

В завершение

XPath – это отличный способ сократить количество кода и повысить его обработку, при работе с XML. Дополнительная функциональность PHP DOM позволяет вам расширить XPath функции. Это реально полезная штука, если вы будете ее использовать и углубляться в специфику, вам придется меньше и меньше писать кода.

SimpleXMLElement::xpath

SimpleXMLElement::xpath — Запускает запрос XPath к XML-данным

Описание

Метод xpath ищет узлы SimpleXML с дочерними элементами, соответствующие XPath path .

Список параметров

Возвращаемые значения

Возвращает массив ( array ) объектов SimpleXMLElement или FALSE в случае ошибки.

Примеры

Пример #1 Xpath

$xml = new SimpleXMLElement ( $string );

while(list( , $node ) = each ( $result )) <
echo ‘/a/b/c: ‘ , $node , «n» ;
>

/* Относительные пути также работают. */
$result = $xml -> xpath ( ‘b/c’ );

while(list( , $node ) = each ( $result )) <
echo ‘b/c: ‘ , $node , «n» ;
>
?>

Результат выполнения данного примера:

Обратите внимание, что оба результата одинаковы.

Смотрите также

  • SimpleXMLElement::registerXPathNamespace() — Создает префикс/пространство имен контекста для следующего запроса XPath
  • SimpleXMLElement::getDocNamespaces() — Возвращает пространства имен, объявленные в документе
  • SimpleXMLElement::getNamespaces() — Возвращает пространства имен, используемые в документе
  • Базовое использование SimpleXML

User Contributed Notes 17 notes

To run an xpath query on an XML document that has a namespace, the namespace must be registered with SimpleXMLElement::registerXPathNamespace() before running the query. If the XML document namespace does not include a prefix, you must make up an arbitrary one, and then use it in your query.

$xmlDoc =new SimpleXMLElement ( $strXml );

foreach( $xmlDoc -> getDocNamespaces () as $strPrefix => $strNamespace ) <
if( strlen ( $strPrefix )== 0 ) <
$strPrefix = «a» ; //Assign an arbitrary namespace prefix.
>
$xmlDoc -> registerXPathNamespace ( $strPrefix , $strNamespace );
>

Читать еще:  Php odbc connect

print( $xmlDoc -> xpath ( «//a:message» )[ 0 ]); //Use the arbitrary namespace prefix in the query.
?>

This will output:

On a xml that have namespace you need to do this before your xpath request (or empty array will be return) :

= str_replace ( ‘ns=’ , $string ); //$string is a string that contains xml.
?>

xpath() can also be used to select elements by their attributes. For a good XPath reference check out: http://www.w3schools.com/xpath/xpath_syntax.asp

$xml = simplexml_load_string ( $string );
$result = $xml -> xpath ( «//size[@label=’Large’]» );

// print the first (and only) member of the array
echo $result [ 0 ]-> asXml ();
?>

The script would print:

If you want to find easly all records satisfying some condition in XML data like

try example below

= file_get_contents ( ‘data/books.xml’ );
$xml = new SimpleXMLElement ( $xmlStr );
// seach records by tag value:
// find all book records with price higher than 40$
$res = $xml -> xpath ( «book/price[.>’40’]/parent::*» );
print_r ( $res );

?>

You will see response like:
Array (
[0] => SimpleXMLElement Object
(
[@attributes] => Array
(
[id] => bk101
)

[author] => Gambardella, Matthew
[title] => XML Developer’s Guide
[genre] => Computer
[price] => 44.95
[publish_date] => 2000-10-01
[description] => An in-depth look at creating applications
with XML.
)
.

As mentioned already xpath will fail is the default namespace ‘xmlns’ is used like in:

= $string =

XML;
?>

xpath cannot search through the xml without explicitly specifying a namespace.
There are 2 options :
1. rename the ‘xmlns’ into something else to trick xpath into believing that no default namespace is defined.
2. register a string as the default namespace and use that string in all your queries. Unfortunatly, an empty space will not work.
No other option currently exist until XPath2.0 becomes the default library.

Xpath actually knows which element is root regardless of element on which you execute it. Example:

header ( ‘content-type: text/plain’ );

$xml = new SimpleXMLElement ( $string );

//relative to root
$b0 = $xml -> b [ 0 ]-> xpath ( ‘//c’ );
while(list( , $node ) = each ( $b0 )) <
echo ‘b[0]: //c: ‘ , $node , «n» ;
>

$b1 = $xml -> b [ 1 ]-> xpath ( ‘//c’ );
while(list( , $node ) = each ( $b1 )) <
echo ‘b[1]: //c: ‘ , $node , «n» ;
>

//relative to current element
$b0 = $xml -> b [ 0 ]-> xpath ( ‘.//c’ );
while(list( , $node ) = each ( $b0 )) <
echo ‘b[0]: .//c: ‘ , $node , «n» ;
>

$b1 = $xml -> b [ 1 ]-> xpath ( ‘.//c’ );
while(list( , $node ) = each ( $b1 )) <
echo ‘b[1]: .//c: ‘ , $node , «n» ;
>

Примеры xpath-запросов к html

Создание запроса к узлам веб-страниц

Предлагаю вашему вниманию небольшую лабораторную работу, в ходе которой я продемонстрирую создание 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 запрос к выбранному элементу.

Читать еще:  Подключение к серверу php

Если вы выделили заголовок первого события, то запрос будет таким:

После удаления лишних индексов запрос станет соответствовать всем элементам типа «заголовок».

Firepath подсвечивает элементы, которые соответствуют запросу. Вы можете в реальном времени увидеть, какие узлы документа соответствуют запросу.

Идем дальше. Создаем запросы для поиска мест проведения конференций и их спонсоров либо с помощью селектора, либо модифицировав первый запрос.

Запрос для получения информации о местах проведения конференций:
.//*[@ ]/ul/li/div/p[2]

Так мы получим список спонсоров:
.//*[@ ]/ul/li/div/p[3]

Синтаксис xpath

Давайте вернемся к созданным запросам и разберемся в том, как они устроены.
Рассмотрим подробно первый запрос

В этом запросе я выделил три части для демонстрации возможностей xpath. (Деление на части уловное)

Первая часть
.// — рекурсивный спуск на ноль или более уровней иерархии от текущего контекста. В нашем случае текущий контекст это корень документа

Вторая часть
* — любой элемент,
[@ . Идентификаторы элементов XHTML должны быть уникальны. Поэтому запрос «любой элемент с конкретным ID» должен вернуть единственный искомый нами узел.

Мы можем заменить * на точное имя узла div в этом запросе
div[@ ]

Таким образом, мы спускаемся по дереву документа до нужного нам узла div[@ ]. Нас абсолютно не волнует, из каких узлов состоит DOM-дерево и сколько уровней иерархии осталось выше.

Третья часть
/ul/li/div/p/a –xpath-путь до конкретного элемента. Путь состоит из шагов адресации и условия проверки узлов (ul, li и т.д.). Шаги разделяются символом » /»(косая черта).

Коллекции xpath

Не всегда удается получить доступ к интересующему узлу с помощью предиката или шагов адресации. Очень часто на одном уровне иерархии находится насколько узлов одинакового типа и необходимо выбрать «только первые» или «только вторые» узлы. Для таких случаев предусмотрены коллекции.

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

Исходя из того, что «место проведения» всегда второй параграф после «названия конференции», получаем следующий запрос:
.//*[@ ]/ul/li/div/p[2]
Где p[2] – второй элемент в наборе для каждого узла списка /ul/li/div.

Аналогично список спонсоров мы можем получить запросом:
.//*[@ ]/ul/li/div/p[3]

Некоторые функции хpath

В хpath существует множество функций для работы с элементами внутри коллекции. Я приведу только некоторые из них.

last():
Возвращает последний элемент коллекции.
Запрос ul/li/div/p[last()] — возвратит последние параграфы для каждого узла списка «ul».
Функция first() не предусмотрена. Для доступа к первому элементу используйте индекс «1».

text():
Возвращает тестовое содержание элемента.
.//a[text() = ‘Archive’] – получаем все ссылки с текстом «Archive».

position() и mod:
position() — возвращает позицию элемента в множестве.
mod — остаток от деления.

Комбинацией данных функций можем получить:
— не четные элементы ul/li[position() mod 2 = 1]
— четные элементы: ul/li[position() mod 2 = 0]

Операции сравнения

  • — логическое «больше»
  • = — логическое «больше либо равно»

ul/li[position() > 2] , ul/li[position() — элементы списка начиная с 3го номера и наоборот.

Самостоятельно

Попробуйте получить:
— четные URL ссылки из левого меню «Standards»;
— заголовки всех новостей, кроме первой с главной страницы w3c.org.

Xpath в PHP5

В заключение

На простом примере мы увидели возможности xpath для доступа к узлам веб-страниц.
Xpath является отраслевым стандартом для доступа к элементам xml и xhtml, xslt преобразований.
Вы можете применять его для парсинга любой html-страницы. В случае если исходный html-код содержит значительные ошибки в разметке пропустите его через tidy. Ошибки будут исправлены.

Старайтесь отказаться от регулярных выражений при парсинге веб-страниц в пользу xpath.
Это сделает ваш код проще, понятнее. Вы допустите меньше ошибок. Сократиться время отладки.

Ссылка на основную публикацию
Adblock
detector