Как разобрать xml файл php

Обновлено: 04.07.2024

Frontend / Backend developer

Парсинг XML с помощью XMLReader на PHP

XMLReader это потоковый XML парсер, способный обрабатывать большие объемы данных при низких затратах оперативной памяти.

XMLReader использует курсор для перемещения по структуре документа, без создания DOM дерева, как это делает, к примеру SimpleXML. Обрабатывать документы, конечно становится немного сложнее, но минимальные затраты драгоценной памяти и возможность обрабатывать огромные массивы данных, я думаю, перекрывают этот недостаток.

Самый простой пример использования XMLReader.

Предположим, у нас стоит задача импорта из XML в нашу базу данных.

Вот XML структура (файл example.xml) :

Для разбора этой, относительно несложной структуры, достаточно такого кода:

Таким образом, мы решили задачу об импорте из xml:

Dive into XMLReader

С парсингом простых структур понятно, но что делать если есть структуры непростые? Писать каждый раз цикл чтения и кучу условий как-то не по взрослому, да и правки всего этотого кода в случае изменения структуры могут обернуться тем еще баттхёртом.

Для себя я нашел простое, но достаточно практичное решение - я написал несколько оберток для работы с XMLReader, и то что получилось, меня пока что полностью удовлетворяет.

Итак, стояла задача обмена конфигурацией web-приложения с 1с. Обмен производится в виде XML документов с общими настройками приложения и ценообразования.

Вот пример конфигурационного xml файла, приходящего в приложение из 1с:

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

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

Но довольно слов, приступим к коду:

Сперва нужно разработать общий базовый класс для оберток над этой библиотекой. Назовем наш абстрактный класс AbstractAdvertisementXMLReader.

Первое что нужно сделать - это объявить переменные-члены и создать конструктор:

В конструкторе мы пытаемся инициализировать XMLReader, и открыть с помощью него переданный путь к xml файлу.

Тут все достаточно просто и наглядно.

Теперь давайте реализуем необходимые акцессоры:

Реализация событийной модели:

Соответственно, теперь у нас есть два метода - onEvent и fireEvent - являющиеся по сути реализацией паттерна Pub/Sub.

В качестве параметров, подписчики дополнительно получают контекст, т.е. ссылку на вызывающий объект AbstractAdvertisementXMLReader (либо класс его наследующий).

Осталось добавить в этот класс щепотку базовой логики:

Вот и все, базовый класс полностью готов!

Далее я покажу как можно использовать все это безобразие.

Как видим, все просто и понятно.

Далее самое вкусное - вызывающий код:

Вот таким нехитрым способом можно парсить большие и достаточно сложные XML файлы.

Работа с XML в PHP

Инструмент XMLWriter был создан специально для записи в XML формате. Один из важных его методов это startDocument(), который позволяет задать кодировку версии XML.

Попробуем создать простенький XML следующего вида:

<?xml version = "1.0" ?>
<Customer>
<id> 1 < / id>
<name> Марк < / name>
< address > Санкт-Петербург < / address >
< / Customer>

Получить такой формат можно с помощью XMLWriter таки вот образом:

<xml version = "1.0" ?>
<purchase>
<customer>
<id> 1 < / id>
<time> 2013-04-19 10:56:03 < / time>
<total> $350 < / total>
< / customer>
<customer>
<id> 2 < / id>
<time> 2013-04-23 13:43:41 < / time>
<total> $1456 < / total>
< / customer>
< / purchase>

Чтобы получить такую структуру нужно выполнить ряд не хитрых методов класса XMLWriter.

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

<?xml version = "1.0" ?>
<products>
<product pid = "314" >
<name> Яблоко < / name>
<price> $1.00 < / price>
<discount> 3% < / discount>
< / product>
<product pid = "315" >
<name> Манго < / name>
<price> $0.90 < / price>
<discount> 3% < / discount>
< / product>
< / products>

С помощью XMLWriter, делается это так:

Ниже будет приведен пример чтения и получения данных из XML с использованием классов XMLReader и SimpleXMLElement. Читать будем уже имеющийся XML объект, который мы создали в примере №1 при PHP записи в XML.

XMLReader используется для получения заданного узла из XML.

Часто задача возникает в получении данных из XML по значению, какого либо атрибута. Давайте по примеру №2 из раздела PHP запись в XML, получим название, цену и скидку продукта по его атрибуту pid = 315.

Работая с XML в PHP, не редко приходится ломать голову над тем как добавить новый элемент в имеющуюся XML структуру. Используя XMLWriter и SimpleXMLElement сделать это очень легко:

//Добавим новый узел в имеющийся XML
$sXML = new SimpleXMLElement($nXML2); // загрузка в XML
$newchild = $sXML->addChild("product");
//Добавление параметров записи
$newchild->addAttribute("pid", 328);
$newchild->addChild("name", "Банан");
$newchild->addChild("price", "$3.00");
$newchild->addChild("discount", "0.3%");
echo $sXML->asXML();

При активной работе с XML в PHP, приходится не только считывать и записывать элементы, но и редактировать имеющиеся. Перезапись существующего узла дерева XML может быть реализована следующим образом:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

/**
* Перезапись узлов дерева XML формата.
*/

Из всего выше рассмотренного, осталась только одна операция, без которой данную статью о работе с XML в PHP , нельзя считать завершенной – это удаление элементов. Удаление элементов самое легкое из всей связки операций. Ну что же, ломать – не стоить, давайте удалим один из продуктов.

Закрыть текущий элемент (тэг) в xmlwriter

Найдя время и отвлекшись от основного своего проекта, я всё-таки опубликовал действительно полезную статью "Работа с XML в PHP", и надеюсь она пригодится в своих разработках. Пишите мне на e-mail, с какими задачами вы сталкиваетесь, и я попробую сформировать материал по их решению в следующих статьях




