Компютърни уроци

Разбор на xml в php. За какво се използват XML парсерите и как могат да бъдат полезни?


публикуването на тази статия е разрешено само с връзка към уебсайта на автора на статията

В тази статия ще покажа пример за това как да анализирате голям XML файл. Ако вашият сървър (хостинг) не забранява увеличаването на времето за изпълнение на скрипта, тогава можете да анализирате XML файл с тегло най-малко гигабайта; Аз лично анализирах само файлове от озон с тегло 450 мегабайта.

При анализиране на големи XML файлове възникват два проблема:
1. Няма достатъчно памет.
2. Няма достатъчно определено време за изпълнение на скрипта.

Вторият проблем с времето може да бъде решен, ако сървърът не го забрани.
Но проблемът с паметта е труден за решаване, дори ако говорим за вашия собствен сървър, тогава преместването на файлове от 500 мегабайта не е много лесно и просто не е възможно да се увеличи паметта на хостинг и VDS.

PHP има няколко вградени опции за обработка на XML - SimpleXML, DOM, SAX.
Всички тези опции са описани подробно в много статии с примери, но всички примери демонстрират работа с пълен XML документ.

Ето един пример, получаване на обект от XML файл

Сега можете да обработите този обект, НО...
Както можете да видите, целият XML файл се чете в паметта, след което всичко се анализира в обект.
Тоест всички данни отиват в паметта и ако няма достатъчно разпределена памет, скриптът спира.

Тази опция не е подходяща за обработка на големи файлове; трябва да четете файла ред по ред и да обработвате тези данни един по един.
В този случай проверката за валидност също се извършва, докато данните се обработват, така че трябва да можете да върнете назад, например, да изтриете всички данни, въведени в базата данни в случай на невалиден XML файл, или да извършите две преминавания през файла, първо прочетете за валидност, след това прочетете за обработка на данни.

Ето теоретичен пример за анализиране на голям XML файл.
Този скрипт чете символ по знак от файл, събира тези данни в блокове и ги изпраща на XML анализатора.
Този подход напълно решава проблема с паметта и не причинява натоварване, но влошава проблема с времето. Как да се опитате да разрешите проблема с времето, прочетете по-долу.

Функция webi_xml ($файл)
{

########
### функция за данни

{
отпечатайте $данни;
}
############################################



{
print $name ;
print_r($attrs);
}


## функция за затварящ етикет
функция endElement ($parser, $name)
{
print $name ;
}
############################################

($xml_parser, "данни");

// отворете файла
$fp = fopen($file, "r");

$perviy_vxod = 1; $данни = "";



{

$simvol = fgetc ($fp); $data .= $simvol ;


if($simvol != ">" ) (продължи;)


ехо "

прекъсване;
}

$данни = "";
}
fclose($fp);

Webi_xml("1.xml");

?>

В този пример поставям всичко в една функция webi_xml() и най-отдолу можете да видите нейното извикване.
Самият скрипт се състои от три основни функции:
1. Функция, която хваща отварянето на тага startElement().
2. Функция, която улавя затварящия таг endElement().
3. И функцията за получаване на данни data() .

Да приемем, че съдържанието на файл 1.xml е рецепта



< title >Обикновен хляб
< ingredient amount = "3" unit = "стакан" >брашно
< ingredient amount = "0.25" unit = "грамм" >мая
< ingredient amount = "1.5" unit = "стакан" >Топла вода
< ingredient amount = "1" unit = "чайная ложка" >Сол
< instructions >
< step > Смесете всички съставки и омесете старателно.
< step > Покрива се с кърпа и се оставя за един час на топло помещение..
< step > Омесете отново, поставете върху лист за печене и поставете във фурната.
< step > Посетете сайта на сайта


Започваме всичко, като извикаме общата функция 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, "данни");

След това идва отварянето на посочения файл, итерация през файла един знак наведнъж и всеки знак се добавя към низовата променлива, докато символът бъде намерен > .
Ако това е първият достъп до файла, тогава по пътя всичко, което е ненужно в началото на файла, ще бъде изтрито, всичко, което идва преди , това е тагът, с който XML трябва да започне.
За първи път низова променлива ще съдържа низ

И го изпратете на разглобителя
xml_parse ($xml_parser, $data, feof ($fp));
След обработката на данните променливата на низа се нулира и събирането на данни в низ започва отново и низът се формира за втори път

На третия
</b><br>на четвъртия <br><b>Обикновен хляб

Моля, обърнете внимание, че низовата променлива винаги се формира от завършен таг > и не е необходимо да изпращате на крадеца отворен и затворен етикет с данни, например
Обикновен хляб
Важно е този манипулатор да получи цял непрекъснат таг, поне един отворен таг и в следващата стъпка затворен таг или веднага да получи 1000 реда от файл, няма значение, основното е, че тагът не се чупи например

le>Обикновен хляб
По този начин е невъзможно да се изпратят данни към манипулатора, тъй като етикетът е разкъсан.
Можете да измислите свой собствен метод за изпращане на данни към манипулатора, например, съберете 1 мегабайт данни и ги изпратете на манипулатора, за да увеличите скоростта, просто се уверете, че етикетите винаги са завършени и данните могат да бъдат разкъсани
просто</b><br><b>хляб

