'', '#value' => '', '#attrs' => array(), '#type' => ''); /** * Массив данных экземпляра шаблона * @var array */ private $_data = array(); /** * * @var XmlGenerator */ private $_XmlGenerator; /** * * @param string $rootName имя корневого элемента */ public function __construct($rootName = false) { $this->_XmlGenerator = new XmlGenerator($rootName); } /** * Создаем переменную для последующей записи в XML структуру * @param string $name Имя переменной (если не передан второй параметр, то первый должен быть массивом с типом 'raw') * @param mixed $value Строка или массив значений * @example (пример переменной $value) * array( * array('tone_check2' => 0), * array('filling' => ''), * array(array * ( * '#name' => 'photo', * '#attrs' => array * ( * 'id' => 1512,'src' => '','w' => '','h' => '','type' => 1 * ), * '#value' => array * ( * array('url' => 'no_url'), * array(array( * '#name' => 'big', * '#attrs' => array('src' => 1512,'format' => 1,) * //'#value' - пустое * )), * array(array * ( * '#name' => 'author', * '#attrs' => array('id' => 3,), * '#value' => 'alp' * )), * ) * )), * 'date_end' => false, * ) * @example raw-массив * ('', array('#type' => 'raw', '#value' => 'value')) */ public function assign($name, $value) { if (self::_isValidTagname($name)) { $this->_data = array_merge_recursive($this->_data, self::_convertArray(array($name =>$value))); } } /** * Конвертирует входящий массив исходя из его типа * в массив вида @link self::$_defTagArray * @param array $array входящий массив * @param int $arrayNumInSet[OPTIONAL] порядковый номер массива * (если передаётся несколько массивов тегов на одном уровне) * @return array массив, содержащий в качестве значения массив вида @link self::$_defTagArray * (array($arrayNumInSet => self::$_defTagArray)) */ private static function _convertArray($array, $arrayNumInSet = 0) { //если просто значение - возвращаем его if (!is_array($array)) return $array; //заполняем массив значениями по умолчанию $tagArray = self::$_defTagArray; $arrayType = self::_getArrayType($array); switch ($arrayType) { case 'simple': $tagArray['#name'] = self::_getSimpleTagName($array); $tagArray['#value'] = self::_getSimpleTagValue($array); break; case 'complex': $tagArray['#name'] = self::_getComplexTagName($array); $tagArray['#type'] = self::_getComplexTagType($array); $tagArray['#attrs'] = self::_getComplexTagAttrs($array); $tagArray['#value'] = self::_getComplexTagValue($array); break; } return array($arrayNumInSet => $tagArray); } /** * Возвращает тип переданного массива (тега). * Мы можем задать массив одного из трёх типов: простой тег, сложный тег, массив тегов * @param array $array тег * return string|bool ('numeric', 'simple', 'complex')|false если не массив */ private static function _getArrayType($array) { if (!is_array($array) || empty ($array)) return false; $firstKey = array_keys($array); $firstKey = $firstKey[0]; if (is_int($firstKey)) return 'numeric'; if (array_key_exists($firstKey, self::$_defTagArray)) return 'complex'; return 'simple'; } /** * Возвращает значение тега (в виде массива) для простого тега * @uses self::_convertArray() для формирования значения * @uses self::_processNumericArray() если передан массив тегов * @param array $array тег * @return array */ private static function _getSimpleTagValue($array) { $value = array_values($array); $value = $value[0]; if (self::_getArrayType($value) == 'numeric') return self::_processNumericArray($value); return self::_convertArray($value); } /** * Возвращает имя тега для простого тега * @param array $array тег * @return string */ private static function _getSimpleTagName($array) { $keys = array_keys($array); $key = $keys[0]; if (self::_isValidTagname($key)) return $key; return ''; } /** * Возвращает имя сложного тега * @param array $array тег * @return string */ private static function _getComplexTagName($array) { return (isset ($array['#name'])) ? $array['#name'] : ''; } /** * Возвращает тип сложного тега (подразумевается либо пустой, либо 'raw') * @param array $array тег * @return string */ private static function _getComplexTagType($array) { return (isset ($array['#type'])) ? $array['#type'] : ''; } /** * Возвращает атрибуты сложного тега * @param array $array тег * @return array */ private static function _getComplexTagAttrs($array) { return (isset ($array['#attrs'])) ? $array['#attrs'] : array(); } /** * Возвращает значение сложного тега (в виде массива) * @uses self::_convertArray() для формирования значения * @uses self::_processNumericArray() если передан массив тегов * @param array $array тег * @return array */ private static function _getComplexTagValue($array) { if (!isset ($array['#value'])) return ''; $value = $array['#value']; if (self::_getArrayType($value) == 'numeric') return self::_processNumericArray($value); return self::_convertArray($value); } /** * Обрабатывает массив массивов тегов * @param array $arrays * @return array обработанный массив массивов тегов */ private static function _processNumericArray($arrays) { $keys = array_keys($arrays); $numKeys = array_filter($keys, 'is_int'); $convertedArrays = array(); foreach ($numKeys as $numKey) { $convertedArrays = array_merge_recursive($convertedArrays, self::_convertArray($arrays[$numKey], $numKey)); } return $convertedArrays; } /** * Проверяет, может ли быть переданное значение быть именем тега * @param string $tagName * @return bool */ private static function _isValidTagname($tagName) { if (/*!empty ($tagName) && */!is_int($tagName)) return true; return false; } /** * Генерация XML структуры. */ private function _generateXml() { $data = $this->_data; foreach ($data as $key => $tagData) { if ($tagData['#type'] == 'raw') $this->_XmlGenerator->writeRaw($tagData['#value']); else if (!empty($tagData['#name'])) { $this->_XmlGenerator->startElement($tagData['#name']); $this->_setCurrentTagAttributes($tagData['#attrs']); $this->_setCurrentTagValue($tagData['#value']); $this->_XmlGenerator->endElement(); } } } /** * Заполняем значение текущего тега * (может вызывать @link $this->getXML(), если передан массив) * @param mixed $tagValue значение тега (массив/строка) */ protected function _setCurrentTagValue($tagValue) { if (is_array($tagValue)) $this->_generateXml($tagValue); else $this->_XmlGenerator->setValue($tagValue); } /** * Заполняем атрибуты текущего тега * @param array $tagAttributes массив атрибутов */ protected function _setCurrentTagAttributes($tagAttributes) { foreach ($tagAttributes as $key => $value) { $this->_XmlGenerator->writeAttribute($key, $value); } } /** * Генерирует и возвращает XML * @return string */ public function getXml() { $this->_XmlGenerator->preGenerate(); $this->_generateXml(); return $this->_XmlGenerator->postGenerate(); } public function getData() { return $this->_data; } } /** * Класс генерации XML данных */ class XmlGenerator { /** * Объект * @var XMLWriter */ protected $writer; /** * Имя корневого элемента * @var string */ protected $rootName = 'root'; /** * Номер версии XML * @var float */ protected $version = '1.0'; /** * Название кодировки * @var string */ protected $encoding = 'UTF-8'; /** * Конструктор */ function __construct($rootName = false) { if ($rootName) $this->rootName = $rootName; $this->writer = new XMLWriter(); } /** * перед генерацией XML документа */ public function preGenerate($write_headers = true) { $this->writer->openMemory(); if( $write_headers ) $this->header(); } /** * после генерации XML документа * @return string */ public function postGenerate($write_headers = true) { if( $write_headers ) $this->footer(); return $this->writer->outputMemory(); } /** * Устанавливает версию и кодировку документа, а также корневой элемент */ protected function header() { $this->writer->startDocument($this->version, $this->encoding); $this->writer->startElement($this->rootName); } /** * Закрываем корневой элемент */ protected function footer() { $this->writer->endElement(); } /** * Пишем сырые XML-данные в структуру * @param string $rawXml */ public function writeRaw($rawXml) { $this->writer->writeRaw($rawXml); } public function startElement($tagName) { $this->writer->startElement($tagName); } public function endElement() { $this->writer->endElement(); } public function writeAttribute($key, $value) { $this->writer->writeAttribute($key, $value); } public function setValue($tagValue) { if (is_numeric($tagValue) || is_bool($tagValue)) $this->writer->text((float) $tagValue); /** * Дальше всё считаем строками. */ else if (!empty ($tagValue)) $this->writer->writeCData($tagValue); } } //использование $tpl = new XmlTpl(); $tpl->assign('', array('#type' => 'raw', '#value' => 'value')); $jscripts = array ( array('#name' => 'script', '#value' => '/js/script.js'), array('#name' => 'script', '#value' => '/js/tooltip.js'), array('#name' => 'script', '#value' => '/js/slib.js'), ); $tpl->assign('ExtraHead', $jscripts); $tpl->assign('MainMenu', ''); $tpl->assign('Footer', ''); echo $tpl->getXml();