Парсинг определенных тегов из xml в php. Парсинг XML с помощью SimpleXML. SimpleXML в действии

Xml парсер - это программа, которая извлекает из исходного файла xml формата данные и сохраняет или использует для последующих действий.

Почему нужны xml парсеры?

В первую очередь потому что сам по себе формат xml популярный среди компьютерных стандартов. XML файл выглядит так:

т.е. по сути есть теги, есть какие-то правила какие теги должны следовать друг за другом.

Причина популярности xml файлов заключается в том, что он хорошо читаем человеком. И то, что его относительно легко обрабатывать в программах.

Минусы xml-файлов.

Минусом является в первую очередь большое количество места на диске, которое занимают эти данные. Ввиду того, что теги, которые постоянно повторяются, при больших объемах данных, занимаю относительно много мегабайт, которые просто необходимо скачивать из источника, а потом и обрабатывать. Есть ли альтернативы? Есть, конечно, но все равно, парсеры xml и xml сегодня один из самых простых и надежных и технологически популярных форматов.

Как пишутся XML парсеры?

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

Глобально есть 2 разных подхода как парсить xml файлы.

Первый - это загружать xml файл полностью в память ну и дальше делать манипуляции по извлечению данных.

Второй - это потоковый вариант. В этом случае в языке программирования определяется определенные теги на которые нужно реагировать функциям создаваемого xml парсера и уже программист сам решает, что нужно делать в случае обнаружения того или иного тега.

Плюсом первого подхода является скорость. Сразу все загрузил файл, потом быстро пробежался в памяти нашел, что нужно и самое главное программировать легко. но Минус есть и очень важный - это

большой объем памяти требуется для работы. Иногда, я бы даже сказал часто бывает так, что просто невозможно обработать и распарсить xml файл, т.е. создать xml парсер, чтобы работал по первому способу корректно. Почему так? Ну, например, ограничение для 32 битных приложений под виндой позволяет программе максимально занимать 2 гигабайта памяти - больше нельзя.

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

Валидность xml файлов и парсеров.

Все было бы с xml файлами и xml парсерами хорошо, но вот есть проблема. Ввиду того, что создать xml файл может "любой школьник", а в реальности так и есть (потому что очень много кода пишется школьниками, то появляются невалидные файлы, т.е. некорректные. Что это значит и чем это чревато? Самая большая проблема, это то, что просто невозможно иногда корректно распарсить невалидный файл. Например у него теги не закрываются как следовало бы ожидать по стандарту или например кодировка задана неверно. Другая проблема заключается, что если например делаешь парсер на.net то, можно создать так называемые врапперы, и самое обидное бывает, что вот сделаешь такой враппер, а потом считываешь им файл, который "школьник" создал, а файл невалидный и его прочитать невозможно. Поэтому приходиться изгаляться и прибегать к весьма и весьма непопулярным вариантам парсинга таких файлов. А все из=за того, что многие создают xml файлы без использования стандартных библиотек и с полным отвращениям ко всем стандартам xml файлов. Заказчикам это сложно объяснить. Они ждут результат - xml парсер, который преобразует данные из оригинального файла в другой формат.

Как создавать xml парсеры (первый вариант)

Есть такой язык запросов к XML данным как Xpath. Язык этот имеет две редакции, углубляться не будем в особенности каждой версии. Лучше представление про этот язык покажут примеры того как использовать его для извлечения данных. Например.

//div[@class="supcat guru"]/a

что делает этот запрос. Он забирает все а тэги, которые имею хреф, содержаший текст catalog.xml?hid= и этот а тэг должен быть чайлдом дива у которого класс равен supcat guru.

Да, на первый раз может быть и не достаточно понятно, но, все же разобраться можно если захотите. Отправная точка для меня это http://ru.wikipedia.org/wiki/XPath и вам советую.


публикация данной статьи разрешена только со ссылкой на сайт автора статьи

В этой статье я покажу пример, как разобрать большой XML файл. Если на вашем сервере (хостинге) не запрещено увеличение времени работы скрипта, то можно разбирать XML файл весом хоть гигабайты, сам лично разбирал только файлы от озона весом 450 мегабайт.

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

Вторую проблему с временем решить можно, если сервером это не запрещено.
А вот проблему с памятью решить сложно, даже если речь идет о своем сервере, то ворочать файлы по 500 мегабайт не очень просто а уж на хостинге и на VDS увеличить память просто не получится.

В PHP существует несколько встроенных вариантов обработки XML - SimpleXML, DOM, SAX.
Все эти варианты подробно описаны во многих статьях с примерами, но все примеры демонстрируют работу с полным XML документом.

Вот один из примеров, получаем объект из 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;}


echo "

break;
}

$data = "" ;
}
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 , "data" );

Дальше идет открытие указанного файла, перебор файла по одному символу и каждый символ добавляется в строковую переменную пока не будет найден символ > .
Если это самое первое обращение к файлу, то попутно будет удалено все что будет лишним в начале файла, все что стоит до , именно с такого тега должен начинаться 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 будет равна 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 , "

// теперь кидаем данные в разборщик 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 на мастерхосте, но об этом не в этой статье.

28.3K

Я видел много xml parser`ов, но не затрагивал при этом веб-программирование. Теперь же я хочу выяснить и научиться вместе с вами, как сделать простой xml parser в php.

А зачем? Надо!

Не, ну на самом деле: xml-файлы — очень полезная штука. И любой профессионал должен… нет, не должен, а обязан знать, как с ними работать. Мы же хотим стать профессионалами? Если Вы на моем блоге, то такое желание у Вас есть.

Мы предполагаем, что знаем, что такое XML и описывать его здесь не будем. Ну, если не знаем, то легко узнаем здесь: http://ru.wikipedia.org/wiki/XML

При поиске способов парсинга XML на PHP, я обнаружил простой набор функций в PHP для работы с XML-файлами, который называется «XML Parser Functions». Парсинг начинается с инициализации парсера вызовом функции 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 Error: ".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 и попытаемся его распарсить с помощью следующего кода:

Element: $name
"; // имя элемента $depth++; // увеличиваем глубину, чтобы браузер показал отступы foreach ($attrs as $attr => $value) { echo str_repeat(" ", $depth * 3); // отступы // выводим имя атрибута и его значение echo "Attribute: ".$attr." = ".$value."
"; } } function endElement($parser, $name) { global $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("could not open XML input"); } while ($data = fgets($fp)) { if (!xml_parse($xml_parser, $data, feof($fp))) { echo "
XML Error: "; 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); ?>

В результате разработанного нами простейшего скрипта браузер вывел в свое окно следующую информацию:

Element: ROOT
Element: INFO
Attribute: WHO = моя
Element: ADDRESS

Attribute: KVARTIRA = 12
Attribute: DOM = 15
Element: PHONE

Попробуем испортить XML-файл, заменив тег На , а закрывающий тег оставив прежним:

Element: ROOT
Element: INFO
Attribute: WHO = моя
Element: ADDRESS
Attribute: ULICA = моя улица!!
Attribute: KVARTIRA = 12
Attribute: DOM = 15
Element: TELEPHONE

XML Error: Mismatched tag at line 5

Ух ты! Сообщения об ошибках работают! Причем довольно информативные.

Эх, я забыл еще одну вещь… Мы же не вывели текст, содержащийся внутри тегов address и phone. Исправляем наш недочет — добавляем текстовый обработчик с помощью функции xml_set_character_data_handler:

xml_set_character_data_handler($xml_parser, ’stringElement’);

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

Вот и лето пришло и первая неделя июля пролетела незаметно. Через две недели мне защищать свой диплом, а одна из частей его – XML parser . Но жалко, что не в пхп. Ну ниче, счас наверстаем

Я видел много xml parser`ов, но не затрагивал при этом веб-программирование. Теперь же я хочу выяснить и научиться вместе с вами, как сделать простой xml parser в php.

А зачем? Надо!

Не, ну на самом деле: xml-файлы – очень полезная штука. И любой профессионал должен… нет, не должен, а обязан знать, как с ними работать. Мы же хотим стать профессионалами? Если Вы на моем блоге, то такое желание у Вас есть.

Мы предполагаем, что знаем, что такое XML и описывать его здесь не будем. Ну, если не знаем, то легко узнаем здесь: http://ru.wikipedia.org/wiki/XML

При поиске способов парсинга XML на PHP, я обнаружил простой набор функций в PHP для работы с XML-файлами, который называется «XML Parser Functions ». Парсинг начинается с инициализации парсера вызовом функции xml_parser_create:

$xml_parser = xml_parser_create();

Потом нам нужно сказать парсеру, какие функции будут обрабатывать попадающиеся ему xml-теги и текстовую информацию в процессе парсинга. Т.е. нужно установить некие обработчики:

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

Эта функция отвечает за установку обработчиков начала элемента и конца элемента. Например, если в тексте xml-файла встретится комбинация, то функция startElement сработает, когда парсер найдет элемент, а функция endElement – при нахождении.

Сами же функции startElement и endElement принимают несколько параметров согласно документации по php:



// (т.к. мы можем использовать несколько парсеров)

