[ Index ] |
|
Code source de LifeType 1.2.4 |
1 <?php 2 // 3 // +----------------------------------------------------------------------+ 4 // | PEAR :: XML_Tree | 5 // +----------------------------------------------------------------------+ 6 // | Copyright (c) 1997-2003 The PHP Group | 7 // +----------------------------------------------------------------------+ 8 // | This source file is subject to version 2.02 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: Bernd Römer <berndr@bonn.edu> | 17 // | Sebastian Bergmann <sb@sebastian-bergmann.de> | 18 // | Tomas V.V.Cox <cox@idecnet.com> | 19 // | Michele Manzato <michele.manzato@verona.miz.it> | 20 // +----------------------------------------------------------------------+ 21 // 22 // $Id: Tree.php,v 1.35 2004/05/26 14:58:18 davey Exp $ 23 // 24 25 lt_include(PLOG_CLASS_PATH."class/xml/parser/Parser.php"); 26 lt_include(PLOG_CLASS_PATH."class/xml/tree/Node.php"); 27 28 /** 29 * \ingroup XML 30 * 31 * PEAR::XML_Tree 32 * 33 * Purpose 34 * 35 * Allows for the building of XML data structures 36 * using a tree representation, without the need 37 * for an extension like DOMXML. 38 * 39 * Example 40 * 41 * $tree = new XML_Tree; 42 * $root =& $tree->addRoot('root'); 43 * $foo =& $root->addChild('foo'); 44 * 45 * $tree->dump(true); 46 * 47 * @author Bernd Römer <berndr@bonn.edu> 48 * @package XML 49 * @version $Version$ - 1.0 50 */ 51 class XML_Tree extends XML_Parser 52 { 53 /** 54 * File Handle 55 * 56 * @var resource 57 */ 58 var $file = NULL; 59 60 /** 61 * Filename from which the XML_Tree was read 62 * 63 * @var string 64 */ 65 var $filename = ''; 66 67 /** 68 * Namespace 69 * 70 * @var array 71 */ 72 var $namespace = array(); 73 74 /** 75 * Root node of the XML tree 76 * 77 * @var object XML_Tree_Node 78 */ 79 var $root = NULL; 80 81 /** 82 * XML Version 83 * 84 * @var string 85 */ 86 var $version = '1.0'; 87 88 /** 89 * Whether to encapsulate the all CDATA in a <![CDATA[]]> section 90 * 91 * @var boolean 92 */ 93 94 var $use_cdata_sections = false; 95 96 /** 97 * Constructor 98 * 99 * @param string filename Filename where to read the XML 100 * @param string version XML Version to apply 101 */ 102 function XML_Tree($filename = '', $version = '1.0') 103 { 104 $this->filename = $filename; 105 $this->version = $version; 106 } 107 108 /** 109 * Use <![CDATA[]]> for all CDATA sections 110 * 111 * @return void 112 */ 113 114 function useCdataSections() 115 { 116 $this->use_cdata_sections = true; 117 } 118 119 /** 120 * Gets the root node 121 * 122 * @return object Root XML_Tree_Node, or PEAR_Error if there isn't any root node. 123 * 124 * @access public 125 */ 126 function &getRoot() 127 { 128 if (!is_null($this->root)) { 129 return $this->root; 130 } 131 return $this->raiseError("No root"); 132 } 133 134 /** 135 * Sets the root node of the XML tree. 136 * 137 * @param string name Name of root element 138 * 139 * @return object XML_Tree_Node Reference to the newly created root node 140 * @access public 141 */ 142 function &addRoot($name, $content = '', $attributes = array(), $lineno = null) 143 { 144 $this->root = new XML_Tree_Node($name, $content, $attributes, $lineno); 145 return $this->root; 146 } 147 148 /** 149 * Inserts a child/tree (child) into tree ($path,$pos) and maintains 150 * namespace integrity 151 * 152 * @param mixed path Path to parent node to add child (see 153 * getNodeAt() for format) 154 * @param integer pos Position where to insert the new child. 155 * 0 < means |$pos| elements before the end, 156 * e.g. -1 appends as last child. 157 * @param mixed child Child to insert (XML_Tree or XML_Tree_Node), 158 * or name of child node 159 * @param string content Content (text) for the new node (only if 160 * $child is the node name) 161 * @param array attributes Attribute-hash for new node 162 * 163 * @return object Reference to the inserted child (node), or PEAR_Error upon error 164 * @access public 165 * @see getNodeAt() 166 */ 167 function &insertChild($path, $pos, $child, $content = '', $attributes = array()) 168 { 169 $parent =& $this->getNodeAt($path); 170 if (!$parent) { 171 return $parent; 172 } 173 174 $x =& $parent->insertChild(null, $pos, $child, $content, $attributes); 175 176 if (!$this->isError($x)) { 177 // update namespace to maintain namespace integrity 178 $count = count($path); 179 foreach ($this->namespace as $key => $val) { 180 if ((array_slice($val,0,$count)==$path) && ($val[$count]>=$pos)) { 181 $this->namespace[$key][$count]++; 182 } 183 } 184 } 185 return $x; 186 } 187 188 /** 189 * Removes a child node from tree and maintains namespace integrity 190 * 191 * @param array path Path to the parent of child to remove (see 192 * getNodeAt() for format) 193 * @param integer pos Position of child in parent children-list 194 * 0 < means |$pos| elements before the end, 195 * e.g. -1 removes the last child. 196 * 197 * @return object Parent XML_Tree_Node whose child was removed, or PEAR_Error upon error 198 * @access public 199 * @see getNodeAt() 200 */ 201 function &removeChild($path, $pos) 202 { 203 $parent =& $this->getNodeAt($path); 204 if ($this->isError($parent)) { 205 return $parent; 206 } 207 208 $x =& $parent->removeChild($pos); 209 210 if (!$this->isError($x)) { 211 // Update namespace to maintain namespace integrity 212 $count=count($path); 213 foreach($this->namespace as $key => $val) { 214 if (array_slice($val,0,$count)==$path) { 215 if ($val[$count]==$pos) { 216 unset($this->namespace[$key]); break; 217 } 218 if ($val[$count]>$pos) { 219 $this->namespace[$key][$count]--; 220 } 221 } 222 } 223 } 224 225 return $x; 226 } 227 228 /** 229 * Maps a XML file to a XML_Tree 230 * 231 * @return mixed The XML tree root (an XML_Tree_Node), or PEAR_Error upon error. 232 * @access public 233 */ 234 function &getTreeFromFile () 235 { 236 $this->folding = false; 237 $this->XML_Parser(null, 'event'); 238 $err = $this->setInputFile($this->filename); 239 if ($this->isError($err)) { 240 return $err; 241 } 242 $this->cdata = null; 243 $err = $this->parse(); 244 if ($this->isError($err)) { 245 return $err; 246 } 247 return $this->root; 248 } 249 250 /** 251 * Maps an XML string to an XML_Tree. 252 * 253 * @return mixed The XML tree root (an XML_Tree_Node), or PEAR_Error upon error. 254 * @access public 255 */ 256 function &getTreeFromString($str) 257 { 258 $this->i = null; 259 $this->folding = false; 260 $this->XML_Parser(null, 'event'); 261 $this->cdata = null; 262 $err = $this->parseString($str); 263 if ($this->isError($err)) { 264 return $err; 265 } 266 return $this->root; 267 } 268 269 /** 270 * Handler for the xml-data 271 * Used by XML_Parser::XML_Parser() when parsing an XML stream. 272 * 273 * @param mixed xp ignored 274 * @param string elem name of the element 275 * @param array attribs attributes for the generated node 276 * 277 * @access private 278 */ 279 function startHandler($xp, $elem, &$attribs) 280 { 281 $lineno = xml_get_current_line_number($xp); 282 283 // root elem 284 if (!isset($this->i)) { 285 $this->obj1 =& $this->addRoot($elem, null, $attribs, $lineno); 286 $this->i = 2; 287 } else { 288 // mixed contents 289 if (!empty($this->cdata)) { 290 $parent_id = 'obj' . ($this->i - 1); 291 $parent =& $this->$parent_id; 292 //$parent->children[] = &new XML_Tree_Node(null, $this->cdata, null, $lineno); 293 } 294 $obj_id = 'obj' . $this->i++; 295 $this->$obj_id = &new XML_Tree_Node($elem, null, $attribs, $lineno); 296 } 297 $this->cdata = null; 298 return null; 299 } 300 301 /** 302 * Handler for the xml-data 303 * Used by XML_Parser::XML_Parser() when parsing an XML stream. 304 * 305 * @param mixed xp ignored 306 * @param string elem name of the element 307 * 308 * @access private 309 */ 310 function endHandler($xp, $elem) 311 { 312 $this->i--; 313 if ($this->i > 1) { 314 $obj_id = 'obj' . $this->i; 315 // recover the node created in StartHandler 316 $node =& $this->$obj_id; 317 // mixed contents 318 if (count($node->children) > 0) { 319 if (trim($this->cdata) != '') { 320 $node->children[] = &new XML_Tree_Node(null, $this->cdata); 321 } 322 } else { 323 $node->setContent($this->cdata); 324 } 325 $parent_id = 'obj' . ($this->i - 1); 326 $parent =& $this->$parent_id; 327 // attach the node to its parent node children array 328 $parent->children[] = $node; 329 } else { 330 $node =& $this->obj1; 331 if (count($node->children) > 0) { 332 if (trim($this->cdata)) { 333 $node->children[] = &new XML_Tree_Node(null, $this->cdata); 334 } 335 } else { 336 $node->setContent($this->cdata); 337 } 338 } 339 $this->cdata = null; 340 return null; 341 } 342 343 /** 344 * The xml character data handler 345 * Used by XML_Parser::XML_Parser() when parsing an XML stream. 346 * 347 * @param mixed xp ignored 348 * @param string data PCDATA between tags 349 * 350 * @access private 351 */ 352 function cdataHandler($xp, $data) 353 { 354 $this->cdata .= $data; 355 } 356 357 /** 358 * Get a copy of this tree by cloning and all of its nodes, recursively. 359 * 360 * @return object XML_Tree copy of this node. 361 * @access public 362 */ 363 function cloneTree() 364 { 365 $clone = new XML_Tree($this->filename, $this->version); 366 if (!is_null($this->root)) { 367 $clone->root = $this->root->cloneTree(); 368 } 369 370 // clone all other vars 371 $temp = get_object_vars($this); 372 foreach($temp as $varname => $value) { 373 if (!in_array($varname,array('filename','version','root'))) { 374 $clone->$varname=$value; 375 } 376 } 377 return $clone; 378 } 379 380 /** 381 * Print text representation of XML tree. 382 * 383 * @param bool xmlHeader if true then generate also the leading XML 384 * 'Content-type' header directive, e.g. for 385 * direct output to a web page. 386 * 387 * @access public 388 */ 389 function dump($xmlHeader = false) 390 { 391 if ($xmlHeader) { 392 header('Content-type: text/xml'); 393 } 394 echo $this->get($this->use_cdata_sections); 395 } 396 397 /** 398 * Get text representation of XML tree. 399 * 400 * @return string Text (XML) representation of the tree 401 * @access public 402 */ 403 function &get() 404 { 405 $out = '<?xml version="' . $this->version . "\"?>\n"; 406 407 if (!is_null($this->root)) 408 { 409 if(!is_object($this->root) || (strtolower(get_class($this->root)) != 'xml_tree_node')) 410 return $this->raiseError("Bad XML root node"); 411 $out .= $this->root->get($this->use_cdata_sections); 412 } 413 return $out; 414 } 415 416 /** 417 * Get current namespace. 418 * 419 * @param string name namespace 420 * @return string 421 * 422 * @access public 423 */ 424 function &getName($name) { 425 return $this->root->getElement($this->namespace[$name]); 426 } 427 428 /** 429 * Get A Nodes Namespace 430 */ 431 432 function getNodeNamespace(&$node) { 433 $name_parts = explode(':',$node->name); 434 if (sizeof($name_parts) > 1) { 435 $namespace = $name_parts[0]; 436 } else { 437 $namespace = ''; 438 } 439 440 if (isset($node->namespace[$namespace])) { 441 return $node->namespace[$namespace]; 442 } elseif (isset($this->root->namespace[$namespace])) { 443 return $this->root->namespace[$namespace]; 444 } else { 445 return ''; 446 } 447 } 448 449 /** 450 * Get a reference to a node. Node is searched by its 'path'. 451 * 452 * @param mixed path Path to node. Can be either a string (slash-separated 453 * children names) or an array (sequence of children names) both 454 * of them starting from node. Note that the first name in sequence 455 * must be the name of the document root. 456 * @return object Reference to the XML_Tree_Node found, or PEAR_Error if 457 * the path does not exist. If more than one element matches 458 * then only the first match is returned. 459 * @access public 460 */ 461 function &getNodeAt($path) 462 { 463 if (is_null($this->root)){ 464 //_debug("XML_Tree hasn't got a root node"); 465 return false; 466 } 467 if (is_string($path)) 468 $path = explode("/", $path); 469 if (sizeof($path) == 0) { 470 //_debug("Path '$path' to node is empty"); 471 return false; 472 } 473 $path1 = $path; 474 $rootName = array_shift($path1); 475 if ($this->root->name != $rootName) { 476 //_debug("Path '$path' does not match the document root"); 477 return false; 478 } 479 $x =& $this->root->getNodeAt($path1); 480 481 if ( $x ) { 482 return $x; 483 } 484 // No node with that name found 485 //_debug("Bad path '$path' to node 2: [".implode('/', $path)."]"); 486 $x = false; 487 return $x; 488 } 489 490 /** 491 * Gets all children that match a given tag name. 492 * 493 * @param string Tag name 494 * 495 * @return array An array of Node objects of the children found, 496 * an empty array if none 497 * @access public 498 * @author Pierre-Alain Joye <paj@pearfr.org> 499 */ 500 function &getElementsByTagName($tagName) 501 { 502 if (empty($tagName)) { 503 return $this->raiseError('Empty tag name'); 504 } 505 $result = array(); 506 foreach ($this->root->children as $child) { 507 if ($child->name == $tagName) { 508 $result[] = $child; 509 } 510 } 511 return $result; 512 } 513 514 /** 515 * Gets all children that match a given tag name from node 516 * 517 * @param string $tagName Tag Name 518 * @param object &$node Node in which to search 519 * @see XML_Tree::getElementsByTagName() 520 * @return array An array of found Node objects, empty is none found. 521 * @access public 522 * @author Pierre-Alain Joye <paj@pearfr.org> 523 * @author Davey Shafik <davey@php.net> 524 */ 525 526 function &getElementsByTagNameFromNode($tagName, &$node) 527 { 528 if (empty($tagName)) { 529 return $this->raiseError('Empty tag name'); 530 } 531 $result = array(); 532 foreach ($node->children as $child) { 533 if ($child->name == $tagName) { 534 $result[] = $child; 535 } 536 } 537 return $result; 538 } 539 540 541 /** 542 * Checks if $name is a valid XML name 543 * 544 * @static 545 * @param string $name String to check for validity as an XML Name 546 * @return mixed 547 */ 548 549 function isValidName($name, $type) { 550 if (trim($name) == '') { 551 return true; 552 } 553 554 // check for invalid starting character 555 if (!preg_match("/[[:alpha:]_]/", $name{0})) { 556 //return new XML_Parser_Error( ucfirst($type) . " ('$name') has an invalid name, an XML name may only start with a letter or underscore"); 557 return false; 558 } 559 560 if (!preg_match("/^([a-zA-Z_]([a-zA-Z0-9_\-\.]*)?:)?[a-zA-Z_]([a-zA-Z0-9_\-\.]+)?$/", $name)) { 561 //return new XML_Parser_Error( ucfirst($type) . " ('$name') has an invalid name, an XML name may only contain alphanumeric chars, period, hyphen, colon and underscores"); 562 return false; 563 } 564 565 return true; 566 } 567 } 568 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Mon Nov 26 21:04:15 2007 | par Balluche grâce à PHPXref 0.7 |
![]() |