XML_Serializer
[ class tree: XML_Serializer ] [ index: XML_Serializer ] [ all elements ]

Source for file Unserializer.php

Documentation is available at Unserializer.php

  1. <?PHP
  2. /* vim: set expandtab tabstop=4 shiftwidth=4: */
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2002 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.0 of the PHP license,       |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available at through the world-wide-web at                           |
  11. // | http://www.php.net/license/2_02.txt.                                 |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Stephan Schmidt <schst@php-tools.net>                       |
  17. // +----------------------------------------------------------------------+
  18. //
  19. //    $Id: Unserializer.php,v 1.15 2004/04/23 17:17:48 schst Exp $
  20.  
  21. /**
  22.  * uses PEAR error managemt
  23.  */
  24. require_once 'PEAR.php';
  25.  
  26. /**
  27.  * uses XML_Parser to unserialize document
  28.  */
  29. require_once 'XML/Parser.php';
  30.  
  31. /**
  32.  * error code for no serialization done
  33.  */
  34. define("XML_UNSERIALIZER_ERROR_NO_UNSERIALIZATION"151);
  35.  
  36. /**
  37.  * XML_Unserializer
  38.  *
  39.  * class to unserialize XML documents that have been created with
  40.  * XML_Serializer. To unserialize an XML document you have to add
  41.  * type hints to the XML_Serializer options.
  42.  *
  43.  * If no type hints are available, XML_Unserializer will guess how
  44.  * the tags should be treated, that means complex structures will be
  45.  * arrays and tags with only CData in them will be strings.
  46.  *
  47.  * <code>
  48.  * require_once 'XML/Unserializer.php';
  49.  *
  50.  * //  be careful to always use the ampersand in front of the new operator
  51.  * $unserializer = &new XML_Unserializer();
  52.  *
  53.  * $unserializer->unserialize($xml);
  54.  *
  55.  * $data = $unserializer->getUnserializedData();
  56.  * <code>
  57.  *
  58.  * Possible options for the Unserializer are:
  59.  *
  60.  * 1. complexTypes => array|object
  61.  * This is needed, when unserializing XML files w/o type hints. If set to
  62.  * 'array' (default), all nested tags will be arrays, if set to 'object'
  63.  * all nested tags will be objects, that means you have read access like:
  64.  *
  65.  * <code>
  66.  * require_once 'XML/Unserializer.php';
  67.  * $options = array('complexType' => 'object');
  68.  * $unserializer = &new XML_Unserializer($options);
  69.  *
  70.  * $unserializer->unserialize('http://pear.php.net/rss.php');
  71.  *
  72.  * $rss = $unserializer->getUnserializedData();
  73.  * echo $rss->channel->item[3]->title;
  74.  * </code>
  75.  *
  76.  * 2. keyAttribute
  77.  * This lets you specify an attribute inside your tags, that are used as key
  78.  * for associative arrays or object properties.
  79.  * You will need this if you have XML that looks like this:
  80.  *
  81.  * <users>
  82.  *   <user handle="schst">Stephan Schmidt</user>
  83.  *   <user handle="ssb">Stig S. Bakken</user>
  84.  * </users>
  85.  *
  86.  * Then you can use:
  87.  * <code>
  88.  * require_once 'XML/Unserializer.php';
  89.  * $options = array('keyAttribute' => 'handle');
  90.  * $unserializer = &new XML_Unserializer($options);
  91.  *
  92.  * $unserializer->unserialize($xml, false);
  93.  *
  94.  * $users = $unserializer->getUnserializedData();
  95.  * </code>
  96.  *
  97.  * @category XML
  98.  * @package  XML_Serializer
  99.  * @version  0.9.1
  100.  * @author   Stephan Schmidt <schst@php-tools.net>
  101.  * @uses     XML_Parser
  102.  */
  103. class XML_Unserializer extends XML_Parser {
  104.  
  105.    /**
  106.     * default options for the serialization
  107.     * @access private
  108.     * @var array $_defaultOptions 
  109.     */
  110.     var $_defaultOptions = array(
  111.                          "complexType"       => "array",                // complex types will be converted to arrays, if no type hint is given
  112.                          "keyAttribute"      => "_originalKey",         // get array key/property name from this attribute
  113.                          "typeAttribute"     => "_type",                // get type from this attribute
  114.                          "classAttribute"    => "_class",               // get class from this attribute (if not given, use tag name)
  115.                          "parseAttributes"   => false,                  // parse the attributes of the tag into an array
  116.                          "attributesArray"   => false,                  // parse them into sperate array (specify name of array here)
  117.                          "prependAttributes" => "",                     // prepend attribute names with this string
  118.                          "contentName"       => "_content",             // put cdata found in a tag that has been converted to a complex type in this key
  119.                          "tagMap"            => array()                 // use this to map tagnames
  120.                         );
  121.  
  122.    /**
  123.     * actual options for the serialization
  124.     * @access private
  125.     * @var array $options 
  126.     */
  127.     var $options = array();
  128.  
  129.    /**
  130.     * do not use case folding
  131.     * @var boolean $folding 
  132.     */
  133.     var $folding = false;
  134.  
  135.    /**
  136.     * unserilialized data
  137.     * @var string $_serializedData 
  138.     */
  139.     var $_unserializedData = null;
  140.  
  141.    /**
  142.     * name of the root tag
  143.     * @var string $_root 
  144.     */
  145.     var $_root = null;
  146.  
  147.    /**
  148.     * stack for all data that is found
  149.     * @var array    $_dataStack 
  150.     */
  151.     var $_dataStack  =   array();
  152.  
  153.    /**
  154.     * stack for all values that are generated
  155.     * @var array    $_valStack 
  156.     */
  157.     var $_valStack  =   array();
  158.  
  159.    /**
  160.     * current tag depth
  161.     * @var int    $_depth 
  162.     */
  163.     var $_depth = 0;
  164.  
  165.    /**
  166.     * constructor
  167.     *
  168.     * @access   public
  169.     * @param    mixed   $options    array containing options for the serialization
  170.     */
  171.     function XML_Unserializer($options = null)
  172.     {
  173.         // reset parser and properties
  174.         $this->XML_Parser(null,"event");
  175.  
  176.         if (is_array($options)) {
  177.             $this->options array_merge($this->_defaultOptions$options);
  178.         else {
  179.             $this->options $this->_defaultOptions;
  180.         }
  181.     }
  182.  
  183.    /**
  184.     * return API version
  185.     *
  186.     * @access   public
  187.     * @static
  188.     * @return   string  $version API version
  189.     */
  190.     function apiVersion()
  191.     {
  192.         return "0.9";
  193.     }
  194.  
  195.    /**
  196.     * reset all options to default options
  197.     *
  198.     * @access   public
  199.     * @see      setOption(), XML_Unserializer()
  200.     */
  201.     function resetOptions()
  202.     {
  203.         $this->options $this->_defaultOptions;
  204.     }
  205.  
  206.    /**
  207.     * set an option
  208.     *
  209.     * You can use this method if you do not want to set all options in the constructor
  210.     *
  211.     * @access   public
  212.     * @see      resetOption(), XML_Unserializer()
  213.     */
  214.     function setOption($name$value)
  215.     {
  216.         $this->options[$name$value;
  217.     }
  218.  
  219.    /**
  220.     * unserialize data
  221.     *
  222.     * @access   public
  223.     * @param    mixed    $data   data to unserialize (string, filename or resource)
  224.     * @param    boolean  $isFile string should be treated as a file
  225.     * @param    array    $options 
  226.     * @return   boolean  $success
  227.     */
  228.     function unserialize($data$isFile = false$options = null)
  229.     {
  230.         $this->_unserializedData = null;
  231.         $this->_root = null;
  232.  
  233.         // if options have been specified, use them instead
  234.         // of the previously defined ones
  235.         if (is_array($options)) {
  236.             $optionsBak $this->options;
  237.             if (isset($options["overrideOptions"]&& $options["overrideOptions"== true{
  238.                 $this->options array_merge($this->_defaultOptions$options);
  239.             else {
  240.                 $this->options array_merge($this->options$options);
  241.             }
  242.         }
  243.         else {
  244.             $optionsBak = null;
  245.         }
  246.  
  247.         $this->_valStack = array();
  248.         $this->_dataStack = array();
  249.         $this->_depth = 0;
  250.  
  251.         if (is_string($data)) {
  252.             if ($isFile{
  253.                 $result $this->setInputFile($data);
  254.                 if (PEAR::isError($result)) {
  255.                     return $result;
  256.                 }
  257.                 $result $this->parse();
  258.             else {
  259.                 $result $this->parseString($data,true);
  260.             }
  261.         else {
  262.            $this->setInput($data);
  263.            $result $this->parse();
  264.         }
  265.  
  266.         if ($optionsBak !== null{
  267.             $this->options $optionsBak;
  268.         }
  269.  
  270.         if (PEAR::isError($result)) {
  271.             return $result;
  272.         }
  273.  
  274.         return  true;
  275.     }
  276.  
  277.    /**
  278.     *   get the result of the serialization
  279.     *
  280.     *   @access public
  281.     *   @return string  $serializedData
  282.     */
  283.         function getUnserializedData()
  284.         {
  285.             if ($this->_root === null {
  286.                 return  $this->raiseError("No unserialized data available. Use XML_Unserializer::unserialize() first."XML_UNSERIALIZER_ERROR_NO_UNSERIALIZATION);
  287.             }
  288.             return $this->_unserializedData;
  289.         }
  290.  
  291.    /**
  292.     *   get the name of the root tag
  293.     *
  294.     *   @access public
  295.     *   @return string  $rootName
  296.     */
  297.         function getRootName()
  298.         {
  299.             if ($this->_root === null {
  300.                 return  $this->raiseError("No unserialized data available. Use XML_Unserializer::unserialize() first."XML_UNSERIALIZER_ERROR_NO_UNSERIALIZATION);
  301.             }
  302.             return $this->_root;
  303.         }
  304.  
  305.     /**
  306.      * Start element handler for XML parser
  307.      *
  308.      * @access private
  309.      * @param  object $parser  XML parser object
  310.      * @param  string $element XML element
  311.      * @param  array  $attribs attributes of XML tag
  312.      * @return void 
  313.      */
  314.     function startHandler($parser$element$attribs)
  315.     {
  316.         if (isset($attribs[$this->options["typeAttribute"]])) {
  317.             $type $attribs[$this->options["typeAttribute"]];
  318.         else {
  319.             $type "string";
  320.         }
  321.  
  322.         $this->_depth++;
  323.         $this->_dataStack[$this->_depth= null;
  324.  
  325.         $val = array(
  326.                      "name"         => $element,
  327.                      "value"        => null,
  328.                      "type"         => $type,
  329.                      "childrenKeys" => array(),
  330.                      "aggregKeys"   => array()
  331.                     );
  332.  
  333.         if ($this->options["parseAttributes"== true && (count($attribs> 0)) {
  334.             $val["children"= array();
  335.             $val["type"$this->options["complexType"];
  336.  
  337.             if ($this->options["attributesArray"!= false{
  338.                 $val["children"][$this->options["attributesArray"]] $attribs;
  339.             else {
  340.                 foreach ($attribs as $attrib => $value{
  341.                     $val["children"][$this->options["prependAttributes"].$attrib$value;
  342.                 }
  343.             }
  344.         }
  345.  
  346.         if (isset($attribs[$this->options["keyAttribute"]])) {
  347.             $val["name"$attribs[$this->options["keyAttribute"]];
  348.         }
  349.  
  350.         if (isset($attribs[$this->options["classAttribute"]])) {
  351.             $val["class"$attribs[$this->options["classAttribute"]];
  352.         }
  353.  
  354.         array_push($this->_valStack$val);
  355.     }
  356.  
  357.     /**
  358.      * End element handler for XML parser
  359.      *
  360.      * @access private
  361.      * @param  object XML parser object
  362.      * @param  string 
  363.      * @return void 
  364.      */
  365.     function endHandler($parser$element)
  366.     {
  367.         $value array_pop($this->_valStack);
  368.         $data  trim($this->_dataStack[$this->_depth]);
  369.  
  370.         // adjust type of the value
  371.         switch(strtolower($value["type"])) {
  372.             /*
  373.              * unserialize an object
  374.              */
  375.             case "object":
  376.                 if(isset($value['class'])) {
  377.                     $classname  $value["class"];
  378.                 else {
  379.                     $classname '';
  380.                 }
  381.                 if (is_array($this->options["tagMap"]&& isset($this->options["tagMap"][$classname])) {
  382.                     $classname $this->options["tagMap"][$classname];
  383.                 }
  384.  
  385.                 // instantiate the class
  386.                 if (class_exists($classname)) {
  387.                     $value["value"&new $classname;
  388.                 else {
  389.                     $value["value"&new stdClass;
  390.                 }
  391.                 if ($data !== ''{
  392.                     $value["children"][$this->options["contentName"]] $data;
  393.                 }
  394.  
  395.                 // set properties
  396.                 foreach($value["children"as $prop => $propVal{
  397.                     // check whether there is a special method to set this property
  398.                     $setMethod "set".$prop;
  399.                     if (method_exists($value["value"]$setMethod)) {
  400.                         call_user_func(array(&$value["value"]$setMethod)$propVal);
  401.                     else {
  402.                         $value["value"]->$prop $propVal;
  403.                     }
  404.                 }
  405.                 //  check for magic function
  406.                 if (method_exists($value["value"]"__wakeup")) {
  407.                     $value["value"]->__wakeup();
  408.                 }
  409.                 break;
  410.  
  411.             /*
  412.              * unserialize an array
  413.              */
  414.             case "array":
  415.                 if ($data !== ''{
  416.                     $value["children"][$this->options["contentName"]] $data;
  417.                 }
  418.  
  419.                 $value["value"$value["children"];
  420.                 break;
  421.  
  422.             /*
  423.              * unserialize a null value
  424.              */
  425.             case "null":
  426.                 $data = null;
  427.                 break;
  428.  
  429.             /*
  430.              * unserialize a resource => this is not possible :-(
  431.              */
  432.             case "resource":
  433.                 $value["value"$data;
  434.                 break;
  435.  
  436.             /*
  437.              * unserialize any scalar value
  438.              */
  439.             default:
  440.                 settype($data$value["type"]);
  441.                 $value["value"$data;
  442.                 break;
  443.         }
  444.         $parent array_pop($this->_valStack);
  445.         if ($parent === null{
  446.             $this->_unserializedData &$value["value"];
  447.             $this->_root &$value["name"];
  448.             return true;
  449.         else {
  450.             // parent has to be an array
  451.             if (!isset($parent["children"]|| !is_array($parent["children"])) {
  452.                 $parent["children"= array();
  453.                 if (!in_array($parent["type"]array("array""object"))) {
  454.                     $parent["type"$this->options["complexType"];
  455.                     if ($this->options["complexType"== "object"{
  456.                         $parent["class"$parent["name"];
  457.                     }
  458.                 }
  459.             }
  460.  
  461.             if (!empty($value["name"])) {
  462.                 // there already has been a tag with this name
  463.                 if (in_array($value["name"]$parent["childrenKeys"])) {
  464.                     // no aggregate has been created for this tag
  465.                     if (!in_array($value["name"]$parent["aggregKeys"])) {
  466.                         $parent["children"][$value["name"]] = array($parent["children"][$value["name"]]);
  467.                         array_push($parent["aggregKeys"]$value["name"]);
  468.                     }
  469.                     array_push($parent["children"][$value["name"]]$value["value"]);
  470.                 else {
  471.                     $parent["children"][$value["name"]] &$value["value"];
  472.                     array_push($parent["childrenKeys"]$value["name"]);
  473.                 }
  474.             else {
  475.                 array_push($parent["children"],$value["value"]);
  476.             }
  477.             array_push($this->_valStack$parent);
  478.         }
  479.  
  480.         $this->_depth--;
  481.     }
  482.  
  483.     /**
  484.      * Handler for character data
  485.      *
  486.      * @access private
  487.      * @param  object XML parser object
  488.      * @param  string CDATA
  489.      * @return void 
  490.      */
  491.     function cdataHandler($parser$cdata)
  492.     {
  493.         $this->_dataStack[$this->_depth.= $cdata;
  494.     }
  495. }
  496. ?>

Documentation generated on Mon, 11 Mar 2019 10:15:35 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.