Blame | Letzte Änderung | Log anzeigen | RSS feed
<?PHP/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: *//*** XML_Serializer** Creates XML documents from PHP data structures like arrays, objects or scalars.** PHP versions 4 and 5** LICENSE:** Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>* All rights reserved.** Redistribution and use in source and binary forms, with or without* modification, are permitted provided that the following conditions* are met:** * Redistributions of source code must retain the above copyright* notice, this list of conditions and the following disclaimer.* * Redistributions in binary form must reproduce the above copyright* notice, this list of conditions and the following disclaimer in the* documentation and/or other materials provided with the distribution.* * The name of the author may not be used to endorse or promote products* derived from this software without specific prior written permission.** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.** @category XML* @package XML_Serializer* @author Stephan Schmidt <schst@php.net>* @copyright 2003-2008 Stephan Schmidt <schst@php.net>* @license http://opensource.org/licenses/bsd-license New BSD License* @version CVS: $Id: Serializer.php 294967 2010-02-12 03:10:19Z clockwerx $* @link http://pear.php.net/package/XML_Serializer* @see XML_Unserializer*//*** uses PEAR error management*/require_once 'PEAR.php';/*** uses XML_Util to create XML tags*/require_once 'XML/Util.php';/*** option: string used for indentation** Possible values:* - any string (default is any string)*/define('XML_SERIALIZER_OPTION_INDENT', 'indent');/*** option: string used for linebreaks** Possible values:* - any string (default is \n)*/define('XML_SERIALIZER_OPTION_LINEBREAKS', 'linebreak');/*** option: enable type hints** Possible values:* - true* - false*/define('XML_SERIALIZER_OPTION_TYPEHINTS', 'typeHints');/*** option: add an XML declaration** Possible values:* - true* - false*/define('XML_SERIALIZER_OPTION_XML_DECL_ENABLED', 'addDecl');/*** option: encoding of the document** Possible values:* - any valid encoding* - null (default)*/define('XML_SERIALIZER_OPTION_XML_ENCODING', 'encoding');/*** option: default name for tags** Possible values:* - any string (XML_Serializer_Tag is default)*/define('XML_SERIALIZER_OPTION_DEFAULT_TAG', 'defaultTagName');/*** option: use classname for objects in indexed arrays** Possible values:* - true* - false (default)*/define('XML_SERIALIZER_OPTION_CLASSNAME_AS_TAGNAME', 'classAsTagName');/*** option: attribute where original key is stored** Possible values:* - any string (default is _originalKey)*/define('XML_SERIALIZER_OPTION_ATTRIBUTE_KEY', 'keyAttribute');/*** option: attribute for type (only if typeHints => true)** Possible values:* - any string (default is _type)*/define('XML_SERIALIZER_OPTION_ATTRIBUTE_TYPE', 'typeAttribute');/*** option: attribute for class (only if typeHints => true)** Possible values:* - any string (default is _class)*/define('XML_SERIALIZER_OPTION_ATTRIBUTE_CLASS', 'classAttribute');/*** option: scalar values (strings, ints,..) will be serialized as attribute** Possible values:* - true* - false (default)* - array which sets this option on a per-tag basis*/define('XML_SERIALIZER_OPTION_SCALAR_AS_ATTRIBUTES', 'scalarAsAttributes');/*** option: prepend string for attributes** Possible values:* - any string (default is any string)*/define('XML_SERIALIZER_OPTION_PREPEND_ATTRIBUTES', 'prependAttributes');/*** option: indent the attributes, if set to '_auto',* it will indent attributes so they all start at the same column** Possible values:* - true* - false (default)* - '_auto'*/define('XML_SERIALIZER_OPTION_INDENT_ATTRIBUTES', 'indentAttributes');/*** option: use 'simplexml' to use parent name as tagname* if transforming an indexed array** Possible values:* - XML_SERIALIZER_MODE_DEFAULT (default)* - XML_SERIALIZER_MODE_SIMPLEXML*/define('XML_SERIALIZER_OPTION_MODE', 'mode');/*** option: add a doctype declaration** Possible values:* - true* - false (default)*/define('XML_SERIALIZER_OPTION_DOCTYPE_ENABLED', 'addDoctype');/*** option: supply a string or an array with id and uri* ({@see XML_Util::getDoctypeDeclaration()}** Possible values:* - string* - array*/define('XML_SERIALIZER_OPTION_DOCTYPE', 'doctype');/*** option: name of the root tag** Possible values:* - string* - null (default)*/define('XML_SERIALIZER_OPTION_ROOT_NAME', 'rootName');/*** option: attributes of the root tag** Possible values:* - array*/define('XML_SERIALIZER_OPTION_ROOT_ATTRIBS', 'rootAttributes');/*** option: all values in this key will be treated as attributes** Possible values:* - string*/define('XML_SERIALIZER_OPTION_ATTRIBUTES_KEY', 'attributesArray');/*** option: this value will be used directly as content,* instead of creating a new tag, may only be used* in conjuction with attributesArray** Possible values:* - string* - null (default)*/define('XML_SERIALIZER_OPTION_CONTENT_KEY', 'contentName');/*** option: this value will be used in a comment, instead of creating a new tag** Possible values:* - string* - null (default)*/define('XML_SERIALIZER_OPTION_COMMENT_KEY', 'commentName');/*** option: tag names that will be changed** Possible values:* - array*/define('XML_SERIALIZER_OPTION_TAGMAP', 'tagMap');/*** option: function that will be applied before serializing** Possible values:* - any valid PHP callback*/define('XML_SERIALIZER_OPTION_ENCODE_FUNC', 'encodeFunction');/*** option: namespace to use for the document** Possible values:* - string* - null (default)*/define('XML_SERIALIZER_OPTION_NAMESPACE', 'namespace');/*** option: type of entities to replace** Possible values:* - XML_SERIALIZER_ENTITIES_NONE* - XML_SERIALIZER_ENTITIES_XML (default)* - XML_SERIALIZER_ENTITIES_XML_REQUIRED* - XML_SERIALIZER_ENTITIES_HTML*/define('XML_SERIALIZER_OPTION_ENTITIES', 'replaceEntities');/*** option: whether to return the result of the serialization from serialize()** Possible values:* - true* - false (default)*/define('XML_SERIALIZER_OPTION_RETURN_RESULT', 'returnResult');/*** option: whether to ignore properties that are set to null** Possible values:* - true* - false (default)*/define('XML_SERIALIZER_OPTION_IGNORE_NULL', 'ignoreNull');/*** option: whether to use cdata sections for character data** Possible values:* - true* - false (default)*/define('XML_SERIALIZER_OPTION_CDATA_SECTIONS', 'cdata');/*** option: whether a boolean FALSE value should become a string** Possible values:* - true* - false (default)** @since 0.20.0*/define('XML_SERIALIZER_OPTION_FALSE_AS_STRING', 'falseAsString');/*** default mode*/define('XML_SERIALIZER_MODE_DEFAULT', 'default');/*** SimpleXML mode** When serializing indexed arrays, the key of the parent value is used as a tagname.*/define('XML_SERIALIZER_MODE_SIMPLEXML', 'simplexml');/*** error code for no serialization done*/define('XML_SERIALIZER_ERROR_NO_SERIALIZATION', 51);/*** do not replace entitites*/define('XML_SERIALIZER_ENTITIES_NONE', XML_UTIL_ENTITIES_NONE);/*** replace all XML entitites* This setting will replace <, >, ", ' and &*/define('XML_SERIALIZER_ENTITIES_XML', XML_UTIL_ENTITIES_XML);/*** replace only required XML entitites* This setting will replace <, " and &*/define('XML_SERIALIZER_ENTITIES_XML_REQUIRED', XML_UTIL_ENTITIES_XML_REQUIRED);/*** replace HTML entitites* @link http://www.php.net/htmlentities*/define('XML_SERIALIZER_ENTITIES_HTML', XML_UTIL_ENTITIES_HTML);/*** Creates XML documents from PHP data structures like arrays, objects or scalars.** 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 an RDF document from an array in the* following format:* <code>* $data = array(* 'channel' => array(* 'title' => 'Example RDF channel',* 'link' => 'http://www.php-tools.de',* 'image' => array(* 'title' => 'Example image',* 'url' => 'http://www.php-tools.de/image.gif',* 'link' => 'http://www.php-tools.de'* ),* array(* 'title' => 'Example item',* 'link' => 'http://example.com'* ),* array(* 'title' => 'Another Example item',* 'link' => 'http://example.org'* )* )* );* </code>** To create an RDF document from this array, do the following:** <code>* require_once 'XML/Serializer.php';* $options = array(* XML_SERIALIZER_OPTION_INDENT => "\t", // indent with tabs* XML_SERIALIZER_OPTION_LINEBREAKS => "\n", // use UNIX line breaks* XML_SERIALIZER_OPTION_ROOT_NAME => 'rdf:RDF',// root tag* XML_SERIALIZER_OPTION_DEFAULT_TAG => 'item' // tag for values* // with numeric keys* );* $serializer = new XML_Serializer($options);* $rdf = $serializer->serialize($data);* </code>** You will get a complete XML document that can be processed like any RDF document.** 2. This class 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* meta 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* <code>* XML_SERIALIZER_OPTION_TYPEHINTS => true* </code>* to the options array in the constructor.** @category XML* @package XML_Serializer* @author Stephan Schmidt <schst@php.net>* @copyright 2003-2008 Stephan Schmidt <schst@php.net>* @license http://opensource.org/licenses/bsd-license New BSD License* @version Release: @package_version@* @link http://pear.php.net/package/XML_Serializer* @see XML_Unserializer* @todo replace extending PEAR class with instead using a PEAR_Error object*/class XML_Serializer extends PEAR{/*** List of all available options** @access private* @var array*/var $_knownOptions = array(XML_SERIALIZER_OPTION_INDENT,XML_SERIALIZER_OPTION_LINEBREAKS,XML_SERIALIZER_OPTION_TYPEHINTS,XML_SERIALIZER_OPTION_XML_DECL_ENABLED,XML_SERIALIZER_OPTION_XML_ENCODING,XML_SERIALIZER_OPTION_DEFAULT_TAG,XML_SERIALIZER_OPTION_CLASSNAME_AS_TAGNAME,XML_SERIALIZER_OPTION_ATTRIBUTE_KEY,XML_SERIALIZER_OPTION_ATTRIBUTE_TYPE,XML_SERIALIZER_OPTION_ATTRIBUTE_CLASS,XML_SERIALIZER_OPTION_SCALAR_AS_ATTRIBUTES,XML_SERIALIZER_OPTION_PREPEND_ATTRIBUTES,XML_SERIALIZER_OPTION_INDENT_ATTRIBUTES,XML_SERIALIZER_OPTION_MODE,XML_SERIALIZER_OPTION_DOCTYPE_ENABLED,XML_SERIALIZER_OPTION_DOCTYPE,XML_SERIALIZER_OPTION_ROOT_NAME,XML_SERIALIZER_OPTION_ROOT_ATTRIBS,XML_SERIALIZER_OPTION_ATTRIBUTES_KEY,XML_SERIALIZER_OPTION_CONTENT_KEY,XML_SERIALIZER_OPTION_COMMENT_KEY,XML_SERIALIZER_OPTION_TAGMAP,XML_SERIALIZER_OPTION_ENCODE_FUNC,XML_SERIALIZER_OPTION_NAMESPACE,XML_SERIALIZER_OPTION_ENTITIES,XML_SERIALIZER_OPTION_RETURN_RESULT,XML_SERIALIZER_OPTION_IGNORE_NULL,XML_SERIALIZER_OPTION_CDATA_SECTIONS,);/*** Default options for the serialization** @access private* @var array*/var $_defaultOptions = array(// string used for indentationXML_SERIALIZER_OPTION_INDENT => '',// string used for newlinesXML_SERIALIZER_OPTION_LINEBREAKS => "\n",// automatically add type hin attributesXML_SERIALIZER_OPTION_TYPEHINTS => false,// add an XML declarationXML_SERIALIZER_OPTION_XML_DECL_ENABLED => false,// encoding specified in the XML declarationXML_SERIALIZER_OPTION_XML_ENCODING => null,// tag used for indexed arrays or invalid namesXML_SERIALIZER_OPTION_DEFAULT_TAG => 'XML_Serializer_Tag',// use classname for objects in indexed arraysXML_SERIALIZER_OPTION_CLASSNAME_AS_TAGNAME => false,// attribute where original key is storedXML_SERIALIZER_OPTION_ATTRIBUTE_KEY => '_originalKey',// attribute for type (only if typeHints => true)XML_SERIALIZER_OPTION_ATTRIBUTE_TYPE => '_type',// attribute for class of objects (only if typeHints => true)XML_SERIALIZER_OPTION_ATTRIBUTE_CLASS => '_class',// scalar values (strings, ints,..) will be serialized as attributeXML_SERIALIZER_OPTION_SCALAR_AS_ATTRIBUTES => false,// prepend string for attributesXML_SERIALIZER_OPTION_PREPEND_ATTRIBUTES => '',// indent the attributes, if set to '_auto',// it will indent attributes so they all start at the same columnXML_SERIALIZER_OPTION_INDENT_ATTRIBUTES => false,// use XML_SERIALIZER_MODE_SIMPLEXML to use parent name as tagname// if transforming an indexed arrayXML_SERIALIZER_OPTION_MODE => XML_SERIALIZER_MODE_DEFAULT,// add a doctype declarationXML_SERIALIZER_OPTION_DOCTYPE_ENABLED => false,// supply a string or an array with id and uri// ({@see XML_Util::getDoctypeDeclaration()}XML_SERIALIZER_OPTION_DOCTYPE => null,// name of the root tagXML_SERIALIZER_OPTION_ROOT_NAME => null,// attributes of the root tagXML_SERIALIZER_OPTION_ROOT_ATTRIBS => array(),// all values in this key will be treated as attributesXML_SERIALIZER_OPTION_ATTRIBUTES_KEY => null,// this value will be used directly as content,// instead of creating a new tag, may only be used// in conjuction with attributesArrayXML_SERIALIZER_OPTION_CONTENT_KEY => null,// this value will be used directly as comment,// instead of creating a new tag, may only be used// in conjuction with attributesArrayXML_SERIALIZER_OPTION_COMMENT_KEY => null,// tag names that will be changedXML_SERIALIZER_OPTION_TAGMAP => array(),// function that will be applied before serializingXML_SERIALIZER_OPTION_ENCODE_FUNC => null,// namespace to useXML_SERIALIZER_OPTION_NAMESPACE => null,// type of entities to replace,XML_SERIALIZER_OPTION_ENTITIES => XML_SERIALIZER_ENTITIES_XML,// serialize() returns the result of the serialization instead of trueXML_SERIALIZER_OPTION_RETURN_RESULT => false,// ignore properties that are set to nullXML_SERIALIZER_OPTION_IGNORE_NULL => false,// Whether to use cdata sections for plain character dataXML_SERIALIZER_OPTION_CDATA_SECTIONS => false,// Whether to convert a boolean FALSE into a stringXML_SERIALIZER_OPTION_FALSE_AS_STRING => false,);/*** Options for the serialization** @access public* @var array*/var $options = array();/*** Current tag depth** @access private* @var integer*/var $_tagDepth = 0;/*** Serialized representation of the data** @access private* @var string*/var $_serializedData = null;/*** Constructor** @param mixed $options array containing options for the serialization** @access public*/function XML_Serializer( $options = null ){$this->PEAR();if (is_array($options)) {$this->options = array_merge($this->_defaultOptions, $options);} else {$this->options = $this->_defaultOptions;}}/*** Return the package version number** @access public* @static* @return string the version number of XML_Serializer*/function apiVersion(){return '@package_version@';}/*** Reset all options to default options** @return void* @access public*/function resetOptions(){$this->options = $this->_defaultOptions;}/*** Set an option** You can use this method if you do not want* to set all options in the constructor.** @param string $name option name* @param mixed $value option value** @return void* @access public*/function setOption($name, $value){$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.** @param array $options options array** @return void* @access public*/function setOptions($options){$this->options = array_merge($this->options, $options);}/*** serialize data** @param mixed $data data to serialize* @param array $options options array** @return boolean true on success, pear error on failure* @access public* @uses XML_Util::getDoctypeDeclaration()* @uses XML_Util::getXMLDeclaration()* @internal uses error suppression "@settype()"*/function serialize($data, $options = null){// if options have been specified, use them instead// of the previously defined onesif (is_array($options)) {$optionsBak = $this->options;if (isset($options['overrideOptions'])&& $options['overrideOptions'] == true) {$this->options = array_merge($this->_defaultOptions, $options);} else {$this->options = array_merge($this->options, $options);}} else {$optionsBak = null;}// start depth is zero$this->_tagDepth = 0;$rootAttributes = $this->options[XML_SERIALIZER_OPTION_ROOT_ATTRIBS];if (isset($this->options[XML_SERIALIZER_OPTION_NAMESPACE])&& is_array($this->options[XML_SERIALIZER_OPTION_NAMESPACE])) {$rootAttributes['xmlns:'. $this->options[XML_SERIALIZER_OPTION_NAMESPACE][0]] =$this->options[XML_SERIALIZER_OPTION_NAMESPACE][1];}$this->_serializedData = '';// serialize an arrayif (is_array($data)) {if (isset($this->options[XML_SERIALIZER_OPTION_ROOT_NAME])) {$tagName = $this->options[XML_SERIALIZER_OPTION_ROOT_NAME];} else {$tagName = 'array';}$this->_serializedData .=$this->_serializeArray($data, $tagName, $rootAttributes);} elseif (is_object($data)) {// serialize an objectif (isset($this->options[XML_SERIALIZER_OPTION_ROOT_NAME])) {$tagName = $this->options[XML_SERIALIZER_OPTION_ROOT_NAME];} else {$tagName = get_class($data);}$this->_serializedData .=$this->_serializeObject($data, $tagName, $rootAttributes);} else {$tag = array();if (isset($this->options[XML_SERIALIZER_OPTION_ROOT_NAME])) {$tag['qname'] = $this->options[XML_SERIALIZER_OPTION_ROOT_NAME];} else {$tag['qname'] = gettype($data);}$tagName = $tag['qname'];if ($this->options[XML_SERIALIZER_OPTION_TYPEHINTS] === true) {$rootAttributes[$this->options[XML_SERIALIZER_OPTION_ATTRIBUTE_TYPE]] = gettype($data);}if (!is_bool($data)) {$tag['content'] = $data;} elseif ($data === false) {if ($this->options[XML_SERIALIZER_OPTION_FALSE_AS_STRING] === true) {$tag['content'] = '0';} else {$tag['content'] = '';}} else {$tag['content'] = $data;}@settype($data, 'string');$tag['attributes'] = $rootAttributes;$this->_serializedData = $this->_createXMLTag($tag);}// add doctype declarationif ($this->options[XML_SERIALIZER_OPTION_DOCTYPE_ENABLED] === true) {$this->_serializedData =XML_Util::getDoctypeDeclaration($tagName,$this->options[XML_SERIALIZER_OPTION_DOCTYPE]). $this->options[XML_SERIALIZER_OPTION_LINEBREAKS]. $this->_serializedData;}// build xml declarationif ($this->options[XML_SERIALIZER_OPTION_XML_DECL_ENABLED]) {$atts = array();$this->_serializedData = XML_Util::getXMLDeclaration('1.0',$this->options[XML_SERIALIZER_OPTION_XML_ENCODING]). $this->options[XML_SERIALIZER_OPTION_LINEBREAKS]. $this->_serializedData;}if ($this->options[XML_SERIALIZER_OPTION_RETURN_RESULT] === true) {$result = $this->_serializedData;} else {$result = true;}if ($optionsBak !== null) {$this->options = $optionsBak;}return $result;}/*** get the result of the serialization** @access public* @return string serialized XML*/function getSerializedData(){if ($this->_serializedData == null) {return $this->raiseError('No serialized data available. '. 'Use XML_Serializer::serialize() first.',XML_SERIALIZER_ERROR_NO_SERIALIZATION);}return $this->_serializedData;}/*** serialize any value** This method checks for the type of the value and calls the appropriate method** @param mixed $value tag value* @param string $tagName tag name* @param array $attributes attributes** @return string* @access private*/function _serializeValue($value, $tagName = null, $attributes = array()){if (is_array($value)) {$xml = $this->_serializeArray($value, $tagName, $attributes);} elseif (is_object($value)) {$xml = $this->_serializeObject($value, $tagName);} else {$tag = array('qname' => $tagName,'attributes' => $attributes,'content' => $value);$xml = $this->_createXMLTag($tag);}return $xml;}/*** serialize an array** @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* @access private* @uses XML_Util::isValidName() to check, whether key has to be substituted* @uses XML_Util::replaceEntities()* @uses XML_Util::createComment()* @uses PEAR::popExpect()* @uses PEAR::expectError()*/function _serializeArray(&$array, $tagName = null, $attributes = array()){$_content = null;$_comment = null;// check for commentif ($this->options[XML_SERIALIZER_OPTION_COMMENT_KEY] !== null) {if (isset($array[$this->options[XML_SERIALIZER_OPTION_COMMENT_KEY]])) {$_comment =$array[$this->options[XML_SERIALIZER_OPTION_COMMENT_KEY]];unset($array[$this->options[XML_SERIALIZER_OPTION_COMMENT_KEY]]);}}/*** check for special attributes*/if ($this->options[XML_SERIALIZER_OPTION_ATTRIBUTES_KEY] !== null) {if (isset($array[$this->options[XML_SERIALIZER_OPTION_ATTRIBUTES_KEY]])) {$attributes =$array[$this->options[XML_SERIALIZER_OPTION_ATTRIBUTES_KEY]];unset($array[$this->options[XML_SERIALIZER_OPTION_ATTRIBUTES_KEY]]);}/*** check for special content*/if ($this->options[XML_SERIALIZER_OPTION_CONTENT_KEY] !== null) {if (isset($array[$this->options[XML_SERIALIZER_OPTION_CONTENT_KEY]])) {$_content =XML_Util::replaceEntities($array[$this->options[XML_SERIALIZER_OPTION_CONTENT_KEY]]);unset($array[$this->options[XML_SERIALIZER_OPTION_CONTENT_KEY]]);}}}if ($this->options[XML_SERIALIZER_OPTION_IGNORE_NULL] === true) {foreach (array_keys($array) as $key) {if (is_null($array[$key])) {unset($array[$key]);}}}/** if mode is set to simpleXML, check whether* the array is associative or indexed*/if (is_array($array) && !empty($array)&& $this->options[XML_SERIALIZER_OPTION_MODE]== XML_SERIALIZER_MODE_SIMPLEXML) {$indexed = true;foreach ($array as $key => $val) {if (!is_int($key)) {$indexed = false;break;}}if ($indexed&& $this->options[XML_SERIALIZER_OPTION_MODE]== XML_SERIALIZER_MODE_SIMPLEXML) {$string = '';foreach ($array as $key => $val) {$string .= $this->_serializeValue($val, $tagName, $attributes);$string .= $this->options[XML_SERIALIZER_OPTION_LINEBREAKS];// do indentationif ($this->options[XML_SERIALIZER_OPTION_INDENT]!==null&& $this->_tagDepth>0) {$string .=str_repeat($this->options[XML_SERIALIZER_OPTION_INDENT],$this->_tagDepth);}}return rtrim($string);}}$scalarAsAttributes = false;if (is_array($this->options[XML_SERIALIZER_OPTION_SCALAR_AS_ATTRIBUTES])&& isset($this->options[XML_SERIALIZER_OPTION_SCALAR_AS_ATTRIBUTES][$tagName])) {$scalarAsAttributes =$this->options[XML_SERIALIZER_OPTION_SCALAR_AS_ATTRIBUTES][$tagName];} elseif ($this->options[XML_SERIALIZER_OPTION_SCALAR_AS_ATTRIBUTES] === true) {$scalarAsAttributes = true;}if ($scalarAsAttributes === true) {$this->expectError('*');foreach ($array as $key => $value) {if (is_scalar($value) && (XML_Util::isValidName($key) === true)) {unset($array[$key]);$attributes[$this->options[XML_SERIALIZER_OPTION_PREPEND_ATTRIBUTES].$key] = $value;}}$this->popExpect();} elseif (is_array($scalarAsAttributes)) {$this->expectError('*');foreach ($scalarAsAttributes as $key) {if (!isset($array[$key])) {continue;}$value = $array[$key];if (is_scalar($value) && (XML_Util::isValidName($key) === true)) {unset($array[$key]);$attributes[$this->options[XML_SERIALIZER_OPTION_PREPEND_ATTRIBUTES].$key] = $value;}}$this->popExpect();}// check for empty array => create empty tagif (empty($array)) {$tag = array('qname' => $tagName,'content' => $_content,'attributes' => $attributes);} else {$this->_tagDepth++;$tmp = $_content . $this->options[XML_SERIALIZER_OPTION_LINEBREAKS];foreach ($array as $key => $value) {// do indentationif ($this->options[XML_SERIALIZER_OPTION_INDENT]!==null&& $this->_tagDepth>0) {$tmp .= str_repeat($this->options[XML_SERIALIZER_OPTION_INDENT],$this->_tagDepth);}// copy key$origKey = $key;$this->expectError('*');// key cannot be used as tagname => use default tag$valid = XML_Util::isValidName($key);$this->popExpect();if (PEAR::isError($valid)) {if ($this->options[XML_SERIALIZER_OPTION_CLASSNAME_AS_TAGNAME]&& is_object($value)) {$key = get_class($value);} else {$key = $this->_getDefaultTagname($tagName);}}// once we've established the true $key, is there a tagmap for it?if (isset($this->options[XML_SERIALIZER_OPTION_TAGMAP][$key])) {$key = $this->options[XML_SERIALIZER_OPTION_TAGMAP][$key];}$atts = array();if ($this->options[XML_SERIALIZER_OPTION_TYPEHINTS] === true) {$atts[$this->options[XML_SERIALIZER_OPTION_ATTRIBUTE_TYPE]] =gettype($value);if ($key !== $origKey) {$atts[$this->options[XML_SERIALIZER_OPTION_ATTRIBUTE_KEY]] =(string)$origKey;}}$tmp .= $this->_createXMLTag(array('qname' => $key,'attributes' => $atts,'content' => $value));$tmp .= $this->options[XML_SERIALIZER_OPTION_LINEBREAKS];}$this->_tagDepth--;if ($this->options[XML_SERIALIZER_OPTION_INDENT]!==null&& $this->_tagDepth>0) {$tmp .= str_repeat($this->options[XML_SERIALIZER_OPTION_INDENT],$this->_tagDepth);}if (trim($tmp) === '') {$tmp = null;}$tag = array('qname' => $tagName,'content' => $tmp,'attributes' => $attributes);}if ($this->options[XML_SERIALIZER_OPTION_TYPEHINTS] === true) {if (!isset($tag['attributes'][$this->options[XML_SERIALIZER_OPTION_ATTRIBUTE_TYPE]])) {$tag['attributes'][$this->options[XML_SERIALIZER_OPTION_ATTRIBUTE_TYPE]] = 'array';}}$string = '';if (!is_null($_comment)) {$string .= XML_Util::createComment($_comment);$string .= $this->options[XML_SERIALIZER_OPTION_LINEBREAKS];if ($this->options[XML_SERIALIZER_OPTION_INDENT]!==null&& $this->_tagDepth>0) {$string .= str_repeat($this->options[XML_SERIALIZER_OPTION_INDENT],$this->_tagDepth);}}$string .= $this->_createXMLTag($tag, false);return $string;}/*** get the name of the default tag.** The name of the parent tag needs to be passed as the* default name can depend on the context.** @param string $parent name of the parent tag** @return string default tag name*/function _getDefaultTagname($parent){if (is_string($this->options[XML_SERIALIZER_OPTION_DEFAULT_TAG])) {return $this->options[XML_SERIALIZER_OPTION_DEFAULT_TAG];}if (isset($this->options[XML_SERIALIZER_OPTION_DEFAULT_TAG][$parent])) {return $this->options[XML_SERIALIZER_OPTION_DEFAULT_TAG][$parent];} elseif (isset($this->options[XML_SERIALIZER_OPTION_DEFAULT_TAG]['#default'])) {return $this->options[XML_SERIALIZER_OPTION_DEFAULT_TAG]['#default'];} elseif (isset($this->options[XML_SERIALIZER_OPTION_DEFAULT_TAG]['__default'])) {// keep this for BCreturn $this->options[XML_SERIALIZER_OPTION_DEFAULT_TAG]['__default'];}return 'XML_Serializer_Tag';}/*** serialize an object** @param object &$object object to serialize* @param string $tagName tag name* @param array $attributes attributes** @return string $string serialized data* @access private*/function _serializeObject(&$object, $tagName = null, $attributes = array()){// check for magic functionif (method_exists($object, '__sleep')) {$propNames = $object->__sleep();if (is_array($propNames)) {$properties = array();foreach ($propNames as $propName) {$properties[$propName] = $object->$propName;}} else {$properties = get_object_vars($object);}} else {$properties = get_object_vars($object);}if (empty($tagName)) {$tagName = get_class($object);}// typehints activated?if ($this->options[XML_SERIALIZER_OPTION_TYPEHINTS] === true) {$attributes[$this->options[XML_SERIALIZER_OPTION_ATTRIBUTE_TYPE]] ='object';$attributes[$this->options[XML_SERIALIZER_OPTION_ATTRIBUTE_CLASS]] =get_class($object);}$string = $this->_serializeArray($properties, $tagName, $attributes);return $string;}/*** create a tag from an array* this method awaits an array in the following format* array(* 'qname' => $tagName,* 'attributes' => array(),* 'content' => $content, // optional* 'namespace' => $namespace // optional* 'namespaceUri' => $namespaceUri // optional* )** @param array $tag tag definition* @param boolean $firstCall whether or not this is the first call** @return string $string XML tag* @access private*/function _createXMLTag($tag, $firstCall = true){// build fully qualified tag nameif ($this->options[XML_SERIALIZER_OPTION_NAMESPACE] !== null) {if (is_array($this->options[XML_SERIALIZER_OPTION_NAMESPACE])) {$tag['qname'] = $this->options[XML_SERIALIZER_OPTION_NAMESPACE][0]. ':' . $tag['qname'];} else {$tag['qname'] = $this->options[XML_SERIALIZER_OPTION_NAMESPACE]. ':' . $tag['qname'];}}// attribute indentationif ($this->options[XML_SERIALIZER_OPTION_INDENT_ATTRIBUTES] !== false) {$multiline = true;$indent = str_repeat($this->options[XML_SERIALIZER_OPTION_INDENT],$this->_tagDepth);if ($this->options[XML_SERIALIZER_OPTION_INDENT_ATTRIBUTES] == '_auto') {$indent .= str_repeat(' ', (strlen($tag['qname'])+2));} else {$indent .= $this->options[XML_SERIALIZER_OPTION_INDENT_ATTRIBUTES];}} else {$multiline = false;$indent = false;}if (is_array($tag['content'])) {if (empty($tag['content'])) {$tag['content'] = '';}} elseif (XML_SERIALIZER_OPTION_FALSE_AS_STRING && $tag['content'] === false) {$tag['content'] = '0';} elseif (is_scalar($tag['content']) && (string)$tag['content'] == '') {$tag['content'] = '';}// replace XML entitiesif ($firstCall === true) {if ($this->options[XML_SERIALIZER_OPTION_CDATA_SECTIONS] === true) {$replaceEntities = XML_UTIL_CDATA_SECTION;} else {$replaceEntities = $this->options[XML_SERIALIZER_OPTION_ENTITIES];}} else {// this is a nested call, so value is already encoded// and must not be encoded again$replaceEntities = XML_SERIALIZER_ENTITIES_NONE;// but attributes need to be encoded anyways// (done here because the rest of the code assumes the same encoding// can be used both for attributes and content)foreach ($tag['attributes'] as $k => $v) {$v = XML_Util::replaceEntities($v,$this->options[XML_SERIALIZER_OPTION_ENTITIES]);$tag['attributes'][$k] = $v;}}if (is_scalar($tag['content']) || is_null($tag['content'])) {if ($this->options[XML_SERIALIZER_OPTION_ENCODE_FUNC]) {if ($firstCall === true) {$tag['content'] = call_user_func($this->options[XML_SERIALIZER_OPTION_ENCODE_FUNC], $tag['content']);}$tag['attributes'] = array_map($this->options[XML_SERIALIZER_OPTION_ENCODE_FUNC], $tag['attributes']);}$tag = XML_Util::createTagFromArray($tag, $replaceEntities, $multiline,$indent, $this->options[XML_SERIALIZER_OPTION_LINEBREAKS]);} elseif (is_array($tag['content'])) {$tag = $this->_serializeArray($tag['content'], $tag['qname'],$tag['attributes']);} elseif (is_object($tag['content'])) {$tag = $this->_serializeObject($tag['content'], $tag['qname'],$tag['attributes']);} elseif (is_resource($tag['content'])) {settype($tag['content'], 'string');if ($this->options[XML_SERIALIZER_OPTION_ENCODE_FUNC]) {if ($replaceEntities === true) {$tag['content'] = call_user_func($this->options[XML_SERIALIZER_OPTION_ENCODE_FUNC], $tag['content']);}$tag['attributes'] = array_map($this->options[XML_SERIALIZER_OPTION_ENCODE_FUNC],$tag['attributes']);}$tag = XML_Util::createTagFromArray($tag, $replaceEntities);}return $tag;}}?>