Така на части, както желаете, можете да изпратите голям файл към процесора.

Сега нека да разгледаме как се обработват тези данни и как да ги получим.

Нека започнем с функцията за отварящи тагове startElement ($parser, $name, $attrs)
Да приемем, че обработката е достигнала линията
< ingredient amount = "3" unit = "стакан" >брашно
Тогава вътре във функцията променливата $name ще бъде равна на съставкатоест името на отворения етикет (все още не е стигнало до затварянето на етикета).
Също така в този случай ще бъде наличен масив от атрибути на този таг $attrs, който ще съдържа данни сума = "3" и единица = "стъкло".

След това данните от отворения таг бяха обработени от функцията данни ($parser, $data)
Променливата $data ще съдържа всичко, което е между отварящия и затварящия тагове, в нашия случай това е текстът Muka

И обработката на нашия низ от функцията приключва endElement ($parser, $name)
Това е името на затворения таг, в нашия случай $name ще бъде равно на съставка

И след това всичко отново се завъртя в кръг.

Горният пример само демонстрира принципа на обработка на XML, но за реално приложение той трябва да бъде модифициран.
Обикновено трябва да анализирате голям XML, за да въведете данни в базата данни и за да обработите правилно данните, трябва да знаете към кой отворен етикет принадлежат данните, какво ниво на влагане на етикети и кои тагове са отворени в йерархията по-горе. С тази информация можете да обработите файла правилно без никакви проблеми.
За да направите това, трябва да въведете няколко глобални променливи, които ще събират информация за отворени тагове, влагане и данни.
Ето един пример, който можете да използвате

