| [ Index ] |
|
Code source de phpMyVisites 2.3 |
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 2005/12/06 01:50:39 matthieu_ 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 * error code for no serialization done 39 */ 40 define('XML_UNSERIALIZER_ERROR_NO_UNSERIALIZATION', 151); 41 42 /** 43 * XML_Unserializer 44 * 45 * class to unserialize XML documents that have been created with 46 * XML_Serializer. To unserialize an XML document you have to add 47 * type hints to the XML_Serializer options. 48 * 49 * If no type hints are available, XML_Unserializer will guess how 50 * the tags should be treated, that means complex structures will be 51 * arrays and tags with only CData in them will be strings. 52 * 53 * <code> 54 * require_once 'XML/Unserializer.php'; 55 * 56 * // be careful to always use the ampersand in front of the new operator 57 * $unserializer = &new XML_Unserializer(); 58 * 59 * $unserializer->unserialize($xml); 60 * 61 * $data = $unserializer->getUnserializedData(); 62 * <code> 63 * 64 * Possible options for the Unserializer are: 65 * 66 * 1. complexTypes => array|object 67 * This is needed, when unserializing XML files w/o type hints. If set to 68 * 'array' (default), all nested tags will be arrays, if set to 'object' 69 * all nested tags will be objects, that means you have read access like: 70 * 71 * <code> 72 * require_once 'XML/Unserializer.php'; 73 * $options = array('complexType' => 'object'); 74 * $unserializer = &new XML_Unserializer($options); 75 * 76 * $unserializer->unserialize('http://pear.php.net/rss.php'); 77 * 78 * $rss = $unserializer->getUnserializedData(); 79 * echo $rss->channel->item[3]->title; 80 * </code> 81 * 82 * 2. keyAttribute 83 * This lets you specify an attribute inside your tags, that are used as key 84 * for associative arrays or object properties. 85 * You will need this if you have XML that looks like this: 86 * 87 * <users> 88 * <user handle="schst">Stephan Schmidt</user> 89 * <user handle="ssb">Stig S. Bakken</user> 90 * </users> 91 * 92 * Then you can use: 93 * <code> 94 * require_once 'XML/Unserializer.php'; 95 * $options = array('keyAttribute' => 'handle'); 96 * $unserializer = &new XML_Unserializer($options); 97 * 98 * $unserializer->unserialize($xml, false); 99 * 100 * $users = $unserializer->getUnserializedData(); 101 * </code> 102 * 103 * @category XML 104 * @package XML_Serializer 105 * @author Stephan Schmidt <schst@php.net> 106 * @copyright 1997-2005 The PHP Group 107 * @license http://www.php.net/license/3_0.txt PHP License 3.0 108 * @version Release: 0.16.0 109 * @link http://pear.php.net/package/XML_Serializer 110 * @see XML_Serializer 111 */ 112 class XML_Unserializer extends PEAR 113 { 114 115 /** 116 * default options for the serialization 117 * 118 * @access private 119 * @var array 120 */ 121 var $_defaultOptions = array( 122 'complexType' => 'array', // complex types will be converted to arrays, if no type hint is given 123 'keyAttribute' => '_originalKey', // get array key/property name from this attribute 124 'typeAttribute' => '_type', // get type from this attribute 125 'classAttribute' => '_class', // get class from this attribute (if not given, use tag name) 126 'tagAsClass' => true, // use the tagname as the classname 127 'defaultClass' => 'stdClass', // name of the class that is used to create objects 128 'parseAttributes' => false, // parse the attributes of the tag into an array 129 'attributesArray' => false, // parse them into sperate array (specify name of array here) 130 'prependAttributes' => '', // prepend attribute names with this string 131 'contentName' => '_content', // put cdata found in a tag that has been converted to a complex type in this key 132 'tagMap' => array(), // use this to map tagnames 133 'forceEnum' => array(), // these tags will always be an indexed array 134 'encoding' => null, // specify the encoding character of the document to parse 135 'targetEncoding' => null, // specify the target encoding 136 'decodeFunction' => null, // function used to decode data 137 'returnResult' => false // unserialize() returns the result of the unserialization instead of true 138 ); 139 140 /** 141 * actual options for the serialization 142 * 143 * @access public 144 * @var array 145 */ 146 var $options = array(); 147 148 /** 149 * unserialized data 150 * 151 * @access private 152 * @var string 153 */ 154 var $_unserializedData = null; 155 156 /** 157 * name of the root tag 158 * 159 * @access private 160 * @var string 161 */ 162 var $_root = null; 163 164 /** 165 * stack for all data that is found 166 * 167 * @access private 168 * @var array 169 */ 170 var $_dataStack = array(); 171 172 /** 173 * stack for all values that are generated 174 * 175 * @access private 176 * @var array 177 */ 178 var $_valStack = array(); 179 180 /** 181 * current tag depth 182 * 183 * @access private 184 * @var int 185 */ 186 var $_depth = 0; 187 188 /** 189 * XML_Parser instance 190 * 191 * @access private 192 * @var object XML_Parser 193 */ 194 var $_parser = null; 195 196 /** 197 * constructor 198 * 199 * @access public 200 * @param mixed $options array containing options for the unserialization 201 */ 202 function XML_Unserializer($options = null) 203 { 204 if (is_array($options)) { 205 $this->options = array_merge($this->_defaultOptions, $options); 206 } else { 207 $this->options = $this->_defaultOptions; 208 } 209 } 210 211 /** 212 * return API version 213 * 214 * @access public 215 * @static 216 * @return string $version API version 217 */ 218 function apiVersion() 219 { 220 return '0.16.0'; 221 } 222 223 /** 224 * reset all options to default options 225 * 226 * @access public 227 * @see setOption(), XML_Unserializer(), setOptions() 228 */ 229 function resetOptions() 230 { 231 $this->options = $this->_defaultOptions; 232 } 233 234 /** 235 * set an option 236 * 237 * You can use this method if you do not want to set all options in the constructor 238 * 239 * @access public 240 * @see resetOption(), XML_Unserializer(), setOptions() 241 */ 242 function setOption($name, $value) 243 { 244 $this->options[$name] = $value; 245 } 246 247 /** 248 * sets several options at once 249 * 250 * You can use this method if you do not want to set all options in the constructor 251 * 252 * @access public 253 * @see resetOption(), XML_Unserializer(), setOption() 254 */ 255 function setOptions($options) 256 { 257 $this->options = array_merge($this->options, $options); 258 } 259 260 /** 261 * unserialize data 262 * 263 * @access public 264 * @param mixed $data data to unserialize (string, filename or resource) 265 * @param boolean $isFile data should be treated as a file 266 * @param array $options options that will override the global options for this call 267 * @return boolean $success 268 */ 269 function unserialize($data, $isFile = false, $options = null) 270 { 271 $this->_unserializedData = null; 272 $this->_root = null; 273 274 // if options have been specified, use them instead 275 // of the previously defined ones 276 if (is_array($options)) { 277 $optionsBak = $this->options; 278 if (isset($options['overrideOptions']) && $options['overrideOptions'] == true) { 279 $this->options = array_merge($this->_defaultOptions, $options); 280 } else { 281 $this->options = array_merge($this->options, $options); 282 } 283 } else { 284 $optionsBak = null; 285 } 286 287 $this->_valStack = array(); 288 $this->_dataStack = array(); 289 $this->_depth = 0; 290 291 $this->_createParser(); 292 293 if (is_string($data)) { 294 if ($isFile) { 295 $result = $this->_parser->setInputFile($data); 296 if (PEAR::isError($result)) { 297 return $result; 298 } 299 $result = $this->_parser->parse(); 300 } else { 301 $result = $this->_parser->parseString($data,true); 302 } 303 } else { 304 $this->_parser->setInput($data); 305 $result = $this->_parser->parse(); 306 } 307 308 if ($this->options['returnResult'] === true) { 309 $return = $this->_unserializedData; 310 } else { 311 $return = true; 312 } 313 314 if ($optionsBak !== null) { 315 $this->options = $optionsBak; 316 } 317 318 if (PEAR::isError($result)) { 319 return $result; 320 } 321 322 return $return; 323 } 324 325 /** 326 * get the result of the serialization 327 * 328 * @access public 329 * @return string $serializedData 330 */ 331 function getUnserializedData() 332 { 333 if ($this->_root === null) { 334 return $this->raiseError('No unserialized data available. Use XML_Unserializer::unserialize() first.', XML_UNSERIALIZER_ERROR_NO_UNSERIALIZATION); 335 } 336 return $this->_unserializedData; 337 } 338 339 /** 340 * get the name of the root tag 341 * 342 * @access public 343 * @return string $rootName 344 */ 345 function getRootName() 346 { 347 if ($this->_root === null) { 348 return $this->raiseError('No unserialized data available. Use XML_Unserializer::unserialize() first.', XML_UNSERIALIZER_ERROR_NO_UNSERIALIZATION); 349 } 350 return $this->_root; 351 } 352 353 /** 354 * Start element handler for XML parser 355 * 356 * @access private 357 * @param object $parser XML parser object 358 * @param string $element XML element 359 * @param array $attribs attributes of XML tag 360 * @return void 361 */ 362 function startHandler($parser, $element, $attribs) 363 { 364 if (isset($attribs[$this->options['typeAttribute']])) { 365 $type = $attribs[$this->options['typeAttribute']]; 366 } else { 367 $type = 'string'; 368 } 369 370 if ($this->options['decodeFunction'] !== null) { 371 $element = call_user_func($this->options['decodeFunction'], $element); 372 $attribs = array_map($this->options['decodeFunction'], $attribs); 373 } 374 375 $this->_depth++; 376 $this->_dataStack[$this->_depth] = null; 377 378 if (is_array($this->options['tagMap']) && isset($this->options['tagMap'][$element])) { 379 $element = $this->options['tagMap'][$element]; 380 } 381 382 $val = array( 383 'name' => $element, 384 'value' => null, 385 'type' => $type, 386 'childrenKeys' => array(), 387 'aggregKeys' => array() 388 ); 389 390 if ($this->options['parseAttributes'] == true && (count($attribs) > 0)) { 391 $val['children'] = array(); 392 $val['type'] = $this->options['complexType']; 393 $val['class'] = $element; 394 395 if ($this->options['attributesArray'] != false) { 396 $val['children'][$this->options['attributesArray']] = $attribs; 397 } else { 398 foreach ($attribs as $attrib => $value) { 399 $val['children'][$this->options['prependAttributes'].$attrib] = $value; 400 } 401 } 402 } 403 404 $keyAttr = false; 405 406 if (is_string($this->options['keyAttribute'])) { 407 $keyAttr = $this->options['keyAttribute']; 408 } elseif (is_array($this->options['keyAttribute'])) { 409 if (isset($this->options['keyAttribute'][$element])) { 410 $keyAttr = $this->options['keyAttribute'][$element]; 411 } elseif (isset($this->options['keyAttribute']['__default'])) { 412 $keyAttr = $this->options['keyAttribute']['__default']; 413 } 414 } 415 416 if ($keyAttr !== false && isset($attribs[$keyAttr])) { 417 $val['name'] = $attribs[$keyAttr]; 418 } 419 420 if (isset($attribs[$this->options['classAttribute']])) { 421 $val['class'] = $attribs[$this->options['classAttribute']]; 422 } 423 424 array_push($this->_valStack, $val); 425 } 426 427 /** 428 * End element handler for XML parser 429 * 430 * @access private 431 * @param object XML parser object 432 * @param string 433 * @return void 434 */ 435 function endHandler($parser, $element) 436 { 437 $value = array_pop($this->_valStack); 438 $data = trim($this->_dataStack[$this->_depth]); 439 440 // adjust type of the value 441 switch(strtolower($value['type'])) { 442 443 // unserialize an object 444 case 'object': 445 if (isset($value['class'])) { 446 $classname = $value['class']; 447 } else { 448 $classname = ''; 449 } 450 // instantiate the class 451 if ($this->options['tagAsClass'] === true && class_exists($classname)) { 452 $value['value'] = &new $classname; 453 } else { 454 $value['value'] = &new $this->options['defaultClass']; 455 } 456 if ($data !== '') { 457 $value['children'][$this->options['contentName']] = $data; 458 } 459 460 // set properties 461 foreach ($value['children'] as $prop => $propVal) { 462 // check whether there is a special method to set this property 463 $setMethod = 'set'.$prop; 464 if (method_exists($value['value'], $setMethod)) { 465 call_user_func(array(&$value['value'], $setMethod), $propVal); 466 } else { 467 $value['value']->$prop = $propVal; 468 } 469 } 470 // check for magic function 471 if (method_exists($value['value'], '__wakeup')) { 472 $value['value']->__wakeup(); 473 } 474 break; 475 476 // unserialize an array 477 case 'array': 478 if ($data !== '') { 479 $value['children'][$this->options['contentName']] = $data; 480 } 481 if (isset($value['children'])) { 482 $value['value'] = $value['children']; 483 } else { 484 $value['value'] = array(); 485 } 486 break; 487 488 // unserialize a null value 489 case 'null': 490 $data = null; 491 break; 492 493 // unserialize a resource => this is not possible :-( 494 case 'resource': 495 $value['value'] = $data; 496 break; 497 498 // unserialize any scalar value 499 default: 500 settype($data, $value['type']); 501 $value['value'] = $data; 502 break; 503 } 504 $parent = array_pop($this->_valStack); 505 if ($parent === null) { 506 $this->_unserializedData = &$value['value']; 507 $this->_root = &$value['name']; 508 return true; 509 } else { 510 // parent has to be an array 511 if (!isset($parent['children']) || !is_array($parent['children'])) { 512 $parent['children'] = array(); 513 if (!in_array($parent['type'], array('array', 'object'))) { 514 $parent['type'] = $this->options['complexType']; 515 if ($this->options['complexType'] == 'object') { 516 $parent['class'] = $parent['name']; 517 } 518 } 519 } 520 521 if (!empty($value['name'])) { 522 // there already has been a tag with this name 523 if (in_array($value['name'], $parent['childrenKeys']) || in_array($value['name'], $this->options['forceEnum'])) { 524 // no aggregate has been created for this tag 525 if (!in_array($value['name'], $parent['aggregKeys'])) { 526 if (isset($parent['children'][$value['name']])) { 527 $parent['children'][$value['name']] = array($parent['children'][$value['name']]); 528 } else { 529 $parent['children'][$value['name']] = array(); 530 } 531 array_push($parent['aggregKeys'], $value['name']); 532 } 533 array_push($parent['children'][$value['name']], $value['value']); 534 } else { 535 $parent['children'][$value['name']] = &$value['value']; 536 array_push($parent['childrenKeys'], $value['name']); 537 } 538 } else { 539 array_push($parent['children'],$value['value']); 540 } 541 array_push($this->_valStack, $parent); 542 } 543 544 $this->_depth--; 545 } 546 547 /** 548 * Handler for character data 549 * 550 * @access private 551 * @param object XML parser object 552 * @param string CDATA 553 * @return void 554 */ 555 function cdataHandler($parser, $cdata) 556 { 557 $this->_dataStack[$this->_depth] .= $cdata; 558 } 559 560 /** 561 * create the XML_Parser instance 562 * 563 * @access private 564 * @return boolean 565 */ 566 function _createParser() 567 { 568 if (is_object($this->_parser)) { 569 $this->_parser->free(); 570 unset($this->_parser); 571 } 572 $this->_parser = &new XML_Parser($this->options['encoding'], 'event', $this->options['targetEncoding']); 573 $this->_parser->folding = false; 574 $this->_parser->setHandlerObj($this); 575 return true; 576 } 577 } 578 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Mon Nov 26 14:10:01 2007 | par Balluche grâce à PHPXref 0.7 |
|