Синтаксический анализ XML по сути означает навигацию по документу XML и возврат соответствующих данных. Все больше веб-сервисов возвращают данные в формате JSON, но большое количество по-прежнему возвращает XML, поэтому вам нужно освоить синтаксический анализ XML, если вы действительно хотите использовать весь спектр доступных API.
Используя расширение SimpleXML в PHP, которое было введено еще в PHP 5.0, работать с XML очень легко. В этой статье я покажу вам, как.
Основное использование
Давайте начнем со следующего примера в качестве languages.xml
<?xml version="1.0" encoding="utf-8"?>
<languages>
<lang name="C">
<appeared>1972</appeared>
<creator>Dennis Ritchie</creator>
</lang>
<lang name="PHP">
<appeared>1995</appeared>
<creator>Rasmus Lerdorf</creator>
</lang>
<lang name="Java">
<appeared>1995</appeared>
<creator>James Gosling</creator>
</lang>
</languages>
Приведенный выше XML-документ кодирует список языков программирования, предоставляя две детали о каждом языке: год его внедрения и имя его создателя.
Первый шаг — загрузка XML с использованием simplexml_load_file()
simplexml_load_string()
Как и следовало ожидать, первый загрузит файл XML в файл, а второй загрузит XML из заданной строки.
<?php
$languages = simplexml_load_file("languages.xml");
Обе функции читают все дерево DOM в память и возвращают его представление объекта SimpleXMLElement
В приведенном выше примере объект сохраняется в переменной $ languages
Затем вы можете использовать var_dump()
print_r()
SimpleXMLElement Object ( [lang] => Массив ( [0] => SimpleXMLElement Object ( [@attributes] => Массив ( [name] => C ) [появилось] => 1972 [создатель] => Деннис Ритчи ) [1] => SimpleXMLElement Object ( [@attributes] => Массив ( [name] => PHP ) [появилось] => 1995 [создатель] => Расмус Лердорф ) [2] => SimpleXMLElement Object ( [@attributes] => Массив ( [name] => Java ) [появилось] => 1995 [создатель] => Джеймс Гослинг ) ) )
XML содержал элемент корневого language
lang
SimpleXMLElement
lang
SimpleXMLElements
Каждый элемент массива соответствует элементу lang
Вы можете получить доступ к свойствам объекта обычным способом с помощью оператора ->
Например, $languages->lang[0]
SimpleXMLElement
lang
Этот объект имеет два общедоступных свойства: appeared
creator
<?php
$languages->lang[0]->appeared;
$languages->lang[0]->creator;
Итерирование по списку языков и отображение их деталей может быть очень легко выполнено с помощью стандартных методов циклов, таких как foreach
<?php
foreach ($languages->lang as $lang) {
printf(
"<p>%s appeared in %d and was created by %s.</p>",
$lang["name"],
$lang->appeared,
$lang->creator
);
}
Обратите внимание, что я получил доступ к атрибуту name элемента lang
Вы можете получить доступ к любому атрибуту элемента, представленного как объект SimpleXMLElement
Работа с пространствами имен
Много раз вы сталкивались с элементами пространства имен при работе с XML из разных веб-сервисов. Давайте изменим наш пример languages.xml
<?xml version="1.0" encoding="utf-8"?>
<languages
xmlns:dc="http://purl.org/dc/elements/1.1/">
<lang name="C">
<appeared>1972</appeared>
<dc:creator>Dennis Ritchie</dc:creator>
</lang>
<lang name="PHP">
<appeared>1995</appeared>
<dc:creator>Rasmus Lerdorf</dc:creator>
</lang>
<lang name="Java">
<appeared>1995</appeared>
<dc:creator>James Gosling</dc:creator>
</lang>
</languages>
Теперь элемент creator
dc
http://purl.org/dc/elements/1.1/ . Если вы попытаетесь напечатать создателя языка, используя нашу предыдущую технику, это не сработает. Чтобы читать подобные элементы пространства имен, вам нужно использовать один из следующих подходов.
Первый подход заключается в использовании URI пространства имен непосредственно в вашем коде при доступе к элементам пространства имен. Следующий пример демонстрирует, как:
<?php
$dc = $languages->lang[1]- >children("http://purl.org/dc/elements/1.1/");
echo $dc->creator;
Метод children()
Он принимает два аргумента; первое — это пространство имен XML, а второе — необязательный логический тип, который по умолчанию равен false. Если вы передадите true, пространство имен будет рассматриваться как префикс, а не как фактический URI пространства имен.
Второй подход заключается в чтении URI пространства имен из документа и использовании его при доступе к элементам пространства имен. На самом деле это более чистый способ доступа к элементам, потому что вам не нужно жестко кодировать URI.
<?php
$namespaces = $languages->getNamespaces(true);
$dc = $languages->lang[1]->children($namespaces["dc"]);
echo $dc->creator;
Метод getNamespaces()
Он принимает необязательный параметр, который по умолчанию равен false. Если вы установите значение true, метод вернет пространства имен, используемые в родительских и дочерних узлах. В противном случае он находит пространства имен, используемые только в родительском узле.
Теперь вы можете перебирать список языков следующим образом:
<?php
$languages = simplexml_load_file("languages.xml");
$ns = $languages->getNamespaces(true);
foreach($languages->lang as $lang) {
$dc = $lang->children($ns["dc"]);
printf(
"<p>%s appeared in %d and was created by %s.</p>",
$lang["name"],
$lang->appeared,
$dc->creator
);
}
Практический пример — парсинг видео с YouTube
Давайте рассмотрим пример, который получает канал RSS с канала YouTube и отображает ссылки на все видео из него. Для этого нам нужно позвонить по следующему URL:
http://gdata.youtube.com/feeds/api/users//uploads
URL возвращает список последних видео с данного канала в формате XML. Мы проанализируем XML и получим следующую информацию для каждого видео:
- URL видео
- Thumbnail
- заглавие
Мы начнем с извлечения и загрузки XML:
<?php
$channel = "channelName";
$url = "http://gdata.youtube.com/feeds/api/users/".$channel."/uploads";
$xml = file_get_contents($url);
$feed = simplexml_load_string($xml);
$ns=$feed->getNameSpaces(true);
Если вы посмотрите на канал XML, то увидите, что есть несколько элементов entity
Но нас интересуют только миниатюра изображения, видео URL и заголовок. Три элемента являются дочерними элементами group
entry
<entry>
…
<media:group>
…
<media:player url="video url"/>
<media:thumbnail url="video url" height="height" width="width"/>
<media:title type="plain">Title…</media:title>
…
</media:group>
…
</entry>
Мы просто перебираем все элементы entry
Обратите внимание, что player
thumbnail
title
media
Итак, нам нужно действовать как в предыдущем примере. Мы получаем пространства имен из документа и используем пространство имен при доступе к элементам.
<?php
foreach ($feed->entry as $entry) {
$group=$entry->children($ns["media"]);
$group=$group->group;
$thumbnail_attrs=$group->thumbnail[1]->attributes();
$image=$thumbnail_attrs["url"];
$player=$group->player->attributes();
$link=$player["url"];
$title=$group->title;
printf('<p><a href="%s"><img src="%s" alt="%s"></a></p>',
$player, $image, $title);
}
Вывод
Теперь, когда вы знаете, как использовать SimpleXML для анализа XML-данных, вы можете улучшить свои навыки, анализируя различные потоки XML из различных API. Но важно учитывать, что SimpleXML считывает весь DOM в память, поэтому, если вы анализируете большие наборы данных, у вас могут возникнуть проблемы с памятью. В этих случаях рекомендуется использовать что-то отличное от SimpleXML, предпочтительно анализатор на основе событий, такой как XML Parser. Чтобы узнать больше о SimpleXML, ознакомьтесь с его документацией .
И если вам понравилось читать этот пост, вы полюбите Learnable ; место, чтобы узнать новые навыки и приемы у мастеров. Участники получают мгновенный доступ ко всем электронным книгам SitePoint и интерактивным онлайн-курсам, таким как Jump Start PHP .
Комментарии к этой статье закрыты. Есть вопрос по PHP? Почему бы не спросить об этом на наших форумах ?