Source for file Serializer.php
Documentation is available at Serializer.php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Stephan Schmidt <schst@php-tools.net> |
// +----------------------------------------------------------------------+
// $Id: Serializer.php,v 1.26 2004/11/06 15:49:52 schst Exp $
* uses PEAR error management
* uses XML_Util to create XML tags
require_once 'XML/Util.php';
* error code for no serialization done
define('XML_SERIALIZER_ERROR_NO_SERIALIZATION', 51 );
* class that serializes various structures into an XML document
* this class can be used in two modes:
* 1. create an XML document from an array or object that is processed by other
* applications. That means, you can create a RDF document from an array in the
* 'title' => 'Example RDF channel',
* 'link' => 'http://www.php-tools.de',
* 'title' => 'Example image',
* 'url' => 'http://www.php-tools.de/image.gif',
* 'link' => 'http://www.php-tools.de'
* 'title' => 'Example item',
* 'link' => 'http://example.com'
* 'title' => 'Another Example item',
* 'link' => 'http://example.org'
* to create a RDF document from this array do the following:
* require_once 'XML/Serializer.php';
* 'indent' => "\t", // indent with tabs
* 'linebreak' => "\n", // use UNIX line breaks
* 'rootName' => 'rdf:RDF', // root tag
* 'defaultTagName' => 'item' // tag for values with numeric keys
* $serializer = new XML_Serializer($options);
* $rdf = $serializer->serialize($data);
* You will get a complete XML document that can be processed like any RDF document.
* 2. this classes can be used to serialize any data structure in a way that it can
* later be unserialized again.
* XML_Serializer will store the type of the value and additional meta information
* in attributes of the surrounding tag. This meat information can later be used
* to restore the original data structure in PHP. If you want XML_Serializer
* to add meta information to the tags, add
* to the options array in the constructor.
* Future versions of this package will include an XML_Unserializer, that does
* the unserialization automatically for you.
* @package XML_Serializer
* @author Stephan Schmidt <schst@php.net>
* default options for the serialization
* @var array $_defaultOptions
var $_defaultOptions = array (
'indent' => '', // string used for indentation
'linebreak' => "\n", // string used for newlines
'typeHints' => false , // automatically add type hin attributes
'addDecl' => false , // add an XML declaration
'defaultTagName' => 'XML_Serializer_Tag', // tag used for indexed arrays or invalid names
'classAsTagName' => false , // use classname for objects in indexed arrays
'keyAttribute' => '_originalKey', // attribute where original key is stored
'typeAttribute' => '_type', // attribute for type (only if typeHints => true)
'classAttribute' => '_class', // attribute for class of objects (only if typeHints => true)
'scalarAsAttributes' => false , // scalar values (strings, ints,..) will be serialized as attribute
'prependAttributes' => '', // prepend string for attributes
'indentAttributes' => false , // indent the attributes, if set to '_auto', it will indent attributes so they all start at the same column
'mode' => 'default', // use 'simplexml' to use parent name as tagname if transforming an indexed array
'addDoctype' => false , // add a doctype declaration
'doctype' => null , // supply a string or an array with id and uri ({@see XML_Util::getDoctypeDeclaration()}
'rootName' => null , // name of the root tag
'rootAttributes' => array (), // attributes of the root tag
'attributesArray' => null , // all values in this key will be treated as attributes
'contentName' => null , // this value will be used directly as content, instead of creating a new tag, may only be used in conjuction with attributesArray
* options for the serialization
* @var integer $_tagDepth
* serilialized representation of the data
* @var string $_serializedData
var $_serializedData = null;
* @param mixed $options array containing options for the serialization
$this->options = array_merge($this->_defaultOptions, $options);
$this->options = $this->_defaultOptions;
* @return string $version API version
* reset all options to default options
* @see setOption(), XML_Unserializer()
$this->options = $this->_defaultOptions;
* You can use this method if you do not want to set all options in the constructor
* @see resetOption(), XML_Serializer()
$this->options[$name] = $value;
* sets several options at once
* You can use this method if you do not want to set all options in the constructor
* @see resetOption(), XML_Unserializer(), setOption()
$this->options = array_merge($this->options, $options);
* @param mixed $data data to serialize
* @return boolean true on success, pear error on failure
// if options have been specified, use them instead
// of the previously defined ones
$optionsBak = $this->options;
if (isset ($options['overrideOptions']) && $options['overrideOptions'] == true ) {
$this->options = array_merge($this->_defaultOptions, $options);
$this->options = array_merge($this->options, $options);
if (isset ($this->options['tagName'])) {
$this->options['rootName'] = $this->options['tagName'];
$this->_serializedData = '';
if (isset ($this->options['rootName'])) {
$tagName = $this->options['rootName'];
$this->_serializedData .= $this->_serializeArray ($data, $tagName, $this->options['rootAttributes']);
if (isset ($this->options['rootName'])) {
$tagName = $this->options['rootName'];
$this->_serializedData .= $this->_serializeObject ($data, $tagName, $this->options['rootAttributes']);
// add doctype declaration
if ($this->options['addDoctype'] === true ) {
$this->_serializedData = XML_Util ::getDoctypeDeclaration ($tagName, $this->options['doctype'])
. $this->options['linebreak']
. $this->_serializedData;
if ($this->options['addDecl']) {
if (isset ($this->options['encoding']) ) {
$encoding = $this->options['encoding'];
$this->_serializedData = XML_Util ::getXMLDeclaration ('1.0', $encoding)
. $this->options['linebreak']
. $this->_serializedData;
if ($optionsBak !== null ) {
$this->options = $optionsBak;
* get the result of the serialization
* @return string serialized XML
if ($this->_serializedData == null ) {
return $this->_serializedData;
* This method checks for the type of the value and calls the appropriate method
* @param array $attributes
function _serializeValue ($value, $tagName = null , $attributes = array ())
$xml = $this->_serializeArray ($value, $tagName, $attributes);
$xml = $this->_serializeObject ($value, $tagName);
'attributes' => $attributes,
$xml = $this->_createXMLTag ($tag);
* @param array $array array to serialize
* @param string $tagName name of the root tag
* @param array $attributes attributes for the root tag
* @return string $string serialized data
* @uses XML_Util::isValidName() to check, whether key has to be substituted
function _serializeArray (&$array, $tagName = null , $attributes = array ())
* check for special attributes
if ($this->options['attributesArray'] !== null ) {
if (isset ($array[$this->options['attributesArray']])) {
$attributes = $array[$this->options['attributesArray']];
unset ($array[$this->options['attributesArray']]);
* check for special content
if ($this->options['contentName'] !== null ) {
if (isset ($array[$this->options['contentName']])) {
$_content = $array[$this->options['contentName']];
unset ($array[$this->options['contentName']]);
* if mode is set to simpleXML, check whether
* the array is associative or indexed
if (is_array($array) && !empty ($array) && $this->options['mode'] == 'simplexml') {
foreach ($array as $key => $val) {
if ($indexed && $this->options['mode'] == 'simplexml') {
foreach ($array as $key => $val) {
$string .= $this->_serializeValue ( $val, $tagName, $attributes);
$string .= $this->options['linebreak'];
if ($this->options['indent']!==null && $this->_tagDepth>0 ) {
$string .= str_repeat($this->options['indent'], $this->_tagDepth);
if ($this->options['scalarAsAttributes'] === true ) {
foreach ($array as $key => $value) {
if (is_scalar($value) && (XML_Util ::isValidName ($key) === true )) {
$attributes[$this->options['prependAttributes']. $key] = $value;
// check for empty array => create empty tag
'attributes' => $attributes
$tmp = $this->options['linebreak'];
foreach ($array as $key => $value) {
if ($this->options['indent']!==null && $this->_tagDepth>0 ) {
$tmp .= str_repeat($this->options['indent'], $this->_tagDepth);
if (isset ($this->options['tagMap'][$key])) {
$key = $this->options['tagMap'][$key];
// key cannot be used as tagname => use default tag
$valid = XML_Util ::isValidName ($key);
if (PEAR ::isError ($valid)) {
if ($this->options['classAsTagName'] && is_object($value)) {
$key = $this->options['defaultTagName'];
if ($this->options['typeHints'] === true ) {
$atts[$this->options['typeAttribute']] = gettype($value);
$atts[$this->options['keyAttribute']] = (string) $origKey;
$tmp .= $this->_createXMLTag (array (
$tmp .= $this->options['linebreak'];
if ($this->options['indent']!==null && $this->_tagDepth>0 ) {
$tmp .= str_repeat($this->options['indent'], $this->_tagDepth);
'attributes' => $attributes
if ($this->options['typeHints'] === true ) {
if (!isset ($tag['attributes'][$this->options['typeAttribute']])) {
$tag['attributes'][$this->options['typeAttribute']] = 'array';
$string = $this->_createXMLTag ($tag, false );
* @param object $object object to serialize
* @return string $string serialized data
function _serializeObject (&$object, $tagName = null , $attributes = array ())
// check for magic function
$tmp = $this->options['linebreak'];
if ($this->options['typeHints'] === true ) {
$attributes[$this->options['typeAttribute']] = 'object';
$attributes[$this->options['classAttribute']] = get_class($object);
$string = $this->_serializeArray ($properties, $tagName, $attributes);
* create a tag from an array
* this method awaits an array in the following format
* 'attributes' => array(),
* 'content' => $content, // optional
* 'namespace' => $namespace // optional
* 'namespaceUri' => $namespaceUri // optional
* @param array $tag tag definition
* @param boolean $replaceEntities whether to replace XML entities in content or not
* @return string $string XML tag
function _createXMLTag ( $tag, $replaceEntities = true )
if ($this->options['indentAttributes'] !== false ) {
$indent = str_repeat($this->options['indent'], $this->_tagDepth);
if ($this->options['indentAttributes'] == '_auto') {
$indent .= $this->options['indentAttributes'];
if (empty ($tag['content'])) {
} elseif (is_scalar($tag['content']) && (string) $tag['content'] == '') {
$tag = XML_Util ::createTagFromArray ($tag, $replaceEntities, $multiline, $indent, $this->options['linebreak']);
$tag = $this->_serializeArray ($tag['content'], $tag['qname'], $tag['attributes']);
$tag = $this->_serializeObject ($tag['content'], $tag['qname'], $tag['attributes']);
settype($tag['content'], 'string');
$tag = XML_Util ::createTagFromArray ($tag, $replaceEntities);
Documentation generated on Mon, 11 Mar 2019 13:58:25 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.
|