// $attrs - массив атрибутов обнаруженного элемента
}function endElement($parser, $name) {
// $parser - уникальный идентификатор парсера
// $name - имя обнаруженного элемента
}
?>

А как же считывать данные из файла? Мы же пока не видели ни одного параметра для этого ни в одной из функций! А об этом дальше: считывание файла возлагается на плечи программиста, т.е. мы должны использовать стандартные функции для работы с файлами:

Открыли файл. А теперь нужно построчно считывать его и скармливать считываемые строки функции xml_parse:

Здесь заметим две очень важные вещи. Первая – это то, что функции 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 и попытаемся его распарсить с помощью следующего кода:

function startElement($parser, $name, $attrs) {
global $depth;echo str_repeat (" ", $depth * 3); // отступы
echo "Element: $name
"; // имя элемента

$depth++; // увеличиваем глубину, чтобы браузер показал отступы

xml_set_element_handler ($xml_parser, "startElement", "endElement");

if (!($fp = fopen ($file, "r"))) {
die ("could not open XML input");
}

while ($data = fgets ($fp)) {
if (!xml_parse ($xml_parser, $data, feof ($fp))) {
echo "
XML Error: ";
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);
?>

В результате разработанного нами простейшего скрипта браузер вывел в свое окно следующую информацию:

Element: ROOT Element: INFO Attribute: WHO = моя Element: ADDRESS Attribute: ULICA = моя улица!! Attribute: KVARTIRA = 12 Attribute: DOM = 15 Element: PHONE

Попробуем испортить XML-файл, заменив тег На , а закрывающий тег оставив прежним:

Element: ROOT Element: INFO Attribute: WHO = моя Element: ADDRESS Attribute: ULICA = моя улица!! Attribute: KVARTIRA = 12 Attribute: DOM = 15 Element: TELEPHONE

XML Error: Mismatched tag at line 5

Ух ты! Сообщения об ошибках работают! Причем довольно информативные.

Эх, я забыл еще одну вещь… Мы же не вывели текст, содержащийся внутри тегов address и phone. Исправляем наш недочет – добавляем текстовый обработчик с помощью функции xml_set_character_data_handler:

xml_set_character_data_handler($xml_parser, ’stringElement’);

И добавляем в код саму функцию-обработчик:

Посмотрим теперь на вывод:

Element: ROOT Element: INFO Attribute: WHO = моя Element: ADDRESS Attribute: ULICA = моя улица!! Attribute: KVARTIRA = 12 Attribute: DOM = 15 String: 123 Element: PHONE String: +71234567890

О! Теперь вывели все!

Кстати, кто-нибудь заметил, что имена тегов и атрибутов все большими буквами написаны? Странно… они же в нашем xml-файле малыми буквами обозначены. Видимо где-то какие-то настройки установлены, чтобы делать uppercase…

Ааа, нашел! Оказывается есть еще функция xml_parser_set_option:

xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, 0);

Таким вызовом мы отменяем вывод имен атрибутов и имен тегов большими буквами:

Element: root Element: info Attribute: who = моя Element: address Attribute: ulica = моя улица!! Attribute: kvartira = 12 Attribute: dom = 15 String: 123 Element: phone String: +71234567890

В этой статье мы рассмотрели самый простой, но для большинства задач достаточный метод вытаскивания информации из XML-файлов. Я еще слышал про какие-то другие более мощные методы, но их буду рассматривать, когда сам изучу немного

nika, Вам нужно вставить вызов
xml_set_character_data_handler($xml_parser, ’stringElement’);
после
xml_set_element_handler($xml_parser, “startElement”, “endElement”);

В общем для правильного отображения нужно соблюдать следующее:
1. нужно, чтобы xml-файл был в кодировке UTF-8
2. в xml-файле первая строчка должна быть такой:
< ?xml version="1.0" encoding="UTF-8"?>
3. нужно инициализировать парсер так:
xml_parser_create(”UTF-8?);
4. нужно перед выводом содержимого xml-файла в браузер настроить последний на кодировку UTF-8:
header(“Content-Type: text/html; charset=utf-8?);

Для отображения текста на русском языке используем
iconv(”UTF-8?,”windows-1251?, $attr), где $attr, то что нужно вывести.

Есть такие два класса интересных в стандартной библеотеке PHP5 – DOMDocument() и XSLTProcesor() использовал на довольно крупных проектах – не жалуюсь =)

