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

Владимир | | PHP, Web разработка.

Сегодня речь пойдет о работе с 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». Лучше, конечно, задавать ключи для всех элементов массива явно.

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

class Array2XML {
	
	private $writer;
	private $version = '1.0';
	private $encoding = 'UTF-8';
	private $rootName = 'root';
	

	function __construct() {
		$this->writer = new XMLWriter();
	}
	
	public function convert($data) {
		$this->writer->openMemory();
		$this->writer->startDocument($this->version, $this->encoding);
		$this->writer->startElement($this->rootName);
		if (is_array($data)) {
			$this->getXML($data);
		}
		$this->writer->endElement();
		return $this->writer->outputMemory();
	}
	public function setVersion($version) {
		$this->version = $version;
	}
	public function setEncoding($encoding) {
		$this->encoding = $encoding;
	}
	public function setRootName($rootName) {
		$this->rootName = $rootName;
	}
	private function getXML($data) {
		foreach ($data as $key => $val) {
			if (is_numeric($key)) {
				$key = 'key'.$key;
			}
			if (is_array($val)) {
				$this->writer->startElement($key);
				$this->getXML($val);
				$this->writer->endElement();
			}
			else {
				$this->writer->writeElement($key, $val);
			}
		}
	}
}
//end of Array2XML.php

Прежде всего, в конструкторе мы создаем объект типа 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 купить киев