[ Index ]
 

Code source de LifeType 1.2.4

Accédez au Source d'autres logiciels libres

Classes | Fonctions | Variables | Constantes | Tables

title

Body

[fermer]

/class/xml/tree/ -> Tree.php (source)

   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  ?>


Généré le : Mon Nov 26 21:04:15 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics