Skip to content

Instantly share code, notes, and snippets.

@vasia123
Created December 7, 2012 13:20
Show Gist options
  • Save vasia123/4233238 to your computer and use it in GitHub Desktop.
Save vasia123/4233238 to your computer and use it in GitHub Desktop.
Разбор большого XML файла с помощью PHP
<?php
// convert http://webi.ru/webi_articles/big_xml.html to class
class webi_xml
{
var $webi_depth; // счетчик, для отслеживания глубины вложенности
var $this->webi_tag_open; // будет содержать массив открытых в данный момент тегов
var $this->webi_data_temp; // этот массив будет содержать данные одного тега
private function __construct()
{
$this->webi_depth = 0;
$this->webi_tag_open= array();
}
####################################################
### функция работы с данными
function data ($parser, $data)
{
// добавляем данные в массив с указанием вложенности и открытого в данный момент тега
$this->webi_data_temp[$this->webi_depth][$this->webi_tag_open[$this->webi_depth]]['data'].=$data;
}
############################################
####################################################
### функция открывающих тегов
function startElement($parser, $name, $attrs)
{
// если уровень вложенности уже не нулевой, значит один тег уже открыт
// и данные из него уже в массиве, можно их обработать
if ($this->webi_depth)
{
// здесь начинается обработка данных, например добаление в базу, сохранение в файл и т.д.
// $this->webi_tag_open содержит цепочку открытых тегов по уровню вложенности
// например $this->webi_tag_open[$this->webi_depth] содержит название открытого тега чья информация сейчас обрабатывается
// $this->webi_depth уровень вложенности тега
// $this->webi_data_temp[$this->webi_depth][$this->webi_tag_open[$this->webi_depth]]['attrs'] массив атрибутов тега
// $this->webi_data_temp[$this->webi_depth][$this->webi_tag_open[$this->webi_depth]]['data'] данные тега
print 'данные '.$this->webi_tag_open[$this->webi_depth].'--'.($this->webi_data_temp[$this->webi_depth][$this->webi_tag_open[$this->webi_depth]]['data']).'<br>';
print_r($this->webi_data_temp[$this->webi_depth][$this->webi_tag_open[$this->webi_depth]]['attrs']);
print '<br>';
print_r($this->webi_tag_open); // массив открытых тегов
print '<hr>';
// после обработки данных удаляем их для освобождения памяти
unset($this->webi_data_temp[$this->webi_depth]);
}
// теперь пошло открытие следующего тега и дальше обработка его произойдет на следующем шаге
$this->webi_depth++; // увеличиваем вложенность
$this->webi_tag_open[$this->webi_depth]=$name; // добавляем открытый тег в массив информаци
$this->webi_data_temp[$this->webi_depth][$name]['attrs']=$attrs; // теперь добавляем атрибуты тега
}
###############################################
#################################################
## функция закрывающих тегов
function endElement($parser, $name)
{
// здесь начинается обработка данных, например добаление в базу, сохранение в файл и т.д.
// $this->webi_tag_open содержит цепочку открытых тегов по уровню вложенности
// например $this->webi_tag_open[$this->webi_depth] содержит название открытого тега чья информация сейчас обрабатывается
// $this->webi_depth уровень вложенности тега
// $this->webi_data_temp[$this->webi_depth][$this->webi_tag_open[$this->webi_depth]]['attrs'] массив атрибутов тега
// $this->webi_data_temp[$this->webi_depth][$this->webi_tag_open[$this->webi_depth]]['data'] данные тега
print 'данные '.$this->webi_tag_open[$this->webi_depth].'--'.($this->webi_data_temp[$this->webi_depth][$this->webi_tag_open[$this->webi_depth]]['data']).'<br>';
print_r($this->webi_data_temp[$this->webi_depth][$this->webi_tag_open[$this->webi_depth]]['attrs']);
print '<br>';
print_r($this->webi_tag_open);
print '<hr>';
unset($this->webi_data_temp); // после обработки данных удаляем массив с данными целиком, так как произошло закрытие тега
unset($this->webi_tag_open[$this->webi_depth]); // удаляем информацию об этом открытом теге... так как он закрылся
$this->webi_depth--; // уменьшаем вложенность
}
############################################
function start($file) {
$xml_parser = xml_parser_create();
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, true);
// указываем какие функции будут работать при открытии и закрытии тегов
xml_set_element_handler($xml_parser, Array(&$this, "startElement"), Array(&$this, "endElement"));
// указываем функцию для работы с данными
xml_set_character_data_handler($xml_parser, Array(&$this, '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 "<br>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);
}
}
$newClass = new webi_xml(); // Создаем экземпляр класса
$newClass->start($file); // Запускаем файл
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment