публикация данной статьи разрешена только со ссылкой на сайт автора статьи
В этой статье я покажу пример, как разобрать большой XML файл. Если на вашем сервере (хостинге) не запрещено увеличение времени работы скрипта, то можно разбирать XML файл весом хоть гигабайты, сам лично разбирал только файлы от озона весом 450 мегабайт.
При разборе больших XML файлов возникает две проблемы:
1. Не хватает памяти.
2. Не хватает выделенного времени для работы скрипта.
Вторую проблему с временем решить можно, если сервером это не запрещено.
А вот проблему с памятью решить сложно, даже если речь идет о своем сервере, то ворочать файлы по 500 мегабайт не очень просто а уж на хостинге и на VDS увеличить память просто не получится.
В PHP существует несколько встроенных вариантов обработки XML - SimpleXML, DOM, SAX.
Все эти варианты подробно описаны во многих статьях с примерами, но все примеры демонстрируют работу с полным XML документом.
Вот один из примеров, получаем объект из XML файла
$xml = simplexml_load_file ("1.xml" ); ?>
Теперь можно обрабатывать этот объект, НО...
Как видно, весь XML файл считывается в память, затем все разбирается в объект.
То есть все данные попадают в память и если выделенной памяти мало, то скрипт останавливается.
Для обработки больших файлов такой вариант не подходит, нужно читать файл построчно и обрабатывать эти данные по очереди.
При этом проверка на валидность осуществляется так же по мере обработки данных, поэтому нужно иметь возможность для отката, например удалить все внесенные в базу данные в случае не валидного XML файла, либо осуществить два прохода по файлу, сначала читать на валидность, затем читать для обработки данных.
Вот теоретический пример разбора большого XML файла.
Этот скрипт читает по одному символу из файла, собирает эти данные в блоки и отправляет в разборщик XML.
Такой подход полностью решает проблему с памятью и не вызывает нагрузки, но усугубляет проблему со временем. Как попытаться решить проблему со временем, читайте ниже.
Function
webi_xml
($file
)
{
########
### функция работы с данными
{
print
$data
;
}
############################################
{
print
$name
;
print_r
($attrs
);
}
## функция закрывающих тегов
function
endElement
($parser
,
$name
)
{
print
$name
;
}
############################################
($xml_parser , "data" );
// открываем файл
$fp
=
fopen
($file
,
"r"
);
$perviy_vxod = 1 ; $data = "" ;
{
$simvol = fgetc ($fp ); $data .= $simvol ;
if($simvol
!=
">"
) { continue;}
"
);
$perviy_vxod
=
0
;}
echo
"
break;
}
$data
=
""
;
}
fclose
($fp
);
Webi_xml ("1.xml" );
?>
В этом примере я все сложил в одну функцию webi_xml()
и в самом низу видно ее вызов.
Сам скрипт состоит из трех основных функций:
1. Функция которая ловит открытие тега startElement()
2. Функция которая ловит закрытие тега endElement()
3. И функция получения данных data()
.
Предположим что содержимое файла 1.xml некий рецепт
<
title
>
Простой хлеб
title
>
<
ingredient amount
=
"3"
unit
=
"стакан"
>
Мука
ingredient
>
<
ingredient amount
=
"0.25"
unit
=
"грамм"
>
Дрожжи
ingredient
>
<
ingredient amount
=
"1.5"
unit
=
"стакан"
>
Тёплая вода
ingredient
>
<
ingredient amount
=
"1"
unit
=
"чайная ложка"
>
Соль
ingredient
>
<
instructions
>
<
step
>
Смешать все ингредиенты и тщательно замесить
.
step
>
<
step
>
Закрыть тканью и оставить на один час в тёплом помещении
.
step
>
<
step
>
Замесить ещё раз
,
положить на противень и поставить в духовку
.
step
>
<
step
>
Посетить сайт сайт
step
>
instructions
>
recipe
>
Начинаем все с вызова общей функции webi_xml
("1.xml"
);
Дальше в этой функции стартует разборщик и все имена тегов переводим в верхний регистр, чтобы все теги имели одинаковый регистр.
$xml_parser
=
xml_parser_create
();
xml_parser_set_option
($xml_parser
,
XML_OPTION_CASE_FOLDING
,
true
);
Теперь указываем какие функции будут работать для отлова открытия тега, закрытия и обработки данных
xml_set_element_handler
($xml_parser
,
"startElement"
,
"endElement"
);
xml_set_character_data_handler
($xml_parser
,
"data"
);
Дальше идет открытие указанного файла, перебор файла по одному символу и каждый символ добавляется в строковую переменную пока не будет найден символ >
.
Если это самое первое обращение к файлу, то попутно будет удалено все что будет лишним в начале файла, все что стоит до
, именно с такого тега должен начинаться XML.
В первый раз строковая переменная соберет в себе строку
И отправит ее в разборщик
xml_parse
($xml_parser
,
$data
,
feof
($fp
))
;
После обработки данных строковая переменная сбрасыватеся и снова начинается сбор данных в строку и во второй раз сформируется строка
В третий
в четвертый
Простой хлеб
Обратите внимание, что строковая переменная всегда формируется по законченному тегу >
и не обязательно посылать разбощику открытый и закрытый тег с данными например
Данному обработчику важно получить целый не разбитый тег, хоть один открытый, а в следущий шаг закрытый тег, или сразу получить 1000 строк файла, не важно, главное чтобы тег не разрывался, например
le>Простой хлеб
Так отправить данные обработчику нельзя, так как тег разорвался.
Вы можете придумать свою методику посылания данных в обработчик, например собирать по 1 мегабайту данных и отправлять в обработчик для повышения скорости, только следите чтобы теги всегда завершались, а данные можно разрывать
хлеб
Таким образом частями, как вы пожелаете можно отправить большой файл в обработчик.
Теперь рассмотрим каким образом эти данные обрабатываются и как их получить.
Начинаем с функции открывающих тегов startElement
($parser
,
$name
,
$attrs
)
Предположим, что обработка дошла до строки
<
ingredient amount
=
"3"
unit
=
"стакан"
>
Мука
ingredient
>
Тогда внутри функции переменная $name
будет равна ingredient
то есть название открытого тега (до закрытия тега дело еще не дошло).
Так же в данном случае будет доступен массив атрибутов этого тега $attrs
, в котором будут данные amount
=
"3"
и unit
=
"стакан"
.
После этого пошла обработка данных открытого тега функцией data
($parser
,
$data
)
В переменной $data
будет все, что находится между открывающим и закрывающим тегом, в нашем случае это текст Мука
И завершается обработка нашей строки функцией endElement
($parser
,
$name
)
Это название закрытого тега, в нашем случае $name
будет равна ingredient
А после этого опять пошло все по кругу.
Приведенный пример лишь демонстрирует принцип обработки XML, но для реального применения его нужно доработать.
Обычно, разбирать большой XML приходится для занесения данных в базу и для правильной обработки данных нужно знать к какому открытому тегу относятся данные, какой уровень вложения тега и какие теги открыты по иерархии выше. Обладая такой информацией можно без проблем правильно обработать файл.
Для этого нужно ввести несколько глобальных переменных, которые будут собирать информацию об открытых тегах, вложенности и данные.
Привожу пример, который можно использовать
Function
webi_xml
($file
)
{
global
$webi_depth
;
// счетчик, для отслеживания глубины вложенности
$webi_depth
=
0
;
global
$webi_tag_open
;
// будет содержать массив открытых в данный момент тегов
$webi_tag_open
= array();
global
$webi_data_temp
;
// этот массив будет содержать данные одного тега
####################################################
### функция работы с данными
function
data
($parser
,
$data
)
{
global
$webi_depth
;
global
$webi_tag_open
;
global
$webi_data_temp
;
// добавляем данные в массив с указанием вложенности и открытого в данный момент тега
$webi_data_temp
[
$webi_depth
][
$webi_tag_open
[
$webi_depth
]][
"data"
].=
$data
;
}
############################################
####################################################
### функция открывающих тегов
function
startElement
($parser
,
$name
,
$attrs
)
{
global
$webi_depth
;
global
$webi_tag_open
;
global
$webi_data_temp
;
// если уровень вложенности уже не нулевой, значит один тег уже открыт
// и данные из него уже в массиве, можно их обработать
if ($webi_depth
)
{
"
;
print
"
"
;
print_r
($webi_tag_open
);
// массив открытых тегов
print
"
" ;
// после обработки данных удаляем их для освобождения памяти
unset($GLOBALS
[
"webi_data_temp"
][
$webi_depth
]);
}
// теперь пошло открытие следующего тега и дальше обработка его произойдет на следующем шаге
$webi_depth
++;
// увеличиваем вложенность
$webi_tag_open
[
$webi_depth
]=
$name
;
// добавляем открытый тег в массив информаци
$webi_data_temp
[
$webi_depth
][
$name
][
"attrs"
]=
$attrs
;
// теперь добавляем атрибуты тега
}
###############################################
#################################################
## функция закрывающих тегов
function
endElement
($parser
,
$name
) {
global
$webi_depth
;
global
$webi_tag_open
;
global
$webi_data_temp
;
// здесь начинается обработка данных, например добаление в базу, сохранение в файл и т.д.
// $webi_tag_open содержит цепочку открытых тегов по уровню вложенности
// например $webi_tag_open[$webi_depth] содержит название открытого тега чья информация сейчас обрабатывается
// $webi_depth уровень вложенности тега
// $webi_data_temp[$webi_depth][$webi_tag_open[$webi_depth]]["attrs"] массив атрибутов тега
// $webi_data_temp[$webi_depth][$webi_tag_open[$webi_depth]]["data"] данные тега
Print
"данные "
.
$webi_tag_open
[
$webi_depth
].
"--"
.($webi_data_temp
[
$webi_depth
][
$webi_tag_open
[
$webi_depth
]][
"data"
]).
"
"
;
print_r
($webi_data_temp
[
$webi_depth
][
$webi_tag_open
[
$webi_depth
]][
"attrs"
]);
print
"
"
;
print_r
($webi_tag_open
);
print
"
" ;
Unset($GLOBALS
[
"webi_data_temp"
]);
// после обработки данных удаляем массив с данными целиком, так как произошло закрытие тега
unset($GLOBALS
[
"webi_tag_open"
][
$webi_depth
]);
// удаляем информацию об этом открытом теге... так как он закрылся
$webi_depth
--;
// уменьшаем вложенность
}
############################################
$xml_parser
=
xml_parser_create
();
xml_parser_set_option
($xml_parser
,
XML_OPTION_CASE_FOLDING
,
true
);
// указываем какие функции будут работать при открытии и закрытии тегов
xml_set_element_handler
($xml_parser
,
"startElement"
,
"endElement"
);
// указываем функцию для работы с данными
xml_set_character_data_handler
($xml_parser
,
"data"
);
// открываем файл
$fp
=
fopen
($file
,
"r"
);
$perviy_vxod
=
1
;
// флаг для проверки первого входа в файл
$data
=
""
;
// сюда собираем частями данные из файла и отправляем в разборщик xml
// цикл пока не найден конец файла
while (!
feof
($fp
) and
$fp
)
{
$simvol
=
fgetc
($fp
);
// читаем один символ из файла
$data
.=
$simvol
;
// добавляем этот символ к данным для отправки
// если символ не завершающий тег, то вернемся к началу цикла и добавим еще один символ к данным, и так до тех пор, пока не будет найден закрывающий тег
if($simvol
!=
">"
) { continue;}
// если закрывающий тег был найден, теперь отправим эти собранные данные в обработку
// проверяем, если это первый вход в файл, то удалим все, что находится до тега
// так как иногда может встретиться мусор до начала XML (корявые редакторы, либо файл получен скриптом с другого сервера)
if($perviy_vxod
) {
$data
=
strstr
($data
,
""
);
$perviy_vxod
=
0
;}
// теперь кидаем данные в разборщик xml
if (!
xml_parse
($xml_parser
,
$data
,
feof
($fp
))) {
// здесь можно обработать и получить ошибки на валидность...
// как только встретится ошибка, разбор прекращается
echo
"
XML Error: "
.
xml_error_string
(xml_get_error_code
($xml_parser
));
echo
" at line "
.
xml_get_current_line_number
($xml_parser
);
break;
}
// после разбора скидываем собранные данные для следующего шага цикла.
$data
=
""
;
}
fclose
($fp
);
xml_parser_free
($xml_parser
);
// удаление глобальных переменных
unset($GLOBALS
[
"webi_depth"
]);
unset($GLOBALS
[
"webi_tag_open"
]);
unset($GLOBALS
[
"webi_data_temp"
]);
Webi_xml ("1.xml" );
?>
Весь пример сопроводил комментариями, теперь тестируйте и экспериментируйте.
Обратите внимание, в функции работы с данными в массив данные не просто вставляются, а именно добавляются с помощью ".="
так как данные могут поступать не в целом виде и если сделать просто присвоение, то время от времени вы будете получать данные кусками.
Ну вот и все, теперь при обработке файла любого размера памяти хватит, а вот время работы скрипта увеличить можно несколькими способами.
В начало скрипта вставьте функцию
set_time_limit
(6000
);
или
ini_set
("max_execution_time"
,
"6000"
);
Либо добавьте в файл.htaccess текст
php_value max_execution_time 6000
Данные примеры увеличат время работы скрипта до 6000 секунд.
Увеличить время подобным образом можно только в выключенном безопасном режиме.
Если у вас есть доступ к редактированию php.ini можете увеличить время с помощью
max_execution_time = 6000
Например на хостинге мастерхост на момент написания статьи увеличение времени скрипта запрещено, не смотря на выключенный безопасный режим, но если вы профи, вы можете сделать свою сборку php на мастерхосте, но об этом не в этой статье.
1 этап. Прохождение тестирования(взаимодействие с тестовым контуром ГИС ГМП)
#Адрес сервиса ГИС ГМП тестовый:
gisgmp.wsdlLocation=http://213.59.255.182:7777/gateway/services/SID0003663?wsdl
gisgmp.wsdlLocation.endPoint=http://213.59.255.182:7777/gateway/services/SID0003663
Этот адрес прописывается в настройках СП.Дополнительно требуется прописать в файле настроек логгирования, указав значение
После выгрузки требуется проверить статус действием "Запрос статуса обработки". После чего ЭД Сведение о платеже переходит на статус "Принят ГИС ГМП" -…
Дано:
Таблица MSG (сообщения) с большим количеством записей.
CREATETABLEmsg(idINTEGERNOTNULLPRIMARYKEY,descriptionCHAR(50)NOTNULL,
date_createDATE);
Задача:
Необходимо очистить таблицу от данных/
Решение:
Для решения данной задачи есть несколько способов. Ниже описание и пример каждого из них.
Самый простой способ (первый вариант
) - выполнение оператора удаления записи. При его выполнении вы будете видеть результат (сколько записей удалено). Удобная штука когда необходимо точно знать и понимать правильные ли данные удалены. НО имеет недостатки перед другими вариантами решения поставленной задачи.
DELETE FROMmsg;--Удалит все строки в таблице--Удалит все строки у которых дата создания "2019.02.01" DELETE FROMmsg WHEREdate_create="2019.02.01";
Второй вариант
. Использование оператораDML для очистки всех строк в таблице.
TRUNCATETABLEmsg;
При этом несколько особенностей использования данного оператора:
Его нет в Firebird, поэтому пользуемся первым и третьим вариантом.После выпо…
Актуальные адреса для обращений к ЕСМЭВ 3.0
Напоминаем, что в соответствии с ранее опубликованной информацией на Технологическом портале СМЭВ 3.0 необходимо использовать актуальные адреса размещения Единого электронного сервиса:
адрес единого электронного сервиса среды разработки СМЭВ 3.0, соответствующий схеме 1.1 - http://smev3-d.test.gosuslugi.ru:7500/smev/v1.1/ws?wsdl , при этом сервис будет также доступен по адресу
Сейчас мы с вами изучим работу с XML. XML - это формат для обмена данными между сайтами. Он очень похож на HTML, только в XML разрешены свои теги и атрибуты.
Зачем нужен XML при парсинге? Иногда бывает так, что сайт, который вам нужно спарсить, имеет API, с помощью которого можно получить желаемое, особо не напрягаясь. Поэтому сразу совет - перед тем, как парсить сайт, проверьте, нету ли у него API.
Что такое API? Это набор функций, с помощью которых вы можете слать запрос этому сайту и получать нужный ответ. Вот этот ответ чаще всего приходит в формате XML. Поэтому давайте приступим к его изучению.
Работа с XML в PHP
Пусть у вас есть XML. Он может быть в строке, либо хранится в файле или отдаваться по запросу к определенному URL.
Пусть XML хранится в строке. В этом случае из этой строки нужно создать объект с помощью new SimpleXMLElement :
$str = "
Сейчас у нас в переменной $xml хранится объект с разобранным XML. Обращаясь к свойствам этого объекта можно получать доступ с содержимому тегов XML. Как именно - разберем чуть ниже.
Если же XML хранится в файле или отдается по обращению к URL (что чаще всего и бывает), то следует использовать функцию simplexml_load_file , которая делает тот же объект $xml :
$xml = simplexml_load_file(путь к файлу или урл);
Приемы работы
В примерах ниже наш XML хранится в файле или по URL.
Пусть дан следующий XML:
Давайте получим имя, возраст и зарплату работника:
$xml = simplexml_load_file(путь к файлу или урл); echo $xml->name; //выведет "Коля" echo $xml->age; //выведет 25 echo $xml->salary; //выведет 1000
Как вы видите, у объекта $xml есть свойства, соответствующие тегам.
Вы может обратили внимание, что тег
$xml = simplexml_load_file(путь к файлу или урл); echo $xml->name; //выведет "Коля" echo $xml->age; //выведет 25 echo $xml->salary; //выведет 1000
Корневой тег в XML может быть только один, так же, как и тег в обычном HTML.
Давайте чуть модифицируем наш XML:
В этом случае у нас получится цепочка обращений:
$xml = simplexml_load_file(путь к файлу или урл); echo $xml->worker->name; //выведет "Коля" echo $xml->worker->age; //выведет 25 echo $xml->worker->salary; //выведет 1000
Работа с атрибутами
Пусть некоторые данные хранятся в атрибутах:
$xml = simplexml_load_file(путь к файлу или урл); echo $xml->worker["name"]; //выведет "Коля" echo $xml->worker["age"]; //выведет 25 echo $xml->worker["salary"]; //выведет 1000 echo $xml->worker; //выведет "Номер 1"
Теги с дефисами
В XML разрешены теги (и атрибуты) с дефисом. В этом случае обращение к таким тегам происходит так:
$xml = simplexml_load_file(путь к файлу или урл); echo $xml->worker->{first-name}; //выведет "Коля" echo $xml->worker->{last-name}; //выведет "Иванов"
Перебор циклом
Пусть теперь у нас не один работник, а несколько. В этом случае мы можем перебрать наш объект с помощью цикла foreach:
$xml = simplexml_load_file(путь к файлу или урл); foreach ($xml as $worker) { echo $worker->name; //выведет "Коля", "Вася", "Петя" }
Из объекта в нормальный массив
Если вам неудобно работать с объектом, вы можете преобразовать его в нормальный массив PHP с помощью следующего хитрого приема:
$xml = simplexml_load_file(путь к файлу или урл); var_dump(json_decode(json_encode($xml), true));
Больше информации
Парсинг на основе sitemap.xml
Зачастую на сайте есть файл sitemap.xml. В этом файле хранятся ссылки на все страницы сайта для удобства индексации их поисковыми системами (индексация - это по сути и есть парсинг сайта яндексом и гуглом).
В общем-то нас мало должно волновать, зачем нужен этот файл, главное, что если он есть - можно не лазить по страницам сайта какими-либо хитрыми методами, а просто воспользоваться этим файлом.
Как проверить наличие этого файла: пусть мы парсим сайт site.ru, тогда обратитесь в браузере к site.ru/sitemap.xml - если что-то увидите, значит он там есть, а если не увидите - то увы.
Если sitemap есть - то в нем содежатся ссылки на все страницы сайта в формате XML. Спокойно забираете этот XML, парсите его, отделяете ссылки на нужные вам страницы любым удобным вам способом (например, анализом URL, который был описан в методе паука).
В итоге вы получаете список ссылок для парсинга, остается только зайти на них и спарсить нужным вам контент.
Подробнее об устройстве sitemap.xml читайте в википедии .
Что вам делать дальше:
Приступайте к решению задач по следующей ссылке: задачи к уроку .
Когда все решите - переходите к изучению новой темы.
Парсинг XML по сути означает проход по XML-документу и возвращение соответствующих данных. И хотя все большее число веб-сервисов возвращает данные в формате JSON, но все же большинство по-прежнему использует XML, поэтому важно освоить парсинг XML, если вы хотите использовать весь спектр доступных интерфейсов API.
Используя расширение SimpleXML в PHP, которое было добавлено еще в PHP 5.0, работать с XML очень легко и просто. В этой статье я покажу вам, как это делать.
Основы использования
Давайте начнем со следующего примера languages.xml :
>
>
>
>
Данный XML-документ содержит список языков программирования с некоторой информацией о каждом языке: год его реализации и имя его создателя.
Первый шаг заключается в загрузке XML с использованием функций либо simplexml_load_file() , либо simplexml_load_string() . Как понятно из названия функций, первая загружает XML из файла, а вторая будет загружать XML из строки.
Обе функции считывают все дерево DOM в память и возвращают объект SimpleXMLElement . В приведенном выше примере, объект сохраняется в переменной $languages. Вы можете использовать функции var_dump() или print_r() , чтобы получить подробную информацию о возвращенном объект, если хотите.
SimpleXMLElement Object
[
lang]
=>
Array
[
0
]
=>
SimpleXMLElement Object
[
@
attributes]
=>
Array
[
name]
=>
C
[
appeared]
=>
1972
[
creator]
=>
Dennis Ritchie
[
1
]
=>
SimpleXMLElement Object
[
@
attributes]
=>
Array
[
name]
=>
PHP
[
appeared]
=>
1995
[
creator]
=>
Rasmus Lerdorf
[
2
]
=>
SimpleXMLElement Object
[
@
attributes]
=>
Array
[
name]
=>
Java
[
appeared]
=>
1995
[
creator]
=>
James Gosling
)
)
Данный XML содержит корневой элемент languages , внутри которого находятся три элемента lang. Каждый элемент массива соответствует элементу lang в XML-документе.
Вы можете получить доступ к свойствам объекта при помощи оператора -> . Например, $languages->lang вернет вам объект SimpleXMLElement, который соответствует первому элементу lang . Этот объект содержит два свойства: appeared и creator.
$languages
->
lang
[
0
]
->
appeared
;
$languages
->
lang
[
0
]
->
creator
;
Вывести на экран список языков и показать их свойства можно очень легко при помощи стандартного цикла, такого как foreach .
foreach
($languages
->
lang
as
$lang
)
{
printf
(
""
,
$lang
[
"name"
]
,
$lang
->
appeared
,
$lang
->
creator
)
;
}
Обратите внимание, как я получил доступ к имени атрибута элемента lang, чтобы получить название языка. Таким образом Вы можете получить доступ к любому атрибуту элемента представленого в виде объекта SimpleXMLElement.
Работа с пространствами имен
Во время работы с XML различных веб-сервисов вы не раз столкнетесь с пространствами имен элементов. Давайте изменим наш languages.xml , чтобы показать пример использования пространства имен:
xmlns:dc
=>
>
>
>
Теперь элемент creator помещается в пространстве имен dc , который указывает на http://purl.org/dc/elements/1.1/. Если вы попытаетесь распечатать создателей языка, используя наш предыдущий код, то он не будет работать. Для того, чтобы читать пространства имен элементов вам необходимо использовать один из следующих подходов.
Первый подход заключается в использовании имен URI непосредственно в коде, когда обращаемся к пространству имен элементов. В следующем примере показано, как это делается:
$dc
=
$languages
->
lang
[
1
]
-
>
children("http://purl.org/dc/elements/1.1/"
)
;
echo
$dc
->
creator
;
Метод children() принимает пространство имен и возвращает дочерние элементы, которые начинаются с префикса. Он принимает два аргумента, первый из которых является пространством имен XML, и второй необязательный аргумент, который по умолчанию равен false . Если второй аргумент установлен как TRUE, пространство имен будет рассмотрено как префикс. Если FALSE, то пространство имен будет рассмотрено как пространство имен URL.
Второй подход состоит в чтении имен URI из документа и использование их при обращении к пространству имен элементов. На самом деле это лучший способ доступа к элементам, потому что вы не должны быть жестко привязаны к URI.
$namespaces
=
$languages
->
getNamespaces
(true
)
;
$dc
=
$languages
->
lang
[
1
]
->
children
($namespaces
[
"dc"
]
)
;
echo $dc -> creator ;
Метод GetNamespaces() возвращает массив имен префиксов и связанные с ними URI. Он принимает дополнительный параметр, который по умолчанию равен false . Если вы установите его как true , то этот метод будет возвращать имена, используемые в родительских и дочерних узлах. В противном случае, он находит пространства имен, используемые только в родительском узле.
Теперь вы можете пройтись по списку языков следующим образом:
$languages
=
simplexml_load_file
("languages.xml"
)
;
$ns
=
$languages
->
getNamespaces
(true
)
;
foreach
($languages
->
lang
as
$lang
)
{
$dc
=
$lang
->
children
($ns
[
"dc"
]
)
;
printf
(
"
%s появился в %d и был создан %s .
" ,$lang [ "name" ] ,
$lang -> appeared ,
$dc -> creator
) ;
}
Практический пример - Парсинг видео-канала с YouTube
Давайте рассмотрим пример, который получает RSS-feed с канала YouTube и отображает ссылки на все видео из него. Для этого нужно обратится по следующему адресу:
http://gdata.youtube.com/feeds/api/users/xxx/uploads
URL возвращает список последних видео с данного канала в формате XML. Мы распарсим XML и получим следующую информацию для каждого видео:
- Ссылка на видео
- Миниатюра
- Название
Мы начнем с поиска и загрузки XML:
$channel
=
"Имя_канала"
;
$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-feed, то вы можете увидеть, что там есть несколько элементов entity , каждый из которых хранит подробную информацию о конкретном видео с канала. Но мы используем только миниатюры изображений, адрес видео и название. Эти три элемента являются потомками элемента group , который, в свою очередь, является дочерним для entry :
…
…
…
>
…
Мы просто пройдемся по всем элементам entry , и для каждого из них извлечем необходимую информацию. Обратите внимание, что player, thumbnail и title находятся в пространстве имен media. Таким образом, мы должны действовать, как в предыдущем примере. Мы получаем имена из документа и используем пространство имен при обращении к элементам.
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
(""
,
$player
,
$image
,
$title
)
;
}
Заключение
Теперь, когда вы знаете, как использовать SimpleXML для разбора XML-данных, вы можете улучшить свои навыки путем анализа различных XML-каналов с различными API. Но важно учитывать, что SimpleXML считывает весь DOM в память, так что если вы парсите большой набор данных, то вы можете столкнуться с нехваткой памяти. Чтобы узнать больше о SimpleXML прочтите документацию .
Если у Вас возникли вопросы, то для скорейшего получения ответа рекомендуем воспользоваться нашим