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.17 2004/07/12 13:33:42 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(), setOptions()
  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(), setOptions()
  213.     */
  214.     function setOption($name$value)
  215.     {
  216.         $this->options[$name$value;
  217.     }
  218.  
  219.    /**
  220.     * sets several options at once
  221.     *
  222.     * You can use this method if you do not want to set all options in the constructor
  223.     *
  224.     * @access   public
  225.     * @see      resetOption(), XML_Unserializer(), setOption()
  226.     */
  227.     function setOptions($options)
  228.     {
  229.         $this->options array_merge($this->options$options);
  230.     }
  231.  
  232.    /**
  233.     * unserialize data
  234.     *
  235.     * @access   public
  236.     * @param    mixed    $data   data to unserialize (string, filename or resource)
  237.     * @param    boolean  $isFile string should be treated as a file
  238.     * @param    array    $options 
  239.     * @return   boolean  $success
  240.     */
  241.     function unserialize($data$isFile = false$options = null)
  242.     {
  243.         $this->_unserializedData = null;
  244.         $this->_root = null;
  245.  
  246.         // if options have been specified, use them instead
  247.         // of the previously defined ones
  248.         if (is_array($options)) {
  249.             $optionsBak $this->options;
  250.             if (isset($options["overrideOptions"]&& $options["overrideOptions"== true{
  251.                 $this->options array_merge($this->_defaultOptions$options);
  252.             else {
  253.                 $this->options array_merge($this->options$options);
  254.             }
  255.         }
  256.         else {
  257.             $optionsBak = null;
  258.         }
  259.  
  260.         $this->_valStack = array();
  261.         $this->_dataStack = array();
  262.         $this->_depth = 0;
  263.  
  264.         if (is_string($data)) {
  265.             if ($isFile{
  266.                 $result $this->setInputFile($data);
  267.                 if (PEAR::isError($result)) {
  268.                     return $result;
  269.                 }
  270.                 $result $this->parse();
  271.             else {
  272.                 $result $this->parseString($data,true);
  273.             }
  274.         else {
  275.            $this->setInput($data);
  276.            $result $this->parse();
  277.         }
  278.  
  279.         if ($optionsBak !== null{
  280.             $this->options $optionsBak;
  281.         }
  282.  
  283.         if (PEAR::isError($result)) {
  284.             return $result;
  285.         }
  286.  
  287.         return  true;
  288.     }
  289.  
  290.    /**
  291.     *   get the result of the serialization
  292.     *
  293.     *   @access public
  294.     *   @return string  $serializedData
  295.     */
  296.         function getUnserializedData()
  297.         {
  298.             if ($this->_root === null {
  299.                 return  $this->raiseError("No unserialized data available. Use XML_Unserializer::unserialize() first."XML_UNSERIALIZER_ERROR_NO_UNSERIALIZATION);
  300.             }
  301.             return $this->_unserializedData;
  302.         }
  303.  
  304.    /**
  305.     *   get the name of the root tag
  306.     *
  307.     *   @access public
  308.     *   @return string  $rootName
  309.     */
  310.         function getRootName()
  311.         {
  312.             if ($this->_root === null {
  313.                 return  $this->raiseError("No unserialized data available. Use XML_Unserializer::unserialize() first."XML_UNSERIALIZER_ERROR_NO_UNSERIALIZATION);
  314.             }
  315.             return $this->_root;
  316.         }
  317.  
  318.     /**
  319.      * Start element handler for XML parser
  320.      *
  321.      * @access private
  322.      * @param  object $parser  XML parser object
  323.      * @param  string $element XML element
  324.      * @param  array  $attribs attributes of XML tag
  325.      * @return void 
  326.      */
  327.     function startHandler($parser$element$attribs)
  328.     {
  329.         if (isset($attribs[$this->options["typeAttribute"]])) {
  330.             $type $attribs[$this->options["typeAttribute"]];
  331.         else {
  332.             $type "string";
  333.         }
  334.  
  335.         $this->_depth++;
  336.         $this->_dataStack[$this->_depth= null;
  337.  
  338.         $val = array(
  339.                      "name"         => $element,
  340.                      "value"        => null,
  341.                      "type"         => $type,
  342.                      "childrenKeys" => array(),
  343.                      "aggregKeys"   => array()
  344.                     );
  345.  
  346.         if ($this->options["parseAttributes"== true && (count($attribs> 0)) {
  347.             $val["children"= array();
  348.             $val["type"$this->options["complexType"];
  349.  
  350.             if ($this->options["attributesArray"!= false{
  351.                 $val["children"][$this->options["attributesArray"]] $attribs;
  352.             else {
  353.                 foreach ($attribs as $attrib => $value{
  354.                     $val["children"][$this->options["prependAttributes"].$attrib$value;
  355.                 }
  356.             }
  357.         }
  358.  
  359.         if (isset($attribs[$this->options["keyAttribute"]])) {
  360.             $val["name"$attribs[$this->options["keyAttribute"]];
  361.         }
  362.  
  363.         if (isset($attribs[$this->options["classAttribute"]])) {
  364.             $val["class"$attribs[$this->options["classAttribute"]];
  365.         }
  366.  
  367.         array_push($this->_valStack$val);
  368.     }
  369.  
  370.     /**
  371.      * End element handler for XML parser
  372.      *
  373.      * @access private
  374.      * @param  object XML parser object
  375.      * @param  string 
  376.      * @return void 
  377.      */
  378.     function endHandler($parser$element)
  379.     {
  380.         $value array_pop($this->_valStack);
  381.         $data  trim($this->_dataStack[$this->_depth]);
  382.  
  383.         // adjust type of the value
  384.         switch(strtolower($value["type"])) {
  385.             /*
  386.              * unserialize an object
  387.              */
  388.             case "object":
  389.                 if(isset($value['class'])) {
  390.                     $classname  $value["class"];
  391.                 else {
  392.                     $classname '';
  393.                 }
  394.                 if (is_array($this->options["tagMap"]&& isset($this->options["tagMap"][$classname])) {
  395.                     $classname $this->options["tagMap"][$classname];
  396.                 }
  397.  
  398.                 // instantiate the class
  399.                 if (class_exists($classname)) {
  400.                     $value["value"&new $classname;
  401.                 else {
  402.                     $value["value"&new stdClass;
  403.                 }
  404.                 if ($data !== ''{
  405.                     $value["children"][$this->options["contentName"]] $data;
  406.                 }
  407.  
  408.                 // set properties
  409.                 foreach($value["children"as $prop => $propVal{
  410.                     // check whether there is a special method to set this property
  411.                     $setMethod "set".$prop;
  412.                     if (method_exists($value["value"]$setMethod)) {
  413.                         call_user_func(array(&$value["value"]$setMethod)$propVal);
  414.                     else {
  415.                         $value["value"]->$prop $propVal;
  416.                     }
  417.                 }
  418.                 //  check for magic function
  419.                 if (method_exists($value["value"]"__wakeup")) {
  420.                     $value["value"]->__wakeup();
  421.                 }
  422.                 break;
  423.  
  424.             /*
  425.              * unserialize an array
  426.              */
  427.             case "array":
  428.                 if ($data !== ''{
  429.                     $value["children"][$this->options["contentName"]] $data;
  430.                 }
  431.                 if (isset($value['children'])) {
  432.                     $value["value"$value["children"];
  433.                 else {
  434.                     $value["value"= array();
  435.                 }
  436.                 break;
  437.  
  438.             /*
  439.              * unserialize a null value
  440.              */
  441.             case "null":
  442.                 $data = null;
  443.                 break;
  444.  
  445.             /*
  446.              * unserialize a resource => this is not possible :-(
  447.              */
  448.             case "resource":
  449.                 $value["value"$data;
  450.                 break;
  451.  
  452.             /*
  453.              * unserialize any scalar value
  454.              */
  455.             default:
  456.                 settype($data$value["type"]);
  457.                 $value["value"$data;
  458.                 break;
  459.         }
  460.         $parent array_pop($this->_valStack);
  461.         if ($parent === null{
  462.             $this->_unserializedData &$value["value"];
  463.             $this->_root &$value["name"];
  464.             return true;
  465.         else {
  466.             // parent has to be an array
  467.             if (!isset($parent["children"]|| !is_array($parent["children"])) {
  468.                 $parent["children"= array();
  469.                 if (!in_array($parent["type"]array("array""object"))) {
  470.                     $parent["type"$this->options["complexType"];
  471.                     if ($this->options["complexType"== "object"{
  472.                         $parent["class"$parent["name"];
  473.                     }
  474.                 }
  475.             }
  476.  
  477.             if (!empty($value["name"])) {
  478.                 // there already has been a tag with this name
  479.                 if (in_array($value["name"]$parent["childrenKeys"])) {
  480.                     // no aggregate has been created for this tag
  481.                     if (!in_array($value["name"]$parent["aggregKeys"])) {
  482.                         $parent["children"][$value["name"]] = array($parent["children"][$value["name"]]);
  483.                         array_push($parent["aggregKeys"]$value["name"]);
  484.                     }
  485.                     array_push($parent["children"][$value["name"]]$value["value"]);
  486.                 else {
  487.                     $parent["children"][$value["name"]] &$value["value"];
  488.                     array_push($parent["childrenKeys"]$value["name"]);
  489.                 }
  490.             else {
  491.                 array_push($parent["children"],$value["value"]);
  492.             }
  493.             array_push($this->_valStack$parent);
  494.         }
  495.  
  496.         $this->_depth--;
  497.     }
  498.  
  499.     /**
  500.      * Handler for character data
  501.      *
  502.      * @access private
  503.      * @param  object XML parser object
  504.      * @param  string CDATA
  505.      * @return void 
  506.      */
  507.     function cdataHandler($parser$cdata)
  508.     {
  509.         $this->_dataStack[$this->_depth.= $cdata;
  510.     }
  511. }
  512. ?>

Documentation generated on Mon, 11 Mar 2019 13:52:54 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.