Source for file Unserializer.php

Documentation is available at Unserializer.php

  1. <?PHP
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3.  
  4. /**
  5. * XML_Unserializer
  6. *
  7. * Parses any XML document into PHP data structures.
  8. *
  9. * PHP versions 4 and 5
  10. *
  11. * LICENSE: This source file is subject to version 3.0 of the PHP license
  12. * that is available through the world-wide-web at the following URI:
  13. * http://www.php.net/license/3_0.txt. If you did not receive a copy of
  14. * the PHP License and are unable to obtain it through the web, please
  15. * send a note to license@php.net so we can mail you a copy immediately.
  16. *
  17. * @category XML
  18. * @package XML_Serializer
  19. * @author Stephan Schmidt <schst@php.net>
  20. * @copyright 1997-2005 The PHP Group
  21. * @license http://www.php.net/license/3_0.txt PHP License 3.0
  22. * @version CVS: $Id: Unserializer.php,v 1.1 2006/07/12 17:57:59 ron Exp $
  23. * @link http://pear.php.net/package/XML_Serializer
  24. * @see XML_Unserializer
  25. */
  26.  
  27. /**
  28. * uses PEAR error managemt
  29. */
  30. require_once 'PEAR.php';
  31.  
  32. /**
  33. * uses XML_Parser to unserialize document
  34. */
  35. require_once 'XML/Parser.php';
  36.  
  37. /**
  38. * option: Convert nested tags to array or object
  39. *
  40. * Possible values:
  41. * - array
  42. * - object
  43. * - associative array to define this option per tag name
  44. */
  45. define('XML_UNSERIALIZER_OPTION_COMPLEXTYPE', 'complexType');
  46.  
  47. /**
  48. * option: Name of the attribute that stores the original key
  49. *
  50. * Possible values:
  51. * - any string
  52. */
  53. define('XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY', 'keyAttribute');
  54.  
  55. /**
  56. * option: Name of the attribute that stores the type
  57. *
  58. * Possible values:
  59. * - any string
  60. */
  61. define('XML_UNSERIALIZER_OPTION_ATTRIBUTE_TYPE', 'typeAttribute');
  62.  
  63. /**
  64. * option: Name of the attribute that stores the class name
  65. *
  66. * Possible values:
  67. * - any string
  68. */
  69. define('XML_UNSERIALIZER_OPTION_ATTRIBUTE_CLASS', 'classAttribute');
  70.  
  71. /**
  72. * option: Whether to use the tag name as a class name
  73. *
  74. * Possible values:
  75. * - true or false
  76. */
  77. define('XML_UNSERIALIZER_OPTION_TAG_AS_CLASSNAME', 'tagAsClass');
  78.  
  79. /**
  80. * option: Name of the default class
  81. *
  82. * Possible values:
  83. * - any string
  84. */
  85. define('XML_UNSERIALIZER_OPTION_DEFAULT_CLASS', 'defaultClass');
  86.  
  87. /**
  88. * option: Whether to parse attributes
  89. *
  90. * Possible values:
  91. * - true or false
  92. */
  93. define('XML_UNSERIALIZER_OPTION_ATTRIBUTES_PARSE', 'parseAttributes');
  94.  
  95. /**
  96. * option: Key of the array to store attributes (if any)
  97. *
  98. * Possible values:
  99. * - any string
  100. * - false (disabled)
  101. */
  102. define('XML_UNSERIALIZER_OPTION_ATTRIBUTES_ARRAYKEY', 'attributesArray');
  103.  
  104. /**
  105. * option: string to prepend attribute name (if any)
  106. *
  107. * Possible values:
  108. * - any string
  109. * - false (disabled)
  110. */
  111. define('XML_UNSERIALIZER_OPTION_ATTRIBUTES_PREPEND', 'prependAttributes');
  112.  
  113. /**
  114. * option: key to store the content, if XML_UNSERIALIZER_OPTION_ATTRIBUTES_PARSE is used
  115. *
  116. * Possible values:
  117. * - any string
  118. */
  119. define('XML_UNSERIALIZER_OPTION_CONTENT_KEY', 'contentName');
  120.  
  121. /**
  122. * option: map tag names
  123. *
  124. * Possible values:
  125. * - associative array
  126. */
  127. define('XML_UNSERIALIZER_OPTION_TAG_MAP', 'tagMap');
  128.  
  129. /**
  130. * option: list of tags that will always be enumerated
  131. *
  132. * Possible values:
  133. * - indexed array
  134. */
  135. define('XML_UNSERIALIZER_OPTION_FORCE_ENUM', 'forceEnum');
  136.  
  137. /**
  138. * option: Encoding of the XML document
  139. *
  140. * Possible values:
  141. * - UTF-8
  142. * - ISO-8859-1
  143. */
  144. define('XML_UNSERIALIZER_OPTION_ENCODING_SOURCE', 'encoding');
  145.  
  146. /**
  147. * option: Desired target encoding of the data
  148. *
  149. * Possible values:
  150. * - UTF-8
  151. * - ISO-8859-1
  152. */
  153. define('XML_UNSERIALIZER_OPTION_ENCODING_TARGET', 'targetEncoding');
  154.  
  155. /**
  156. * option: Callback that will be applied to textual data
  157. *
  158. * Possible values:
  159. * - any valid PHP callback
  160. */
  161. define('XML_UNSERIALIZER_OPTION_DECODE_FUNC', 'decodeFunction');
  162.  
  163. /**
  164. * option: whether to return the result of the unserialization from unserialize()
  165. *
  166. * Possible values:
  167. * - true
  168. * - false (default)
  169. */
  170. define('XML_UNSERIALIZER_OPTION_RETURN_RESULT', 'returnResult');
  171.  
  172. /**
  173. * option: set the whitespace behaviour
  174. *
  175. * Possible values:
  176. * - XML_UNSERIALIZER_WHITESPACE_KEEP
  177. * - XML_UNSERIALIZER_WHITESPACE_TRIM
  178. * - XML_UNSERIALIZER_WHITESPACE_NORMALIZE
  179. */
  180. define('XML_UNSERIALIZER_OPTION_WHITESPACE', 'whitespace');
  181.  
  182. /**
  183. * Keep all whitespace
  184. */
  185. define('XML_UNSERIALIZER_WHITESPACE_KEEP', 'keep');
  186.  
  187. /**
  188. * remove whitespace from start and end of the data
  189. */
  190. define('XML_UNSERIALIZER_WHITESPACE_TRIM', 'trim');
  191.  
  192. /**
  193. * normalize whitespace
  194. */
  195. define('XML_UNSERIALIZER_WHITESPACE_NORMALIZE', 'normalize');
  196.  
  197. /**
  198. * option: whether to ovverride all options that have been set before
  199. *
  200. * Possible values:
  201. * - true
  202. * - false (default)
  203. */
  204. define('XML_UNSERIALIZER_OPTION_OVERRIDE_OPTIONS', 'overrideOptions');
  205.  
  206. /**
  207. * option: list of tags, that will not be used as keys
  208. */
  209. define('XML_UNSERIALIZER_OPTION_IGNORE_KEYS', 'ignoreKeys');
  210.  
  211. /**
  212. * option: whether to use type guessing for scalar values
  213. */
  214. define('XML_UNSERIALIZER_OPTION_GUESS_TYPES', 'guessTypes');
  215.  
  216. /**
  217. * error code for no serialization done
  218. */
  219. define('XML_UNSERIALIZER_ERROR_NO_UNSERIALIZATION', 151);
  220.  
  221. /**
  222. * XML_Unserializer
  223. *
  224. * class to unserialize XML documents that have been created with
  225. * XML_Serializer. To unserialize an XML document you have to add
  226. * type hints to the XML_Serializer options.
  227. *
  228. * If no type hints are available, XML_Unserializer will guess how
  229. * the tags should be treated, that means complex structures will be
  230. * arrays and tags with only CData in them will be strings.
  231. *
  232. * <code>
  233. * require_once 'XML/Unserializer.php';
  234. *
  235. * // be careful to always use the ampersand in front of the new operator
  236. * $unserializer = &new XML_Unserializer();
  237. *
  238. * $unserializer->unserialize($xml);
  239. *
  240. * $data = $unserializer->getUnserializedData();
  241. * <code>
  242. *
  243. *
  244. * @category XML
  245. * @package XML_Serializer
  246. * @author Stephan Schmidt <schst@php.net>
  247. * @copyright 1997-2005 The PHP Group
  248. * @license http://www.php.net/license/3_0.txt PHP License 3.0
  249. * @version Release: @package_version@
  250. * @link http://pear.php.net/package/XML_Serializer
  251. * @see XML_Serializer
  252. */
  253. class XML_Unserializer extends PEAR
  254. {
  255. /**
  256. * list of all available options
  257. *
  258. * @access private
  259. * @var array
  260. */
  261. var $_knownOptions = array(
  262. XML_UNSERIALIZER_OPTION_COMPLEXTYPE,
  263. XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY,
  264. XML_UNSERIALIZER_OPTION_ATTRIBUTE_TYPE,
  265. XML_UNSERIALIZER_OPTION_ATTRIBUTE_CLASS,
  266. XML_UNSERIALIZER_OPTION_TAG_AS_CLASSNAME,
  267. XML_UNSERIALIZER_OPTION_DEFAULT_CLASS,
  268. XML_UNSERIALIZER_OPTION_ATTRIBUTES_PARSE,
  269. XML_UNSERIALIZER_OPTION_ATTRIBUTES_ARRAYKEY,
  270. XML_UNSERIALIZER_OPTION_ATTRIBUTES_PREPEND,
  271. XML_UNSERIALIZER_OPTION_CONTENT_KEY,
  272. XML_UNSERIALIZER_OPTION_TAG_MAP,
  273. XML_UNSERIALIZER_OPTION_FORCE_ENUM,
  274. XML_UNSERIALIZER_OPTION_ENCODING_SOURCE,
  275. XML_UNSERIALIZER_OPTION_ENCODING_TARGET,
  276. XML_UNSERIALIZER_OPTION_DECODE_FUNC,
  277. XML_UNSERIALIZER_OPTION_RETURN_RESULT,
  278. XML_UNSERIALIZER_OPTION_WHITESPACE,
  279. XML_UNSERIALIZER_OPTION_IGNORE_KEYS,
  280. XML_UNSERIALIZER_OPTION_GUESS_TYPES
  281. );
  282. /**
  283. * default options for the serialization
  284. *
  285. * @access private
  286. * @var array
  287. */
  288. var $_defaultOptions = array(
  289. XML_UNSERIALIZER_OPTION_COMPLEXTYPE => 'array', // complex types will be converted to arrays, if no type hint is given
  290. XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY => '_originalKey', // get array key/property name from this attribute
  291. XML_UNSERIALIZER_OPTION_ATTRIBUTE_TYPE => '_type', // get type from this attribute
  292. XML_UNSERIALIZER_OPTION_ATTRIBUTE_CLASS => '_class', // get class from this attribute (if not given, use tag name)
  293. XML_UNSERIALIZER_OPTION_TAG_AS_CLASSNAME => true, // use the tagname as the classname
  294. XML_UNSERIALIZER_OPTION_DEFAULT_CLASS => 'stdClass', // name of the class that is used to create objects
  295. XML_UNSERIALIZER_OPTION_ATTRIBUTES_PARSE => false, // parse the attributes of the tag into an array
  296. XML_UNSERIALIZER_OPTION_ATTRIBUTES_ARRAYKEY => false, // parse them into sperate array (specify name of array here)
  297. XML_UNSERIALIZER_OPTION_ATTRIBUTES_PREPEND => '', // prepend attribute names with this string
  298. XML_UNSERIALIZER_OPTION_CONTENT_KEY => '_content', // put cdata found in a tag that has been converted to a complex type in this key
  299. XML_UNSERIALIZER_OPTION_TAG_MAP => array(), // use this to map tagnames
  300. XML_UNSERIALIZER_OPTION_FORCE_ENUM => array(), // these tags will always be an indexed array
  301. XML_UNSERIALIZER_OPTION_ENCODING_SOURCE => null, // specify the encoding character of the document to parse
  302. XML_UNSERIALIZER_OPTION_ENCODING_TARGET => null, // specify the target encoding
  303. XML_UNSERIALIZER_OPTION_DECODE_FUNC => null, // function used to decode data
  304. XML_UNSERIALIZER_OPTION_RETURN_RESULT => false, // unserialize() returns the result of the unserialization instead of true
  305. XML_UNSERIALIZER_OPTION_WHITESPACE => XML_UNSERIALIZER_WHITESPACE_TRIM, // remove whitespace around data
  306. XML_UNSERIALIZER_OPTION_IGNORE_KEYS => array(), // List of tags that will automatically be added to the parent, instead of adding a new key
  307. XML_UNSERIALIZER_OPTION_GUESS_TYPES => false // Whether to use type guessing
  308. );
  309.  
  310. /**
  311. * current options for the serialization
  312. *
  313. * @access public
  314. * @var array
  315. */
  316. var $options = array();
  317.  
  318. /**
  319. * unserialized data
  320. *
  321. * @access private
  322. * @var string
  323. */
  324. var $_unserializedData = null;
  325.  
  326. /**
  327. * name of the root tag
  328. *
  329. * @access private
  330. * @var string
  331. */
  332. var $_root = null;
  333.  
  334. /**
  335. * stack for all data that is found
  336. *
  337. * @access private
  338. * @var array
  339. */
  340. var $_dataStack = array();
  341.  
  342. /**
  343. * stack for all values that are generated
  344. *
  345. * @access private
  346. * @var array
  347. */
  348. var $_valStack = array();
  349.  
  350. /**
  351. * current tag depth
  352. *
  353. * @access private
  354. * @var int
  355. */
  356. var $_depth = 0;
  357.  
  358. /**
  359. * XML_Parser instance
  360. *
  361. * @access private
  362. * @var object XML_Parser
  363. */
  364. var $_parser = null;
  365. /**
  366. * constructor
  367. *
  368. * @access public
  369. * @param mixed $options array containing options for the unserialization
  370. */
  371. function XML_Unserializer($options = null)
  372. {
  373. if (is_array($options)) {
  374. $this->options = array_merge($this->_defaultOptions, $options);
  375. } else {
  376. $this->options = $this->_defaultOptions;
  377. }
  378. }
  379.  
  380. /**
  381. * return API version
  382. *
  383. * @access public
  384. * @static
  385. * @return string $version API version
  386. */
  387. function apiVersion()
  388. {
  389. return '@package_version@';
  390. }
  391.  
  392. /**
  393. * reset all options to default options
  394. *
  395. * @access public
  396. * @see setOption(), XML_Unserializer(), setOptions()
  397. */
  398. function resetOptions()
  399. {
  400. $this->options = $this->_defaultOptions;
  401. }
  402.  
  403. /**
  404. * set an option
  405. *
  406. * You can use this method if you do not want to set all options in the constructor
  407. *
  408. * @access public
  409. * @see resetOption(), XML_Unserializer(), setOptions()
  410. */
  411. function setOption($name, $value)
  412. {
  413. $this->options[$name] = $value;
  414. }
  415.  
  416. /**
  417. * sets several options at once
  418. *
  419. * You can use this method if you do not want to set all options in the constructor
  420. *
  421. * @access public
  422. * @see resetOption(), XML_Unserializer(), setOption()
  423. */
  424. function setOptions($options)
  425. {
  426. $this->options = array_merge($this->options, $options);
  427. }
  428.  
  429. /**
  430. * unserialize data
  431. *
  432. * @access public
  433. * @param mixed $data data to unserialize (string, filename or resource)
  434. * @param boolean $isFile data should be treated as a file
  435. * @param array $options options that will override the global options for this call
  436. * @return boolean $success
  437. */
  438. function unserialize($data, $isFile = false, $options = null)
  439. {
  440. $this->_unserializedData = null;
  441. $this->_root = null;
  442.  
  443. // if options have been specified, use them instead
  444. // of the previously defined ones
  445. if (is_array($options)) {
  446. $optionsBak = $this->options;
  447. if (isset($options[XML_UNSERIALIZER_OPTION_OVERRIDE_OPTIONS]) && $options[XML_UNSERIALIZER_OPTION_OVERRIDE_OPTIONS] == true) {
  448. $this->options = array_merge($this->_defaultOptions, $options);
  449. } else {
  450. $this->options = array_merge($this->options, $options);
  451. }
  452. } else {
  453. $optionsBak = null;
  454. }
  455.  
  456. $this->_valStack = array();
  457. $this->_dataStack = array();
  458. $this->_depth = 0;
  459.  
  460. $this->_createParser();
  461. if (is_string($data)) {
  462. if ($isFile) {
  463. $result = $this->_parser->setInputFile($data);
  464. if (PEAR::isError($result)) {
  465. return $result;
  466. }
  467. $result = $this->_parser->parse();
  468. } else {
  469. $result = $this->_parser->parseString($data,true);
  470. }
  471. } else {
  472. $this->_parser->setInput($data);
  473. $result = $this->_parser->parse();
  474. }
  475.  
  476. if ($this->options[XML_UNSERIALIZER_OPTION_RETURN_RESULT] === true) {
  477. $return = $this->_unserializedData;
  478. } else {
  479. $return = true;
  480. }
  481.  
  482. if ($optionsBak !== null) {
  483. $this->options = $optionsBak;
  484. }
  485.  
  486. if (PEAR::isError($result)) {
  487. return $result;
  488. }
  489.  
  490. return $return;
  491. }
  492.  
  493. /**
  494. * get the result of the serialization
  495. *
  496. * @access public
  497. * @return string $serializedData
  498. */
  499. function getUnserializedData()
  500. {
  501. if ($this->_root === null) {
  502. return $this->raiseError('No unserialized data available. Use XML_Unserializer::unserialize() first.', XML_UNSERIALIZER_ERROR_NO_UNSERIALIZATION);
  503. }
  504. return $this->_unserializedData;
  505. }
  506.  
  507. /**
  508. * get the name of the root tag
  509. *
  510. * @access public
  511. * @return string $rootName
  512. */
  513. function getRootName()
  514. {
  515. if ($this->_root === null) {
  516. return $this->raiseError('No unserialized data available. Use XML_Unserializer::unserialize() first.', XML_UNSERIALIZER_ERROR_NO_UNSERIALIZATION);
  517. }
  518. return $this->_root;
  519. }
  520.  
  521. /**
  522. * Start element handler for XML parser
  523. *
  524. * @access private
  525. * @param object $parser XML parser object
  526. * @param string $element XML element
  527. * @param array $attribs attributes of XML tag
  528. * @return void
  529. */
  530. function startHandler($parser, $element, $attribs)
  531. {
  532. if (isset($attribs[$this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_TYPE]])) {
  533. $type = $attribs[$this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_TYPE]];
  534. $guessType = false;
  535. } else {
  536. $type = 'string';
  537. if ($this->options[XML_UNSERIALIZER_OPTION_GUESS_TYPES] === true) {
  538. $guessType = true;
  539. } else {
  540. $guessType = false;
  541. }
  542. }
  543.  
  544. if ($this->options[XML_UNSERIALIZER_OPTION_DECODE_FUNC] !== null) {
  545. $attribs = array_map($this->options[XML_UNSERIALIZER_OPTION_DECODE_FUNC], $attribs);
  546. }
  547. $this->_depth++;
  548. $this->_dataStack[$this->_depth] = null;
  549.  
  550. if (is_array($this->options[XML_UNSERIALIZER_OPTION_TAG_MAP]) && isset($this->options[XML_UNSERIALIZER_OPTION_TAG_MAP][$element])) {
  551. $element = $this->options[XML_UNSERIALIZER_OPTION_TAG_MAP][$element];
  552. }
  553.  
  554. $val = array(
  555. 'name' => $element,
  556. 'value' => null,
  557. 'type' => $type,
  558. 'guessType' => $guessType,
  559. 'childrenKeys' => array(),
  560. 'aggregKeys' => array()
  561. );
  562.  
  563. if ($this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTES_PARSE] == true && (count($attribs) > 0)) {
  564. $val['children'] = array();
  565. $val['type'] = $this->_getComplexType($element);
  566. $val['class'] = $element;
  567.  
  568. if ($this->options[XML_UNSERIALIZER_OPTION_GUESS_TYPES] === true) {
  569. $attribs = $this->_guessAndSetTypes($attribs);
  570. }
  571. if ($this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTES_ARRAYKEY] != false) {
  572. $val['children'][$this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTES_ARRAYKEY]] = $attribs;
  573. } else {
  574. foreach ($attribs as $attrib => $value) {
  575. $val['children'][$this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTES_PREPEND].$attrib] = $value;
  576. }
  577. }
  578. }
  579.  
  580. $keyAttr = false;
  581. if (is_string($this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY])) {
  582. $keyAttr = $this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY];
  583. } elseif (is_array($this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY])) {
  584. if (isset($this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY][$element])) {
  585. $keyAttr = $this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY][$element];
  586. } elseif (isset($this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY]['#default'])) {
  587. $keyAttr = $this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY]['#default'];
  588. } elseif (isset($this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY]['__default'])) {
  589. // keep this for BC
  590. $keyAttr = $this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_KEY]['__default'];
  591. }
  592. }
  593. if ($keyAttr !== false && isset($attribs[$keyAttr])) {
  594. $val['name'] = $attribs[$keyAttr];
  595. }
  596.  
  597. if (isset($attribs[$this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_CLASS]])) {
  598. $val['class'] = $attribs[$this->options[XML_UNSERIALIZER_OPTION_ATTRIBUTE_CLASS]];
  599. }
  600.  
  601. array_push($this->_valStack, $val);
  602. }
  603.  
  604. /**
  605. * Try to guess the type of several values and
  606. * set them accordingly
  607. *
  608. * @access private
  609. * @param array array, containing the values
  610. * @return array array, containing the values with their correct types
  611. */
  612. function _guessAndSetTypes($array)
  613. {
  614. foreach ($array as $key => $value) {
  615. $array[$key] = $this->_guessAndSetType($value);
  616. }
  617. return $array;
  618. }
  619. /**
  620. * Try to guess the type of a value and
  621. * set it accordingly
  622. *
  623. * @access private
  624. * @param string character data
  625. * @return mixed value with the best matching type
  626. */
  627. function _guessAndSetType($value)
  628. {
  629. if ($value === 'true') {
  630. return true;
  631. }
  632. if ($value === 'false') {
  633. return false;
  634. }
  635. if ($value === 'NULL') {
  636. return null;
  637. }
  638. if (preg_match('/^[-+]?[0-9]{1,}$/', $value)) {
  639. return intval($value);
  640. }
  641. if (preg_match('/^[-+]?[0-9]{1,}\.[0-9]{1,}$/', $value)) {
  642. return doubleval($value);
  643. }
  644. return (string)$value;
  645. }
  646. /**
  647. * End element handler for XML parser
  648. *
  649. * @access private
  650. * @param object XML parser object
  651. * @param string
  652. * @return void
  653. */
  654. function endHandler($parser, $element)
  655. {
  656. $value = array_pop($this->_valStack);
  657. switch ($this->options[XML_UNSERIALIZER_OPTION_WHITESPACE]) {
  658. case XML_UNSERIALIZER_WHITESPACE_KEEP:
  659. $data = $this->_dataStack[$this->_depth];
  660. break;
  661. case XML_UNSERIALIZER_WHITESPACE_NORMALIZE:
  662. $data = trim(preg_replace('/\s\s+/m', ' ', $this->_dataStack[$this->_depth]));
  663. break;
  664. case XML_UNSERIALIZER_WHITESPACE_TRIM:
  665. default:
  666. $data = trim($this->_dataStack[$this->_depth]);
  667. break;
  668. }
  669.  
  670. // adjust type of the value
  671. switch(strtolower($value['type'])) {
  672.  
  673. // unserialize an object
  674. case 'object':
  675. if (isset($value['class'])) {
  676. $classname = $value['class'];
  677. } else {
  678. $classname = '';
  679. }
  680. // instantiate the class
  681. if ($this->options[XML_UNSERIALIZER_OPTION_TAG_AS_CLASSNAME] === true && class_exists($classname)) {
  682. $value['value'] = &new $classname;
  683. } else {
  684. $value['value'] = &new $this->options[XML_UNSERIALIZER_OPTION_DEFAULT_CLASS];
  685. }
  686. if (trim($data) !== '') {
  687. if ($value['guessType'] === true) {
  688. $data = $this->_guessAndSetType($data);
  689. }
  690. $value['children'][$this->options[XML_UNSERIALIZER_OPTION_CONTENT_KEY]] = $data;
  691. }
  692.  
  693. // set properties
  694. foreach ($value['children'] as $prop => $propVal) {
  695. // check whether there is a special method to set this property
  696. $setMethod = 'set'.$prop;
  697. if (method_exists($value['value'], $setMethod)) {
  698. call_user_func(array(&$value['value'], $setMethod), $propVal);
  699. } else {
  700. $value['value']->$prop = $propVal;
  701. }
  702. }
  703. // check for magic function
  704. if (method_exists($value['value'], '__wakeup')) {
  705. $value['value']->__wakeup();
  706. }
  707. break;
  708.  
  709. // unserialize an array
  710. case 'array':
  711. if (trim($data) !== '') {
  712. if ($value['guessType'] === true) {
  713. $data = $this->_guessAndSetType($data);
  714. }
  715. $value['children'][$this->options[XML_UNSERIALIZER_OPTION_CONTENT_KEY]] = $data;
  716. }
  717. if (isset($value['children'])) {
  718. $value['value'] = $value['children'];
  719. } else {
  720. $value['value'] = array();
  721. }
  722. break;
  723.  
  724. // unserialize a null value
  725. case 'null':
  726. $data = null;
  727. break;
  728.  
  729. // unserialize a resource => this is not possible :-(
  730. case 'resource':
  731. $value['value'] = $data;
  732. break;
  733.  
  734. // unserialize any scalar value
  735. default:
  736. if ($value['guessType'] === true) {
  737. $data = $this->_guessAndSetType($data);
  738. } else {
  739. settype($data, $value['type']);
  740. }
  741. $value['value'] = $data;
  742. break;
  743. }
  744. $parent = array_pop($this->_valStack);
  745. if ($parent === null) {
  746. $this->_unserializedData = &$value['value'];
  747. $this->_root = &$value['name'];
  748. return true;
  749. } else {
  750. // parent has to be an array
  751. if (!isset($parent['children']) || !is_array($parent['children'])) {
  752. $parent['children'] = array();
  753. if (!in_array($parent['type'], array('array', 'object'))) {
  754. $parent['type'] = $this->_getComplexType($parent['name']);
  755. if ($parent['type'] == 'object') {
  756. $parent['class'] = $parent['name'];
  757. }
  758. }
  759. }
  760.  
  761. if (in_array($element, $this->options[XML_UNSERIALIZER_OPTION_IGNORE_KEYS])) {
  762. $ignoreKey = true;
  763. } else {
  764. $ignoreKey = false;
  765. }
  766. if (!empty($value['name']) && $ignoreKey === false) {
  767. // there already has been a tag with this name
  768. if (in_array($value['name'], $parent['childrenKeys']) || in_array($value['name'], $this->options[XML_UNSERIALIZER_OPTION_FORCE_ENUM])) {
  769. // no aggregate has been created for this tag
  770. if (!in_array($value['name'], $parent['aggregKeys'])) {
  771. if (isset($parent['children'][$value['name']])) {
  772. $parent['children'][$value['name']] = array($parent['children'][$value['name']]);
  773. } else {
  774. $parent['children'][$value['name']] = array();
  775. }
  776. array_push($parent['aggregKeys'], $value['name']);
  777. }
  778. array_push($parent['children'][$value['name']], $value['value']);
  779. } else {
  780. $parent['children'][$value['name']] = &$value['value'];
  781. array_push($parent['childrenKeys'], $value['name']);
  782. }
  783. } else {
  784. array_push($parent['children'], $value['value']);
  785. }
  786. array_push($this->_valStack, $parent);
  787. }
  788.  
  789. $this->_depth--;
  790. }
  791.  
  792. /**
  793. * Handler for character data
  794. *
  795. * @access private
  796. * @param object XML parser object
  797. * @param string CDATA
  798. * @return void
  799. */
  800. function cdataHandler($parser, $cdata)
  801. {
  802. if ($this->options[XML_UNSERIALIZER_OPTION_DECODE_FUNC] !== null) {
  803. $cdata = call_user_func($this->options[XML_UNSERIALIZER_OPTION_DECODE_FUNC], $cdata);
  804. }
  805. $this->_dataStack[$this->_depth] .= $cdata;
  806. }
  807.  
  808. /**
  809. * get the complex type, that should be used for a specified tag
  810. *
  811. * @access private
  812. * @param string name of the tag
  813. * @return string complex type ('array' or 'object')
  814. */
  815. function _getComplexType($tagname)
  816. {
  817. if (is_string($this->options[XML_UNSERIALIZER_OPTION_COMPLEXTYPE])) {
  818. return $this->options[XML_UNSERIALIZER_OPTION_COMPLEXTYPE];
  819. }
  820. if (isset($this->options[XML_UNSERIALIZER_OPTION_COMPLEXTYPE][$tagname])) {
  821. return $this->options[XML_UNSERIALIZER_OPTION_COMPLEXTYPE][$tagname];
  822. }
  823. if (isset($this->options[XML_UNSERIALIZER_OPTION_COMPLEXTYPE]['#default'])) {
  824. return $this->options[XML_UNSERIALIZER_OPTION_COMPLEXTYPE]['#default'];
  825. }
  826. return 'array';
  827. }
  828. /**
  829. * create the XML_Parser instance
  830. *
  831. * @access private
  832. * @return boolean
  833. */
  834. function _createParser()
  835. {
  836. if (is_object($this->_parser)) {
  837. $this->_parser->free();
  838. unset($this->_parser);
  839. }
  840. $this->_parser = &new XML_Parser($this->options[XML_UNSERIALIZER_OPTION_ENCODING_SOURCE], 'event', $this->options[XML_UNSERIALIZER_OPTION_ENCODING_TARGET]);
  841. $this->_parser->folding = false;
  842. $this->_parser->setHandlerObj($this);
  843. return true;
  844. }
  845. }
  846. ?>

Documentation generated on Mon, 04 Dec 2006 11:10:16 -0500 by phpDocumentor 1.3.0RC3