Чтобы не пропустить публикацию следующей статьи подписывайтесь на рассылку по E-mail или RSS ленту блога.

Эта функция разбирает XML строку и помещает данные в 2 массива. Массив index содержит указатели на размещение значений в массиве values . Аргументы, задающие массивы, должны передаваться в функцию по ссылке.

Список параметров

Ссылка на используемый XML анализатор.

Строка XML данных.

Массив значений XML данных.

Массив указателей на соответствующие значения в массиве $values.

Возвращаемые значения

xml_parse_into_struct() возвращает 0 при неудачном разборе строки и 1 при успешном. Это не тоже самое, что FALSE и TRUE , будьте осторожны с такими операторами, как ===.

Примеры

Ниже представлен пример, демонстрирующий внутреннее устройство массивов, генерируемых функцией. XML строка содержит простой тэг note вложенный в тэг para. Программа в примере разбирает эту строку и выводит построенные массивы:

<?php
$simple = "<para><note>simple note</note></para>" ;
$p = xml_parser_create ();
xml_parse_into_struct ( $p , $simple , $vals , $index );
xml_parser_free ( $p );
echo "Index array\n" ;
print_r ( $index );
echo "\nМассив Vals\n" ;
print_r ( $vals );
?>

После обработки программа выведет следующее:

Управляемый событиями разбор (основанный на expat библиотеке) может дать труднообрабатываемый результат в случае, если разбирается составной XML документ. Эта функция не создает DOM объектов, но создаваемые ею массивы можно преобразовать в древовидную структуру впоследствии. Таким образом можно довольно просто создавать объекты, представляющие содержимое XML файла. Предположим, что следующий XML файл представляет небольшую базу данных с информацией об аминокислотах:

Код, разбирающий документ и создающий подходящие объекты:

class AminoAcid var $name ; // название аминокислоты
var $symbol ; // трехбуквенное обозначение
var $code ; // однобуквенный код
var $type ; // гидрофобная, заряженная, нейтральная

function AminoAcid ( $aa )
foreach ( $aa as $k => $v )
$this -> $k = $aa [ $k ];
>
>

function readDatabase ( $filename )
// чтение XML базы данных аминокислот
$data = implode ( "" , file ( $filename ));
$parser = xml_parser_create ();
xml_parser_set_option ( $parser , XML_OPTION_CASE_FOLDING , 0 );
xml_parser_set_option ( $parser , XML_OPTION_SKIP_WHITE , 1 );
xml_parse_into_struct ( $parser , $data , $values , $tags );
xml_parser_free ( $parser );

// проход через структуры
foreach ( $tags as $key => $val ) if ( $key == "molecule" ) $molranges = $val ;
// каждая смежная пара значений массивов является верхней и
// нижней границей определения молекулы
for ( $i = 0 ; $i < count ( $molranges ); $i += 2 ) $offset = $molranges [ $i ] + 1 ;
$len = $molranges [ $i + 1 ] - $offset ;
$tdb [] = parseMol ( array_slice ( $values , $offset , $len ));
>
> else continue;
>
>
return $tdb ;
>

function parseMol ( $mvalues )
for ( $i = 0 ; $i < count ( $mvalues ); $i ++) $mol [ $mvalues [ $i ][ "tag" ]] = $mvalues [ $i ][ "value" ];
>
return new AminoAcid ( $mol );
>

Парсинг XML-документа на PHP

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

Предлагаю парсить созданный нами в прошлой статье документ, а данные оттуда просто вывести в браузер. Привожу код скрипта:

<?php
$dom = new domDocument("1.0", "utf-8"); // Создаём XML-документ версии 1.0 с кодировкой utf-8
$dom->load("users.xml"); // Загружаем XML-документ из файла в объект DOM
$root = $dom->documentElement; // Получаем корневой элемент
$childs = $root->childNodes; // Получаем дочерние элементы у корневого элемента
/* Перебираем полученные элементы */
for ($i = 0; $i < $childs->length; $i++) $user = $childs->item($i); // Получаем следующий элемент из NodeList
$lp = $user->childNodes; // Получаем дочерние элементы у узла "user"
$id = $user->getAttribute("id"); // Получаем значение атрибута "id" у узла "user"
$login = $lp->item(0)->nodeValue; // Получаем значение узла "login"
$password = $lp->item(1)->nodeValue; // Получаем значение узла "password"
/* Выводим полученные данные */
echo "ID: $id<br />";
echo "Логин: $login<br />";
echo "Пароль: $password<br />";
echo "-----------------------<br />";
>
?>

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


Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления

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

Порекомендуйте эту статью друзьям:

Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):

Она выглядит вот так:

Комментарии ( 8 ):

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

Михаил, У меня в Вам вопрос! У меня дома 4 компьютера! Один из них я хочу сделать сервером, а не загружать сайт на хостинг! Обьясните пожалуйста как это сделать, что нужно установить или создать и куда закинуть свой сайт! Спасибо.

Я постараюсь написать об этом статью в ближайшее время.

Здравствуйте Михаил! Обьясните пожалуйста как вставить шаблон сделанный в фотошоп на страницу? Ведь этот шаблон будет картинкой! Тогда как сделать чтобы при нажатии на кнопку например пользователь переходил на другую страницу?

Михаил, подскажите. Приведенный выше код работает отлично. Но стоит мне навести порядок в xml файле - расставить переносы строк и сделать табуляцию, php парсер перестает работать. И выдает ошибку: Fatal error: Call to undefined method DOMText::getAttribute() in Z:\home\school\www\xmlparse\index.php on line 10 И за чего возникает эта ошибка?

Читайте также: