Создание XML файлов из массивов на PHP

15 декабря, 2008
php array xml

Сегодня речь пойдет о работе с XML, а точнее об отправке данных PHP скриптов браузеру в формате XML.

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

Постановка задачи

Есть PHP массив (может быть многомерным). Нужно получить xml строку с данными из этого массива.

Немного теории

В дистрибутив PHP входит модуль XMLWriter, который предназначен для записи данных в XML формате. Использовать непосредственно этот модуль в своих скриптах не очень удобно, т.к. он поддерживает только самые базовые функции и преобразование массива в этот формат «выливается» в несколько десятков строк кода.

Поэтому мы напишем собственный класс (Array2XML), который будет представлять собой оболочку для XMLWriter'а и решать одну узкую задачу – преобразовывать PHP массив в XML формат.

Прежде чем переходить к коду класса покажу, как им пользоваться.

require_once('Array2XML.php');

header('Content-type: application/xml');

$data = array(
	'val1' => 111,
	'val2' => '222',
	'val3' => 333,
	500,
	'container' => array(
		'mystr' => 'test test',
		'myobj' => array(
			'x' => 250,
			'y' => 150,
			'name' => 'objName'
		)
	)
);

$converter = new Array2XML();
$xmlStr = $converter->convert($data);

echo $xmlStr;

Как видите, после подключения файла с классом и установки заголовка (строки 1, 3), мы объявили массив с данными.

Обратите внимание. Не для всех элементов массива явно заданы имена ключей.

После этого, мы создаем объект типа Array2XML() и вызываем его метод convert. В качестве параметра этот метод получает наш массив. Как несложно догадаться, после его выполнения мы получим XML документ с данными из массива.

И сразу же покажу скриншот страницы с результатом работы скрипта.

xml data

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

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

Единственное отличие в названиях касается элементов массива, для которых явно не заданы ключи. PHP присваивает им порядковые номера, но число нельзя использовать в качестве XML тега. Поэтому я добавил к его номеру приставку «key». Лучше, конечно, задавать ключи для всех элементов массива явно.

Теперь переходим непосредственно к классу


Прежде всего, в конструкторе мы создаем объект типа XMLWriter. С помощью которого, будем выполнять всю рутинную работу.

Теперь, обратите внимание на метод convert (строки 14-23). В качестве единственного параметра он получает массив с данными.

Метод openMemory() начинает запись нового XML документа.

startDocument – вставляет заголовок.

startElement($this->rootName) – создает корневой тег. По-умолчанию, используется имя root, но его можно изменить.

После этого, мы проверяем, являются ли полученные данные массивом (строка 18) и вызываем метод getXML (строки 33-47), который и выполняет преобразование массива в XML формат.

Рассмотрим его подробнее. Алгоритм следующий:
1) обходим в цикле массив;
  1.1) если ключ текущего элемента является числом, добавляем к нему приставку «key»;
  1.2) если текущий элемент является массивом:
    1.2.1) создаем открывающий тег, в качестве названия используем ключа данного элемента (строка 39);
    1.2.2) вызываем метод getXML, а в качестве параметра передаем текущий элемент, т.е. вложенный массив (рекурсия);
    1.2.3)создаем закрывающий тег;
  1.3) создаем тег для текущего элемента массива (с помощью метода writeElement)

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

Кроме того, класс содержит методы, которые позволяют указать версию XML, кодировку и имя корневого тега (setVersion, setEncoding, setRootName).

Как видите, класс получился довольно простой, но вполне работоспособный :-)

Скачать

Вы можете скачать архив с этим примером.

P.S. Если у вас есть аналогичное решение буду рад обсудить ;)

Интересно почитать:

Оптимизация сайтов - единственный способ вырваться в ТОП поисковиков.
Хотите отдохнуть и расслабиться? Японский сад создаст нужное настроение.
Забудьте о CD болванках. DVD диски превосходят их по всем параметрам. dvd купить киев

Понравилась статья? Подписывайтесь на продолжение rss link !

Или на мой твиттер twitter link

]]>

Добавьте эту страницу в google.com bobrdobr.ru del.icio.us technorati.com linkstore.ru news2.ru rumarkz.ru memori.ru moemesto.ru

]]>

Опубликовано в PHP, Web разработка Комментарии (55) »

]]>

Вы можете оставить комментарий. Трекбеки закрыты.

  • http://mefolio.ru/ Евгений

    Спасибо, странно, никогда раньше не обращал внимания на XMLWriter, все как то SimpleXML хватало. Пойду почитаю.

  • http://mefolio.ru/ Евгений

    Спасибо, странно, никогда раньше не обращал внимания на XMLWriter, все как то SimpleXML хватало. Пойду почитаю.

  • http://www.kachayev.ru/ Алексей Качаев

    Спасибо. Как раз ищу что-то подобное :)

  • http://www.kachayev.ru Алексей Качаев

    Спасибо. Как раз ищу что-то подобное :)

  • http://w3maker.name/ nck

    На мой взгляд, лучшее решение – скрипт by Keith Devens. Называется это громко – XML Library.
    Работает быстро, исходник текущей версии – всего 117 строк (с комментариями и тегами PHP). Умеет как писать, так и читать (не DOM, и не SAX).
    Использовать так:



    Смотреть по адресу http://keithdevens.com/software/phpxml

    • http://www.simplecoding.org/ Владимир

      Интересная библиотека, нужно будет попробовать.

    • http://w3maker.name/ nck

      Почему-то код в теге {code} не отобразился.
      Ещё раз:

      • http://www.simplecoding.org/ Владимир

        Ваш код:

        <?php
        include('xml.php');
        $data = XML_unserialize($xml);
        $xml = XML_serialize($data);
        ?>
        В прошлый раз был:
        <?php
        include('xml.php');
        $data = XML_unserialize($xml);
        ?>
        <?php
        include('xml.php');
        $xml = XML_serialize($data);
        ?>

      • http://www.simplecoding.org/ Владимир

        Действительно, проблема в тегах, точнее в их обработке движком WP.
        Проблема в том, что если автоматически преобразовывать угловые скобки в эскейп последовательности, то буду запрещены вообще все теги, а это меня не устраивает. Я перепробовал несколько плагинов с вроде бы подходящей функциональностью, но со всеми были проблемы. Поэтому на данный момент я просто конвертирую все теги в notepad++ :)

  • http://w3maker.name nck

    На мой взгляд, лучшее решение – скрипт by Keith Devens. Называется это громко – XML Library.
    Работает быстро, исходник текущей версии – всего 117 строк (с комментариями и тегами PHP). Умеет как писать, так и читать (не DOM, и не SAX).
    Использовать так:



    Смотреть по адресу http://keithdevens.com/software/phpxml

    • http://www.simplecoding.org/ Владимир

      Интересная библиотека, нужно будет попробовать.

    • http://w3maker.name nck

      Почему-то код в теге {code} не отобразился.
      Ещё раз:

      • http://www.simplecoding.org/ Владимир

        Ваш код:

        <?php
        include('xml.php');
        $data = XML_unserialize($xml);
        $xml = XML_serialize($data);
        ?>
        В прошлый раз был:
        <?php
        include('xml.php');
        $data = XML_unserialize($xml);
        ?>
        <?php
        include('xml.php');
        $xml = XML_serialize($data);
        ?>

      • http://www.simplecoding.org/ Владимир

        Действительно, проблема в тегах, точнее в их обработке движком WP.
        Проблема в том, что если автоматически преобразовывать угловые скобки в эскейп последовательности, то буду запрещены вообще все теги, а это меня не устраивает. Я перепробовал несколько плагинов с вроде бы подходящей функциональностью, но со всеми были проблемы. Поэтому на данный момент я просто конвертирую все теги в notepad++ :)

  • http://extrasait.ru/ hunter_89

    Большое спасибо. Давно ломал голову над этим вопросом.

  • http://extrasait.ru/ hunter_89

    Большое спасибо. Давно ломал голову над этим вопросом.

  • http://www.charnad.com/ CharnaD

    Хехе, у меня тем же занимается самописная функция. Массив берется из БД.

    public static function array2xmlstring($array) {
    if (empty($array)) {
    return false;
    }
    $xmlstring = "";
    foreach ($array as $article) {
    $xmlstring .= "";
    foreach ($article as $col => $val) {
    $xmlstring .= "".$val."";
    }
    $xmlstring .= "";
    }
    $xmlstring .= "";
    return $xmlstring;
    }

    • http://www.simplecoding.org/ Владимир

      Я так понял многомерные массивы не поддерживаются?

      • guest

        function utils_array_to_simple_xml($array, $check_plain = TRUE) {
        $xml = ";
        foreach ($array as $key => $val) {
        if ($key = str_replace(array("t", "r", "n"), ' ', trim($key))) {
        $params = array_reverse($key = explode(' ', $key));
        array_pop($params);
        $params = trim(implode(' ', $params));
        $xml .=
        ".
        (is_array($val) ? call_user_func(__FUNCTION__, $val, $check_plain) : ($check_plain ? check_plain($val) : $val)).
        ";
        }
        }
        return $xml;
        }

  • http://www.charnad.com CharnaD

    Хехе, у меня тем же занимается самописная функция. Массив берется из БД.

    public static function array2xmlstring($array) {
    if (empty($array)) {
    return false;
    }
    $xmlstring = "";
    foreach ($array as $article) {
    $xmlstring .= "";
    foreach ($article as $col => $val) {
    $xmlstring .= "".$val."";
    }
    $xmlstring .= "";
    }
    $xmlstring .= "";
    return $xmlstring;
    }

    • http://www.simplecoding.org/ Владимир

      Я так понял многомерные массивы не поддерживаются?

  • Vetroff

    Ребята! Вы – психи! Вы полные психи, черт возьми, что понимаете всю эту галиматью! Я вам искренне завидую. )

    • http://www.simplecoding.org/ Владимир

      Почему это галиматью? :)
      Все нормально работает :)

      • Дмитрий

        Владимир, да это ж спамер!

        • http://www.simplecoding.org/ Владимир

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

  • Vetroff

    Ребята! Вы – психи! Вы полные психи, черт возьми, что понимаете всю эту галиматью! Я вам искренне завидую. )

    • http://www.simplecoding.org/ Владимир

      Почему это галиматью? :)
      Все нормально работает :)

      • Дмитрий

        Владимир, да это ж спамер!

        • http://www.simplecoding.org/ Владимир

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

  • http://www.charnad.com/ CharnaD

    Владимир, у меня только 2х мерные массивы, т.к. мне надо таблицу из БД пересылать.

    Vetroff, это наша работа) Врачи вон по латыни пишут, тоже фиг кто поймет. Каждому свое)

    • http://www.simplecoding.org/ Владимир

      Тогда все ясно. Действительно, использовать какие-то дополнительные библиотеки в такой ситуации просто нет смысла.

  • http://www.charnad.com CharnaD

    Владимир, у меня только 2х мерные массивы, т.к. мне надо таблицу из БД пересылать.

    Vetroff, это наша работа) Врачи вон по латыни пишут, тоже фиг кто поймет. Каждому свое)

    • http://www.simplecoding.org/ Владимир

      Тогда все ясно. Действительно, использовать какие-то дополнительные библиотеки в такой ситуации просто нет смысла.

  • http://all-ebooks.com/ test

    не лучшая идея фантастика
    . Потом разбирать это довольно гемморойно.
    А вот так на много практичнее фантастика
    .
    Но все равно спасибо автору (правда код я таки немного модифицировал)
    PS: убейте предыдущий коммент

  • http://all-ebooks.com/ test

    мда.. а тег Code у тебя не работает

    • http://www.simplecoding.org/ Владимир

      Почему не работает? У меня в стилях указано, что текст внутри <code> должен быть зеленым ;)

  • http://all-ebooks.com test

    не лучшая идея фантастика
    . Потом разбирать это довольно гемморойно.
    А вот так на много практичнее фантастика
    .
    Но все равно спасибо автору (правда код я таки немного модифицировал)
    PS: убейте предыдущий коммент

  • http://all-ebooks.com test

    мда.. а тег Code у тебя не работает

    • http://www.simplecoding.org/ Владимир

      Почему не работает? У меня в стилях указано, что текст внутри <code> должен быть зеленым ;)

  • http://zimniesalaty.ru/ Elena

    Он должен быть красным потому что ссылается на другой протокол.

    • http://www.simplecoding.org/ Владимир

      О каком протоколе речь?

  • http://zimniesalaty.ru/ Elena

    Он должен быть красным потому что ссылается на другой протокол.

    • http://www.simplecoding.org/ Владимир

      О каком протоколе речь?

  • Shurik

    Ребята, помогите мне, точнее поставьте на правильный путь! Хочу сделать карту сайта (sitemap.xml) Но черт возьми не могу работать с xml вообще. С чего мне лучше всего начать?

    • http://www.simplecoding.org/ Владимир

      Есть разные варианты:

      1) использовать готовое решение, например, вроде плагина к WP Google XML Sitemaps

      2) есть online сервис

      3) разобраться с какой-нибудь библиотекой для работы с XML и заодно с форматом карты сайта :)

  • Shurik

    Ребята, помогите мне, точнее поставьте на правильный путь! Хочу сделать карту сайта (sitemap.xml) Но черт возьми не могу работать с xml вообще. С чего мне лучше всего начать?

    • http://www.simplecoding.org/ Владимир

      Есть разные варианты:

      1) использовать готовое решение, например, вроде плагина к WP Google XML Sitemaps

      2) есть online сервис

      3) разобраться с какой-нибудь библиотекой для работы с XML и заодно с форматом карты сайта :)

  • KP-0B0-C0C

    Очень полезная и написанная максимально доступным языком статья! Мне помогла! Большое спасибо! =)

  • singer

    Не самый удачный вариант, имхо – использование array_key_exists() в цилке + не поддерживается с 2005 года. На мой взгялд пример в этой статье – лучше.

  • http://semasping.info Semasping

    Я вот заметил странную особенность XmlWriter.
    если ему во writeAttribute("ЗависимОтРегистра", "Тут значение");
    то получим

    как от этого можно избавится… ???

    • http://semasping.info Semasping

      прошу прощения. Это меня Google chrome ввел в заблуждения. В итоговом файле все нормально регистром атрибутов.
      А при просмотре структуры через Chrome все были приведены к lowercase

  • http://twitter.com/olgatcpip Ольга Владимировка

    Спасибо :)

  • Zadvinski

    Скрипт конечно замечательный, потому что простой и функциональный.

    Есть маленький момент с кодировкой – если кому-то позарез нужно windows-1251 вместо UTF-8, то скорее всего будет ругаться ошибкой. 
    Но есть выход – поменять в классе одну единственную 16-ю строчку и написать:
    $this->writer->startDocument($this->version.'" encoding="'.$this->encoding);

    То есть не устанавливаем кодировку, а в строке версии пишем и версию и кодировку..  вроде как пашетИдея почерпнута отсюда - http://www.php.net/manual/en/function.xmlwriter-start-document.php#89957

    • tnt

      сработало! спасибо за это важное уточнение, я то я тут как раз над этим голову ломал –  с какого фига он на русский ругался при 1251

  • Гость

    Вот ещё один врайтер…
    http://istem.ru/open/xmlgen.php

]]>
Tweet