Вообще у PHP есть еще одна библиотечка для разбора XML по принципу SAX – называется XMLReader.

    Господа, как вывести из xml с помощью simplexml не стандартные теги, например?
    Переменная вида $text = $item->yandex:full-text не работает.

    Все ОК, только обратите внимание на наличие следующего параметра,

    function cdata($parser, $cdata)
    {
    var_dump($parser, $cdata);
    }

    xml_set_character_data_handler($this->parser, “cdata”);

    Без него не хочет парсить XML с CDATA…. размером в 1.5 метра

    2Nika, Функция header() работает только в том случае, если до нее не было ничего выведено, то бишь первым действие производили ее, т.к. мы отсылаем заголовки на эту страницу, которые говорят нам, что текст нужно переводить в кодировку UTF-8. Судя по вашей ошибке у вас есть пропуски строк, поэтому сделайте вот так:

    Значение == порядковый номер строки
    header(”Content-Type: text/html; charset=utf-8?); == 2

    Всё намного проще делается в действительности
    yurban.ru/development/php_xml_parser

→ Для чего нужны XML-парсеры и чем они могут быть полезны

Если вы имеется отношение к созданию сайтов, вы наверняка слышали об XML, даже если ещё не использовали его в работе. В таком случае, настало время познакомиться, ведь пережив настоящий бум, за последний десяток лет этот новый формат вырос из новаторского проекта в настоящий промышленный стандарт, и чуть ли не ежедневно появляются сообщения о примерах его успешного использования.

Одной из важнейших составляющих XML-технологии является специальный класс программ, отвечающих за анализ документов и извлечение необходимой информации - парсеры. Именно о них и пойдет речь в этой статье. Разберемся, для чего нужны парсеры, какие они бывают и где их можно достать.

Вообще XML-документ - это простой текстовый файл, в котором при помощи специальных синтаксических конструкций (их называют "тегами") сохраняется необходимая структура данных. Это позволяет хранить информацию не сплошным массивом, а в виде иерархически связанных фрагментов. Так как текстовые файлы очень легко создавать и передавать по сети, они являются крайне удобным способом хранения информации и широко используются при создании сложных распределенных приложений.

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

Что же это такое? XML-парсер - это программа, предназначенная для анализа содержимого текстового документа, который соответствует спецификации XML. Ей достается вся "чёрная" работа: получение общих сведений о документе, анализ текста, поиск в нем служебных конструкций (элементов, атрибутов, сущностей и т.п.), проверка на соблюдение синтаксических правил, а также предоставление интерфейса для доступа к документу. В результате аккуратно извлеченные данные, будут переданы пользовательскому приложению, которое может вообще ничего не знать о том, что такое XML.

Парсер может быть выполнен в виде отдельного программного модуля или ActiveX-компонента, может подключаться к приложению через специальные библиотеки классов на этапе компиляции или выполнения. Парсеры делятся на верифицирующие (validating) и неверифицирующие (non-validating). Первые могут проверять структуру документа на основе DTD или схем данных, вторые же об этом не заботятся - и потому имеют, как правило, меньший размер. Многие из современных парсеров "нагружены" многочисленными дополнительными возможностями (расширенная обработка ошибок, добавление и редактирование данных), что делает их более удобными в работе, хотя и повышает размер программ. Практически все распространенные парсеры поддерживают также ряд важных XML-стандартов (XSLT, схемы данных, Name spaces, XPath и т.д.) - или же поставляются в связке с парсерами других производных от него языков.

Если вы осознали полезность парсера для XML, то пора начинать практические опыты. Где же их взять? Особых проблем с поиском соответствующего софта возникнуть не должно: в Интернете полно свободно распространяемых парсеров, написанных на всевозможных языках программирования, работающих на всех платформах и имеющих самые разные характеристики и предназначение.

Наиболее распространенным и известным является парсер Expat, написанный Джеймсом Кларком - одним из создателей спецификации XML. Он реализован на языке программирования C++ и распространяется вместе с исходным кодом. Кстати, поддержка этого языка разметки в таких известных средах, как РНР и Perl, реализована именно на его основе. Другой распространенный парсер - Xerces, есть в Apache XML Project (реализован на языках Java и C++). Можно найти много парсеров для C++, Perl и Python. Основная их масса написана на Java, и годится для любой платформы, знакомой с Java. Не остались в стороне и лидеры рынка (Microsoft, Oracle, Sun), всегда отличающиеся масштабностью и монументальностью. Они выпустили более "тяжеловесные" и функциональные пакеты, которые содержат, помимо собственно парсеров, множество дополнительных утилит, облегчающих жизнь разработчиков.

Разумеется, невозможно рассказать всё об парсерах в рамках одной заметки. Но хотелось бы надеяться, что вы поняли - работа с XML не так трудна, как может показаться. Все сложности этого формата скрыты от нас внутри парсеров, и нет никаких причин бояться внедрять новый формат в существующие проекты.