Функция webi_xml ($файл)
{
глобална $webi_depth; // брояч за проследяване на дълбочината на влагане
$webi_depth = 0;
глобален $webi_tag_open; // ще съдържа масив от текущо отворени тагове
$webi_tag_open = масив();
глобален $webi_data_temp; // този масив ще съдържа данните от един таг

####################################################
### функция за данни
функционални данни ($parser, $data)
{
глобална $webi_depth;
глобален $webi_tag_open;
глобален $webi_data_temp;
// добавяне на данни към масива, показващи вложеност и текущо отворен етикет
$webi_data_temp [ $webi_depth ][ $webi_tag_open [ $webi_depth ]][ "данни"].= $данни;
}
############################################

####################################################
### функция за отварящ етикет
функция startElement ($parser, $name, $attrs)
{
глобална $webi_depth;
глобален $webi_tag_open;
глобален $webi_data_temp;

// ако нивото на влагане вече не е нула, тогава един таг вече е отворен
// и данните от него вече са в масива, можете да ги обработите
ако ($webi_depth)
{




" ;

печат"
" ;
print_r($webi_tag_open); // масив от отворени етикети
печат"


" ;

// след обработка на данните, изтрийте ги, за да освободите памет
unset($GLOBALS [ "webi_data_temp" ][ $webi_depth ]);
}

// сега следващият таг е отворен и по-нататъшната обработка ще се извърши в следващата стъпка
$webi_depth++; // увеличаване на вложеността

$webi_tag_open [ $webi_depth ]= $name; // добавяне на отворен таг към информационния масив
$webi_data_temp [ $webi_depth ][ $name ][ "attrs" ]= $attrs; // сега добавете атрибути на тагове

}
###############################################

#################################################
## функция за затварящ етикет
функция endElement ($parser, $name) (
глобална $webi_depth;
глобален $webi_tag_open;
глобален $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"] данни за етикет

Отпечатайте "данни". $webi_tag_open [$webi_depth]. "--" .($webi_data_temp [ $webi_depth ][ $webi_tag_open [ $webi_depth ]][ "данни" ]). "
" ;
print_r ($webi_data_temp [ $webi_depth ][ $webi_tag_open [ $webi_depth ]][ "attrs" ]);
печат"
" ;
print_r($webi_tag_open);
печат"


" ;

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, "данни");

// отворете файла
$fp = fopen($file, "r");

$perviy_vxod = 1; // флаг за проверка на първия запис във файла
$данни = ""; // тук събираме данни от файла на части и ги изпращаме на xml анализатора

// цикъл, докато се намери краят на файла
докато (! feof ($fp) и $fp)
{
$simvol = fgetc ($fp); // прочете един символ от файла
$data .= $simvol ; // добавете този символ към данните, които ще бъдат изпратени

// ако знакът не е крайният таг, тогава се върнете в началото на цикъла и добавете друг знак към данните и така нататък, докато бъде намерен крайният таг
if($simvol != ">" ) (продължи;)
// ако е намерен затварящият етикет, сега ще изпратим тези събрани данни за обработка

// проверяваме дали това е първият запис във файла, тогава ще изтрием всичко, което е преди тага// тъй като понякога може да срещнете боклук преди началото на XML (тромави редактори или файлът е получен от скрипт от друг сървър)
if($perviy_vxod) ($data = strstr ($data, "

// сега хвърлете данните в xml анализатора
if (! xml_parse ($xml_parser, $data, feof ($fp))) (

// тук можете да обработвате и получавате грешки във валидността...
// щом възникне грешка, анализът спира
ехо "
XML грешка: ". xml_error_string(xml_get_error_code($xml_parser));
ехо "на линия" . xml_get_current_line_number ($xml_parser);
прекъсване;
}

// след анализиране, изхвърлете събраните данни за следващата стъпка от цикъла.
$данни = "";
}
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");

?>

Целият пример е придружен от коментари, сега тествайте и експериментирайте.
Моля, имайте предвид, че във функцията за работа с данни, данните не просто се вмъкват в масив, а по-скоро се добавят с помощта на " .=" тъй като данните може да не пристигнат в своята цялост и ако просто направите задание, тогава от време на време ще получавате данните на парчета.

Е, това е всичко, сега има достатъчно памет при обработка на файл с всякакъв размер, но времето за изпълнение на скрипта може да се увеличи по няколко начина.
Вмъкнете функция в началото на скрипта
зададен_време_лимит(6000);
или
ini_set ("max_execution_time" , "6000" );

Или добавете текст към файла .htaccess
php_value max_execution_time 6000

Тези примери ще увеличат времето за изпълнение на скрипта до 6000 секунди.
Можете да увеличите времето по този начин само когато безопасният режим е изключен.

Ако имате достъп за редактиране на php.ini, можете да увеличите времето, като използвате
max_execution_time = 6000

Например, на хостинг Masterhost, към момента на писане на тази статия, увеличаването на времето на скрипта е забранено, въпреки че безопасният режим е изключен, но ако сте професионалист, можете да направите своя собствена PHP компилация на Masterhost, но това не е предмет на тази статия.

28.3K

Виждал съм много xml парсери, но не съм засягал уеб програмирането. Сега искам да разбера и да науча с вас как да направя прост xml парсер в php.

За какво? Необходимо!

Не, добре, всъщност: xml файловете са много полезно нещо. И всеки професионалист трябва... не, не трябва, но трябва да знае как да работи с тях. Искаме да станем професионалисти, нали? Ако сте в моя блог, значи имате такова желание.

Предполагаме, че знаем какво е XML и няма да го описваме тук. Е, ако не знаем, лесно можем да разберем тук: http://ru.wikipedia.org/wiki/XML

Докато търсех начини за анализиране на XML в PHP, открих прост набор от функции в PHP за работа с XML файлове, наречени „Функции на XML анализатор“. Анализът започва с инициализиране на анализатора чрез извикване на функцията xml_parser_create:

$xml_parser = xml_parser_create();

След това трябва да кажем на анализатора кои функции ще обработват xml таговете и текстовата информация, които среща по време на процеса на анализиране. Тези. трябва да инсталирате някои манипулатори:

xml_set_element_handler($xml_parser, “startElement”, “endElement”);

Тази функция е отговорна за настройването на манипулатори за начало на елемент и край на елемент. Например, ако се намери комбинация в текста на xml файл, функцията startElement ще работи, когато анализаторът намери елемента, а функцията endElement ще работи, когато го намери.

Самите функции startElement и endElement приемат няколко параметъра според php документацията:

Но как да четем данни от файл? Все още не сме видели нито един параметър за това в нито една от функциите! И повече за това по-късно: четенето на файла лежи на плещите на програмиста, т.е. трябва да използваме стандартни функции за работа с файлове:

Отворих файла. Сега трябва да го прочетете ред по ред и да подадете прочетените редове към функцията xml_parse:

XML грешка: ".xml_error_string(xml_get_error_code($xml_parser)); echo " at line ".xml_get_current_line_number($xml_parser); break; ) ) ?>

Тук отбелязваме две много важни неща. Първият е, че функцията xml_parse трябва да получи флага за четене на последния ред в третия параметър (true - ако редът е последен, false - ако не). Второто нещо е, че както във всеки бизнес и тук трябва да следим за грешки. Функциите xml_get_error_code и xml_error_string са отговорни за това. Първата функция получава кода на грешката, а втората въз основа на получения код връща текстово описание на грешката. Какво ще се случи в резултат на грешка ще бъде обсъдено по-късно. Също толкова полезна функция xml_get_current_line_number ще ни каже номера на текущия ред, който се обработва във файла.

И както винаги, трябва да освободим ресурсите, заети от системата. За анализ на XML това е функцията xml_parser_free:

xml_parser_free($xml_parser);

Тук разгледахме основните функции. Време е да ги видите в действие. За това измислих xml файл с много проста структура:




123

71234567890

Нека наречем този файл data.xml и се опитаме да го анализираме чрез следния код:

Елемент: $name
"; // име на елемент $depth++; // увеличете дълбочината, така че браузърът да показва отстъпи за всеки ($attrs като $attr => $value) ( ​​​​echo str_repeat(" ", $depth * 3); // отстъпи // показване на атрибута име и неговата стойност echo "Атрибут: ".$attr." = ".$value."
"; ) ) функция endElement($parser, $name) (глобална $depth; $depth--; // намаляване на дълбочината) $depth = 0; $file = "data.xml"; $xml_parser = xml_parser_create(); xml_set_element_handler ($xml_parser, "startElement", "endElement"); if (!($fp = fopen($file, "r"))) ( die("не може да отвори XML вход"); ) докато ($data = fgets ($fp)) ( if (!xml_parse($xml_parser, $data, feof($fp))) ( echo "
XML грешка: "; echo xml_error_string(xml_get_error_code($xml_parser)); echo " at line ".xml_get_current_line_number($xml_parser); break; ) ) xml_parser_free($xml_parser); ?>

В резултат на най-простия скрипт, който разработихме, браузърът показа следната информация в своя прозорец:

Елемент: КОРЕН
Елемент: ИНФО
Атрибут: КОЙ = мой
Елемент: АДРЕС

Атрибут: KVARTIRA = 12
Атрибут: DOM = 15
Елемент: ТЕЛЕФОН

Нека се опитаме да повредим XML файла, като заменим етикета На , и оставяйки затварящия етикет същия:

Елемент: КОРЕН
Елемент: ИНФО
Атрибут: КОЙ = мой
Елемент: АДРЕС
Атрибут: УЛИЦА = моята улица!!
Атрибут: KVARTIRA = 12
Атрибут: DOM = 15
Елемент: ТЕЛЕФОН

XML грешка: Несъответстващ етикет на ред 5

Еха! Съобщенията за грешка работят! И доста информативен.

Ех, забравих още нещо... Не показахме текста, който се съдържа в етикетите за адрес и телефон. Коригираме нашия недостатък - добавяме текстов манипулатор с помощта на функцията xml_set_character_data_handler:

xml_set_character_data_handler($xml_parser, 'stringElement');

И добавяме самата манипулаторна функция към кода.

→ За какво са необходими XML парсерите и как могат да бъдат полезни

Ако се занимавате със създаване на уебсайтове, вероятно сте чували за XML, дори ако все още не сте го използвали в работата си. В този случай е време да се запознаем, защото преживявайки истински бум, през последните десет години този нов формат се превърна от иновативен проект в истински индустриален стандарт и почти всеки ден има доклади за примери за успешното му използване .

Един от най-важните компоненти на XML технологията е специален клас програми, отговорни за анализирането на документи и извличането на необходимата информация - парсери. Това са тези, които ще бъдат обсъдени в тази статия. Нека да разберем за какво са необходими парсерите, какви са те и къде можете да ги получите.

Като цяло XML документът е прост текстов файл, в който необходимата структура от данни се съхранява с помощта на специални синтактични структури (наречени „тагове“). Това ви позволява да съхранявате информация не като непрекъснат масив, а под формата на йерархично свързани фрагменти. Тъй като текстовите файлове са толкова лесни за създаване и предаване по мрежа, те са изключително удобен начин за съхраняване на информация и се използват широко при създаване на сложни разпределени приложения.

Но универсалността на XML текстовия формат води до много очевидно неудобство - преди да извлечете данни от документ, трябва наистина да се борите с анализирането на текста и определянето на неговата структура. Ръчното изпълнение на всички необходими процедури е много нетривиална задача и ще изисква значителни усилия. Един от стандартните механизми, които улесняват живота на разработчиците, са парсерите.

Какво е? XML анализаторът е програма, предназначена да анализира съдържанието на текстов документ, който отговаря на XML спецификацията. Тя получава цялата „мръсна“ работа: получаване на обща информация за документа, анализиране на текста, търсене в него за сервизни конструкции (елементи, атрибути, обекти и т.н.), проверка за съответствие със синтактичните правила, както и предоставяне на интерфейс за достъп Документът. В резултат на това внимателно извлечените данни ще бъдат прехвърлени към потребителското приложение, което може да не знае нищо за това какво е XML.

Анализаторът може да бъде реализиран като отделен софтуерен модул или ActiveX компонент и може да бъде свързан към приложението чрез специални библиотеки от класове на етапа на компилация или изпълнение. Парсерите се делят на валидиращи и невалидиращи. Първите могат да проверяват структурата на документа въз основа на DTD или схеми на данни, докато вторите не се интересуват от това - и следователно, като правило, са с по-малък размер. Много от съвременните парсери са „заредени“ с множество допълнителни функции (разширена обработка на грешки, добавяне и редактиране на данни), което ги прави по-удобни за използване, въпреки че увеличава размера на програмите. Почти всички често срещани парсери също поддържат редица важни XML стандарти (XSLT, схеми на данни, пространства от имена, XPath и т.н.) - или се доставят във връзка с анализатори на други езици, извлечени от него.

Ако осъзнавате полезността на XML анализатора, тогава е време да започнете практически експерименти. Къде мога да ги взема? Не би трябвало да има особени проблеми с намирането на подходящия софтуер: Интернет е пълен със свободно разпространявани парсери, написани на всякакви програмни езици, работещи на всякакви платформи и имащи различни характеристики и цели.

Най-разпространеният и добре познат е анализаторът Expat, написан от Джеймс Кларк, един от създателите на XML спецификацията. Той е реализиран на езика за програмиране C++ и се разпространява заедно с изходния код. Между другото, поддръжката на този език за маркиране в такива добре познати среди като PHP и Perl се изпълнява именно на негова основа. Друг общ парсер е Xerces, наличен в Apache XML Project (имплементиран в Java и C++). Можете да намерите много парсери за C++, Perl и Python. Повечето от тях са написани на Java и са подходящи за всяка платформа, запозната с Java. Пазарните лидери (Microsoft, Oracle, Sun), които винаги се отличават със своя мащаб и монументалност, също не останаха настрана. Те пуснаха по-„тежки“ и функционални пакети, които съдържат, в допълнение към самите анализатори, много допълнителни помощни програми, които улесняват живота на разработчиците.

Разбира се, невъзможно е да се каже всичко за анализаторите в една статия. Но бих искал да се надявам, че разбирате, че работата с XML не е толкова трудна, колкото може да изглежда. Всички сложности на този формат са скрити от нас в парсерите и няма причина да се страхувате да въведете нов формат в съществуващи проекти.

Разборът на XML по същество означава преминаване през XML документ и връщане на съответните данни. Въпреки че нарастващ брой уеб услуги връщат данни във формат JSON, повечето все още използват XML, така че е важно да овладеете анализирането на XML, ако искате да използвате пълния набор от налични API.

Използване на разширението SimpleXMLв PHP, който беше добавен обратно в PHP 5.0, работата с XML е много лесна и проста. В тази статия ще ви покажа как да го направите.

Основи на употреба

Да започнем със следния пример езици.xml:


>

> 1972>
> Денис Ричи >
>

> 1995>
> Расмус Лердорф >
>

> 1995>
> Джеймс Гослинг >
>
>

Този XML документ съдържа списък с езици за програмиране с известна информация за всеки език: годината, в която е въведен, и името на неговия създател.

Първата стъпка е да заредите XML с помощта на функциите simplexml_load_file(), или simplexml_load_string(). Както подсказва името на функциите, първата ще зареди XML от файл, а втората ще зареди XML от низ.

И двете функции четат цялото DOM дърво в паметта и връщат обект SimpleXMLElement. В горния пример обектът се съхранява в променливата $languages ​​​​. Можете да използвате функциите var_dump()или print_r()за да получите подробности за върнатия обект, ако желаете.

Обект SimpleXMLElement
[lang] => Масив
[ 0 ] => Обект SimpleXMLElement
[@attributes] => Масив
[име] => C
[появил се] => 1972г
[създател] => Денис Ричи
[ 1 ] => Обект SimpleXMLElement
[@attributes] => Масив
[име] => PHP
[появил се] => 1995г
[създател] => Расмус Лердорф
[ 2 ] => Обект SimpleXMLElement
[@attributes] => Масив
[име] => Java
[появил се] => 1995г
[създател] => Джеймс Гослинг
)
)

Този XML съдържа основен елемент езици, вътре в който има три елемента езикВсеки елемент от масива съответства на елемент езикв XML документа.

Можете да получите достъп до свойствата на обект с помощта на оператора -> . Например $languages->lang ще ви върне обект SimpleXMLElement, който съответства на първия елемент език. Този обект съдържа две свойства: появил се и създател.

$languages ​​​​-> lang [0] -> появи се;
$languages ​​​​-> lang [0] -> създател;

Показването на списък с езици и показването на техните свойства може да се направи много лесно с помощта на стандартен цикъл, като напр за всеки.

foreach ($languages ​​​​-> lang като $lang ) (
printf(
"" ,
$lang [ "име"],
$lang -> се появи,
$lang -> създател
) ;
}

Забележете как получих достъп до името на атрибута lang на елемента, за да получа името на езика. По този начин можете да получите достъп до всеки атрибут на елемент, представен като SimpleXMLElement обект.

Работа с пространства от имена

Докато работите с XML на различни уеб услуги, ще срещнете пространства от имена на елементи повече от веднъж. Нека променим нашите езици.xmlза да покажете пример за използване на пространство от имена:



xmlns:dc =>

> 1972>
> Денис Ричи >
>

> 1995>
> Расмус Лердорф >
>

> 1995>
> Джеймс Гослинг >
>
>

Сега елементът създателсе вписва в пространството на имената dcкоето сочи към http://purl.org/dc/elements/1.1/. Ако се опитате да отпечатате езиковите създатели, като използвате нашия предишен код, това няма да работи. За да прочетете пространства от имена на елементи, трябва да използвате един от следните подходи.

Първият подход е да се използват URI имена директно в кода при достъп до пространството от имена на елементи. Следният пример показва как се прави това:

$dc = $languages ​​​​-> lang [ 1 ] - > деца( "http://purl.org/dc/elements/1.1/") ;
ехо $dc -> създател;

Метод деца()взема пространство от имена и връща дъщерни елементи, които започват с префикс. Необходими са два аргумента, първият от които е XML пространството от имена, а вторият е незадължителен аргумент, който по подразбиране е невярно. Ако вторият аргумент е зададен на TRUE, пространството от имена ще се третира като префикс. Ако е FALSE, тогава пространството от имена ще се третира като пространство от имена на URL.

Вторият подход е да се прочетат имената на URI от документа и да се използват при достъп до пространството на имената на елемента. Това всъщност е по-добър начин за достъп до елементи, защото не е нужно да сте твърдо кодирани към URI.

$namespaces = $languages ​​​​-> getNamespaces (true) ;
$dc = $languages ​​​​-> lang [ 1 ] -> деца (($namespaces [ "dc" ] );

ехо $dc -> създател;

Метод GetNamespaces()връща масив от имена на префикси и свързаните с тях URI. Той приема допълнителен параметър, който е по подразбиране невярно. Ако го настроите като вярно, тогава този метод ще върне имената, използвани в родителските и дъщерните възли. В противен случай той намира пространства от имена, използвани само в родителския възел.

Сега можете да преминете през списъка с езици по следния начин:

$languages ​​​​= simplexml_load_file ("languages.xml" ) ;
$ns = $languages ​​​​-> getNamespaces (true) ;

foreach ($languages ​​​​-> lang като $lang ) (
$dc = $lang -> деца ($ns [ "dc" ] );
printf(
"

%s се появи в %d и беше създаден от %s.

" ,
$lang [ "име"],
$lang -> се появи,
$dc -> създател
) ;
}

Практически пример - Разбор на видео канал от YouTube

Нека да разгледаме пример, който получава RSS емисия от канал в YouTube и показва връзки към всички видеоклипове от него. За да направите това, моля свържете се със следния адрес:

http://gdata.youtube.com/feeds/api/users/xxx/uploads

URL адресът връща списък с най-новите видеоклипове от даден канал в XML формат. Ще анализираме XML и ще получим следната информация за всеки видеоклип:

  • Линк към видео
  • Миниатюрен
  • Име

Ще започнем с търсене и зареждане на XML:

$channel = "Име_на_канал" ;
$url = "http://gdata.youtube.com/feeds/api/users/". $канал. "/качвания" ;
$xml = file_get_contents($url);

$feed = simplexml_load_string ($xml) ;
$ns = $feed -> getNameSpaces (истина);

Ако погледнете XML емисията, можете да видите, че там има няколко елемента образувание, всеки от които съхранява подробна информация за конкретно видео от канала. Но ние използваме само миниатюри на изображения, URL адрес на видеоклип и заглавие. Тези три елемента са потомци на елемента група, което от своя страна е дете на влизане:

>

>



Заглавие… >

>

>

Просто ще преминем през всички елементи влизане, като за всеки от тях ще извлечем необходимата информация. забележи, че играч миниатюраИ заглавиеса в пространството на имената на медиите. Следователно трябва да продължим както в предишния пример. Получаваме имена от документа и използваме пространството от имена при достъп до елементи.

foreach ($feed -> запис като $entry) (
$group = $entry -> children ($ns [ "media" ] );
$group = $group -> group ;
$thumbnail_attrs = $group -> миниатюра [ 1 ] -> атрибути ();
$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, прочетете документацията.


Ако имате някакви въпроси, препоръчваме да използвате нашия

Много примери в тази справка изискват XML низ. Вместо да повтаряме този низ във всеки пример, ние го поставяме във файл, който включваме във всеки пример. Този включен файл е показан в следния примерен раздел. Като алтернатива можете да създадете XML документ и да го прочетете с него simplexml_load_file().

Пример #1 Включете файл example.php с XML низ

$xmlstr =<<


PHP: Зад анализатора


Г-ца. Кодер
Онливия Актора


Г-н. Кодер
Ел Актьор


И така, този език. Това е като език за програмиране. Или е
скриптов език? Всичко се разкрива в тази вълнуваща пародия на ужасите
на документален филм.




7
5


XML;
?>

Простотата на SimpleXML се проявява най-ясно, когато човек извлече низ или число от основен XML документ.

Пример #2 Получаване

включват "example.php" ;

echo $movies -> филм [0]-> сюжет;
?>

И така, този език. Това е нещо като език за програмиране. Или е скриптов език? Всичко се разкрива в тази вълнуваща хорър пародия на документален филм.

Достъпът до елементи в рамките на XML документ, които съдържат символи, които не са разрешени съгласно конвенцията за именуване на PHP (напр. тире), може да бъде осъществен чрез капсулиране на името на елемента в скоби и апостроф.

Пример #3 Получаване

включват "example.php" ;

echo $movies -> movie ->( "great-lines" )-> line ;
?>

Горният пример ще изведе:

PHP решава всички мои уеб проблеми

Пример #4 Достъп до неуникални елементи в SimpleXML

Когато множество екземпляри на елемент съществуват като деца на един родителски елемент, се прилагат нормални техники за итерация.

включват "example.php" ;

$movies = нов SimpleXMLElement ($xmlstr);

/* За всеки възел, ние отразяваме отделно . */
foreach ($movies -> movie -> characters -> character as $character ) (
echo $character -> име, "игран от", $character -> актьор, PHP_EOL;
}

?>

Горният пример ще изведе:

Имоти ( $movies->movieв предишния пример) не са масиви. Те са итерируеми и достъпни обекти.

Пример #5 Използване на атрибути

Досега разгледахме само работата по четене на имена на елементи и техните стойности. SimpleXML може също да има достъп до атрибути на елемент. Осъществявайте достъп до атрибути на елемент точно както бихте направили елементи на an масив.

включват "example.php" ;

$movies = нов SimpleXMLElement ($xmlstr);

/* Достъп до възли на първия филм.
* Изведете и скалата за оценка. */
foreach ($movies -> movie [ 0 ]-> rating as $rating ) (
switch((string) $rating [ "type" ]) ( // Получаване на атрибути като индекси на елементи
случай "палци":
echo $rating, "палец нагоре";
прекъсване;
случай "звезди":
echo $рейтинг, "звезди";
прекъсване;
}
}
?>

Горният пример ще изведе:

7 палеца нагоре5 звезди

Пример #6 Сравняване на елементи и атрибути с текст

За да сравните елемент или атрибут с низ или да го предадете във функция, която изисква низ, трябва да го прехвърлите към низ, като използвате (низ). В противен случай PHP третира елемента като обект.

включват "example.php" ;

$movies = нов SimpleXMLElement ($xmlstr);

if ((низ) $movies -> movie -> title == "PHP: Зад анализатора" ) {!}
печат "Моят любим филм." ;
}

ехо htmlentities ((низ) $movies -> филм -> заглавие);
?>

Горният пример ще изведе:

Любимият ми филм.PHP: Зад анализатора

Пример #7 Сравняване на два елемента

Два SimpleXMLElement се считат за различни дори ако сочат към един и същ елемент от PHP 5.2.0.

включват "example.php" ;

$movies1 = нов SimpleXMLElement ($xmlstr);
$movies2 = нов SimpleXMLElement ($xmlstr);
var_dump($movies1 == $movies2); // невярно от PHP 5.2.0
?>

Горният пример ще изведе:

Пример #8 Използване на XPath

SimpleXML включва вградена поддръжка на XPath. За да намерите всички елементи:

включват "example.php" ;

$movies = нов SimpleXMLElement ($xmlstr);

foreach ($movies -> xpath ("//character") като $character ) (
echo $character -> име, "игран от", $character -> актьор, PHP_EOL;
}
?>

"// " служи като заместващ знак. За да посочите абсолютни пътища, пропуснете една от наклонените черти.

Горният пример ще изведе:

Г-ца. Кодерът, изигран от Onlivia Actora Mr. Кодер, изигран от Ел Актьор

Пример #9 Задаване на стойности

Данните в SimpleXML не трябва да са постоянни. Обектът позволява манипулиране на всички негови елементи.

включват "example.php" ;
$movies = нов SimpleXMLElement ($xmlstr);

$movies -> филм [0]-> символи -> символ [0]-> име = "Miss Coder";

echo $movies -> asXML();
?>

Горният пример ще изведе:

PHP: Зад анализатора Госпожица Кодър Онливия Актора Г-н. Кодер Ел Актьор PHP решава всички мои уеб проблеми 7 5

Пример #10 Добавяне на елементи и атрибути

От PHP 5.1.3 SimpleXML има способността лесно да добавя деца и атрибути.

включват "example.php" ;
$movies = нов SimpleXMLElement ($xmlstr);

$character = $movies -> movie [ 0 ]-> characters -> addChild ("character");
$character -> addChild ( "име", "г-н Анализатор");
$character -> addChild ("актьор", "Джон Доу");

$rating = $movies -> movie [ 0 ]-> addChild ( "рейтинг", "PG");
$rating -> addAttribute ("тип", "mpaa");

echo $movies -> asXML();
?>

Горният пример ще изведе:

PHP: Зад анализатора Г-ца. Кодер Онливия Актора Г-н. Кодер Ел Актьор Г-н. АнализаторДжон Доу И така, този език. Това е нещо като език за програмиране. Или е скриптов език? Всичко се разкрива в тази вълнуваща хорър пародия на документален филм. PHP решава всички мои уеб проблеми 7 5 PG

Пример #11 Оперативна съвместимост на DOM

PHP има механизъм за преобразуване на XML възли между SimpleXML и DOM формати. Този пример показва как човек може да промени DOM елемент на SimpleXML.

$dom = нов DOMDocument;
$dom -> loadXML ( "дрънкане" );
ако (! $dom) (
ехо „Грешка при анализиране на документа“;
изход;
}

$books = simplexml_import_dom($dom);

echo $books -> книга [0]-> заглавие;
?>

Горният пример ще изведе:

преди 4 години

Има общ "трик", който често се предлага за преобразуване на SimpleXML обект в масив, като се изпълнява през json_encode() и след това json_decode(). Бих искал да обясня защо това е лоша идея.

Най-просто, защото целта на SimpleXML е да бъде по-лесен за използване и по-мощен от обикновен масив. Например, можете да пишетеbar -> baz [ "bing" ] ?> и означава същото катоbar [ 0 ]-> baz [ 0 ][ "bing" ] ?> , независимо колко елемента bar или baz има в XML; и ако пишешbar [ 0 ]-> baz [ 0 ] ?> получавате цялото низово съдържание на този възел - включително CDATA секции - независимо дали има и дъщерни елементи или атрибути. Вие също имате достъп до информация за пространството на имената, способността да правите прости редакции на XML и дори способността да „импортирате“ в DOM обект за много по-мощна манипулация. Всичко това се губи при превръщането на обекта в масив, вместо да се четат и разбират примерите на тази страница.

Освен това, тъй като не е проектирано за тази цел, преобразуването в JSON и обратно всъщност ще загуби информация в някои ситуации. Например всички елементи или атрибути в пространство от имена просто ще бъдат отхвърлени и всяко текстово съдържание ще бъде отхвърлено, ако даден елемент също има деца или атрибути. Понякога това няма да има значение, но ако придобиете навика да конвертирате всичко в масиви, в крайна сметка това ще ви ужили.

Разбира се, можете да напишете по-интелигентно преобразуване, което няма тези ограничения, но в този момент не получавате никаква стойност от SimpleXML и трябва просто да използвате функциите на XML Parser от по-ниско ниво или класа XMLReader, за да създадете вашата структура. Все още няма да имате допълнителната удобна функционалност на SimpleXML, но това е вашата загуба.

преди 9 години

Ако трябва да изведете валиден xml във вашия отговор, не забравяйте да зададете тип съдържание на заглавката на xml в допълнение към извеждането на резултата от asXML():

$xml = simplexml_load_file("...");
...
... xml неща
...

//изведете xml във вашия отговор:
header("Content-Type: text/xml");
ехо $xml -> asXML();
?>

преди 1 година

Ако вашият xml низ съдържа булеви стойности, кодирани с "0" и "1", ще срещнете проблеми, когато прехвърлите елемента директно към bool:

$xmlstr =<<

1
0

XML;
$values ​​​​= нов SimpleXMLElement($xmlstr);
$truevalue = (bool)$values->truevalue; // вярно
$falsevalue = (bool)$values->falsevalue; // също е вярно!!!

Вместо това първо трябва да прехвърлите към string или int:

$truevalue = (bool)(int)$values->truevalue; // вярно
$falsevalue = (bool)(int)$values->falsevalue; // невярно

преди 9 години

От файла README:

SimpleXML е предназначен да бъде лесен начин за достъп до XML данни.

SimpleXML обектите следват четири основни правила:

1) свойствата обозначават итератори на елементи
2) цифровите индекси означават елементи
3) нечисловите индекси обозначават атрибути
4) преобразуването на низ позволява достъп до ТЕКСТОВИ данни

Когато итерирате свойства, тогава разширението винаги итерира
всички възли с това име на елемент. Следователно методът children() трябва да бъде
извикан за итерация през подвъзли. Но също така прави следното:
foreach ($obj->node_name като $elem) (
// направи нещо с $elem
}
винаги води до итерация на елементите "node_name". Така че няма повече
необходима е проверка, за да се разграничи броят на възлите от този тип.

Когато даден елемент TEXT се осъществява достъп до данните чрез свойство
тогава резултатът не включва ТЕКСТОВИТЕ данни на поделементите.

Вече известни проблеми
============

Поради проблеми с двигателя в момента не е възможен достъп
поделемент с индекс 0: $object->property.

преди 8 години

Бърз съвет относно xpath заявките и пространствата от имена по подразбиране. Изглежда, че XML-системата зад SimpleXML има същата работа, както вярвам, че използва XML-системата .NET: когато трябва да адресирате нещо в пространството от имена по подразбиране, ще трябва да декларирате пространството от имена с помощта на registerXPathNamespace и след това да използвате неговия префикс за адресирайте иначе в живия елемент на пространството от имена по подразбиране.

$низ =<<

четиридесет какво?
Джо
Джейн

Знам, че това е отговорът - но какъв е въпросът?


XML;

$xml = simplexml_load_string ($string);
$xml -> registerXPathNamespace("def", "http://www.w3.org/2005/Atom");

$nodes = $xml -> xpath ("//def:document/def:title");

?>

преди 8 години

Използването на неща като: is_object($xml->module->admin) за проверка дали действително има възел, наречен "admin", изглежда не работи според очакванията, тъй като simplexml винаги връща обект - в този случай празен - дори ако конкретен възел не съществува.
За мен добрата стара функция empty() изглежда работи добре в такива случаи.

преди 9 години

Въпреки че SimpleXMLElement твърди, че е итерируем, изглежда не изпълнява правилно стандартните интерфейсни функции на Iterator като::next и::reset. Следователно, докато foreach() работи, функции като next(), current() или each() не изглежда да работят, както бихте очаквали - показалецът изглежда никога не се движи или продължава да се нулира.

преди 5 години

Ако кодирането на XML документа не е UTF-8, декларацията за кодиране трябва да се появи непосредствено след version="..." и преди standalone="...". Това е изискване на стандарта XML.

Ако кодирането на XML документ се различава от UTF-8. Декларацията за кодиране трябва да следва непосредствено след версията = "..." и преди standalone = "...". Това изискване е стандартен XML.


Добре

Руски език. руски език
Фатална грешка: Неуловено изключение „Изключение“ със съобщение „Низът не може да бъде анализиран като XML“ в...