[ 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/parser/ -> Parser.php (source)

   1  <?php
   2  //

   3  // +----------------------------------------------------------------------+

   4  // | PHP Version 4                                                        |

   5  // +----------------------------------------------------------------------+

   6  // | Copyright (c) 1997-2004 The PHP Group                                |

   7  // +----------------------------------------------------------------------+

   8  // | This source file is subject to version 3.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/3_0.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  // | Author: Stig Bakken <ssb@fast.no>                                    |

  17  // |         Tomas V.V.Cox <cox@idecnet.com>                              |

  18  // |         Stephan Schmidt <schst@php-tools.net>                        |

  19  // +----------------------------------------------------------------------+

  20  //

  21  // $Id: Parser.php,v 1.15 2004/10/04 16:56:49 schst Exp $

  22  
  23  /**

  24   * XML Parser class.

  25   *

  26   * This is an XML parser based on PHP's "xml" extension,

  27   * based on the bundled expat library.

  28   *

  29   * @category XML

  30   * @package XML_Parser

  31   * @author  Stig Bakken <ssb@fast.no>

  32   * @author  Tomas V.V.Cox <cox@idecnet.com>

  33   * @author  Stephan Schmidt <schst@php-tools.net>

  34   */
  35  
  36  /**

  37   * uses PEAR's error handling

  38   */
  39  //require_once 'PEAR.php';

  40  
  41  /**

  42   * resource could not be created

  43   */
  44  define('XML_PARSER_ERROR_NO_RESOURCE', 200);
  45  
  46  /**

  47   * unsupported mode

  48   */
  49  define('XML_PARSER_ERROR_UNSUPPORTED_MODE', 201);
  50  
  51  /**

  52   * invalid encoding was given

  53   */
  54  define('XML_PARSER_ERROR_INVALID_ENCODING', 202);
  55  
  56  /**

  57   * specified file could not be read

  58   */
  59  define('XML_PARSER_ERROR_FILE_NOT_READABLE', 203);
  60  
  61  /**

  62   * invalid input

  63   */
  64  define('XML_PARSER_ERROR_INVALID_INPUT', 204);
  65  
  66  /**

  67   * remote file cannot be retrieved in safe mode

  68   */
  69  define('XML_PARSER_ERROR_REMOTE', 205);
  70  
  71  /**
  72   * \ingroup XML
  73   *
  74   * XML Parser class.

  75   *

  76   * This is an XML parser based on PHP's "xml" extension,

  77   * based on the bundled expat library.

  78   *

  79   * Notes:

  80   * - It requires PHP 4.0.4pl1 or greater

  81   * - From revision 1.17, the function names used by the 'func' mode

  82   *   are in the format "xmltag_$elem", for example: use "xmltag_name"

  83   *   to handle the <name></name> tags of your xml file.

  84   *

  85   * @category XML

  86   * @package XML_Parser

  87   * @author  Stig Bakken <ssb@fast.no>

  88   * @author  Tomas V.V.Cox <cox@idecnet.com>

  89   * @author  Stephan Schmidt <schst@php-tools.net>

  90   * @todo    create XML_Parser_Namespace to parse documents with namespaces

  91   * @todo    create XML_Parser_Pull

  92   * @todo    Tests that need to be made:

  93   *          - mixing character encodings

  94   *          - a test using all expat handlers

  95   *          - options (folding, output charset)

  96   *          - different parsing modes

  97   */
  98  class XML_Parser
  99  {
 100      // {{{ properties

 101  
 102     /**

 103       * XML parser handle

 104       *

 105       * @var  resource

 106       * @see  xml_parser_create()

 107       */
 108      var $parser;
 109  
 110      /**

 111       * File handle if parsing from a file

 112       *

 113       * @var  resource

 114       */
 115      var $fp;
 116  
 117      /**

 118       * Whether to do case folding

 119       *

 120       * If set to true, all tag and attribute names will

 121       * be converted to UPPER CASE.

 122       *

 123       * @var  boolean

 124       */
 125      var $folding = true;
 126  
 127      /**

 128       * Mode of operation, one of "event" or "func"

 129       *

 130       * @var  string

 131       */
 132      var $mode;
 133  
 134      /**

 135       * Mapping from expat handler function to class method.

 136       *

 137       * @var  array

 138       */
 139      var $handler = array(
 140          'character_data_handler'            => 'cdataHandler',
 141          'default_handler'                   => 'defaultHandler',
 142          'processing_instruction_handler'    => 'piHandler',
 143          'unparsed_entity_decl_handler'      => 'unparsedHandler',
 144          'notation_decl_handler'             => 'notationHandler',
 145          'external_entity_ref_handler'       => 'entityrefHandler'
 146      );
 147  
 148      /**

 149       * source encoding

 150       *

 151       * @var string

 152       */
 153      var $srcenc;
 154  
 155      /**

 156       * target encoding

 157       *

 158       * @var string

 159       */
 160      var $tgtenc;
 161  
 162      /**

 163       * handler object

 164       *

 165       * @var object

 166       */
 167      var $_handlerObj;
 168  
 169      // }}}

 170      // {{{ constructor

 171  
 172      /**

 173       * Creates an XML parser.

 174       *

 175       * This is needed for PHP4 compatibility, it will

 176       * call the constructor, when a new instance is created.

 177       *

 178       * @param string $srcenc source charset encoding, use NULL (default) to use

 179       *                       whatever the document specifies

 180       * @param string $mode   how this parser object should work, "event" for

 181       *                       startelement/endelement-type events, "func"

 182       *                       to have it call functions named after elements

 183       * @param string $tgenc  a valid target encoding

 184       */
 185      function XML_Parser($srcenc = null, $mode = 'event', $tgtenc = null)
 186      {
 187          XML_Parser::__construct($srcenc, $mode, $tgtenc);
 188      }
 189      // }}}

 190  
 191      /**

 192       * PHP5 constructor

 193       *

 194       * @param string $srcenc source charset encoding, use NULL (default) to use

 195       *                       whatever the document specifies

 196       * @param string $mode   how this parser object should work, "event" for

 197       *                       startelement/endelement-type events, "func"

 198       *                       to have it call functions named after elements

 199       * @param string $tgenc  a valid target encoding

 200       */
 201      function __construct($srcenc = null, $mode = 'event', $tgtenc = null)
 202      {
 203          $this->mode   = $mode;
 204          $this->srcenc = $srcenc;
 205          $this->tgtenc = $tgtenc;
 206      }
 207      // }}}

 208  
 209      /**

 210       * Sets the mode of the parser.

 211       *

 212       * Possible modes are:

 213       * - func

 214       * - event

 215       *

 216       * You can set the mode using the second parameter

 217       * in the constructor.

 218       *

 219       * This method is only needed, when switching to a new

 220       * mode at a later point.

 221       *

 222       * @access  public

 223       * @param   string          mode, either 'func' or 'event'

 224       * @return  boolean|object  true on success, PEAR_Error otherwise   

 225       */
 226      function setMode($mode)
 227      {
 228          if ($mode != 'func' && $mode != 'event') {
 229              $this->raiseError('Unsupported mode given', XML_PARSER_ERROR_UNSUPPORTED_MODE);
 230          }
 231  
 232          $this->mode = $mode;
 233          return true;
 234      }
 235  
 236      /**

 237       * Sets the object, that will handle the XML events

 238       *

 239       * This allows you to create a handler object independent of the

 240       * parser object that you are using and easily switch the underlying

 241       * parser.

 242       *

 243       * If no object will be set, XML_Parser assumes that you

 244       * extend this class and handle the events in $this.

 245       *

 246       * @access  public

 247       * @param   object      object to handle the events

 248       * @return  boolean     will always return true

 249       * @since   v1.2.0beta3

 250       */
 251      function setHandlerObj(&$obj)
 252      {
 253          $this->_handlerObj = &$obj;
 254          return true;
 255      }
 256  
 257      /**

 258       * Init the element handlers

 259       *

 260       * @access  private

 261       */
 262      function _initHandlers()
 263      {
 264          if (!is_resource($this->parser)) {
 265              return false;
 266          }
 267  
 268          if (!is_object($this->_handlerObj)) {
 269              $this->_handlerObj = &$this;
 270          }
 271          switch ($this->mode) {
 272  
 273              case 'func':
 274                  xml_set_object($this->parser, $this);
 275                  xml_set_element_handler($this->parser, 'funcStartHandler', 'funcEndHandler');
 276                  break;
 277  
 278              case 'event':
 279                  xml_set_object($this->parser, $this->_handlerObj);
 280                  xml_set_element_handler($this->parser, 'startHandler', 'endHandler');
 281                  break;
 282              default:
 283                  return $this->raiseError('Unsupported mode given', XML_PARSER_ERROR_UNSUPPORTED_MODE);
 284                  break;
 285          }
 286  
 287  
 288          /**

 289           * set additional handlers for character data, entities, etc.

 290           */
 291          foreach ($this->handler as $xml_func => $method) {
 292              if (method_exists($this->_handlerObj, $method)) {
 293                  $xml_func = 'xml_set_' . $xml_func;
 294                  $xml_func($this->parser, $method);
 295              }
 296          }
 297      }
 298  
 299      // {{{ _create()

 300  
 301      /**

 302       * create the XML parser resource

 303       *

 304       * Has been moved from the constructor to avoid

 305       * problems with object references.

 306       *

 307       * Furthermore it allows us returning an error

 308       * if something fails.

 309       *

 310       * @access   private

 311       * @return   boolean|object     true on success, PEAR_Error otherwise

 312       *

 313       * @see xml_parser_create

 314       */
 315      function _create()
 316      {
 317          if ($this->srcenc === null) {
 318              $xp = @xml_parser_create();
 319          } else {
 320              $xp = @xml_parser_create($this->srcenc);
 321          }
 322          if (is_resource($xp)) {
 323              if ($this->tgtenc !== null) {
 324                  if (!@xml_parser_set_option($xp, XML_OPTION_TARGET_ENCODING,
 325                                              $this->tgtenc)) {
 326                      return $this->raiseError('invalid target encoding', XML_PARSER_ERROR_INVALID_ENCODING);
 327                  }
 328              }
 329              $this->parser = $xp;
 330              $result = $this->_initHandlers($this->mode);
 331              if ($this->isError($result)) {
 332                  return $result;
 333              }
 334              xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, $this->folding);
 335  
 336              return true;
 337          }
 338          return $this->raiseError('Unable to create XML parser resource.', XML_PARSER_ERROR_NO_RESOURCE);
 339      }
 340  
 341      // }}}

 342      // {{{ reset()

 343  
 344      /**

 345       * Reset the parser.

 346       *

 347       * This allows you to use one parser instance

 348       * to parse multiple XML documents.

 349       *

 350       * @access   public

 351       * @return   boolean|object     true on success, PEAR_Error otherwise

 352       */
 353      function reset()
 354      {
 355          $result = $this->_create();
 356          if ($this->isError( $result )) {
 357              return $result;
 358          }
 359      }
 360  
 361      // }}}

 362      // {{{ setInputFile()

 363  
 364      /**

 365       * Sets the input xml file to be parsed

 366       *

 367       * @param    string      Filename (full path)

 368       * @return   resource    fopen handle of the given file

 369       * @throws   XML_Parser_Error

 370       * @see      setInput(), setInputString(), parse()

 371       * @access   public

 372       */
 373      function setInputFile($file)
 374      {
 375          /**

 376           * check, if file is a remote file

 377           */
 378          if (eregi('^(http|ftp)://', substr($file, 0, 10))) {
 379              if (!ini_get('safe_mode')) {
 380                  ini_set('allow_url_fopen', 1);
 381              } else {
 382                  return $this->raiseError('Remote files cannot be parsed, as safe mode is enabled.', XML_PARSER_ERROR_REMOTE);
 383              }
 384          }
 385          
 386          $fp = @fopen($file, 'rb');
 387          if (is_resource($fp)) {
 388              $this->fp = $fp;
 389              return $fp;
 390          }
 391          return $this->raiseError('File could not be opened.', XML_PARSER_ERROR_FILE_NOT_READABLE);
 392      }
 393  
 394      // }}}

 395      // {{{ setInputString()

 396      
 397      /**

 398       * XML_Parser::setInputString()

 399       * 

 400       * Sets the xml input from a string

 401       * 

 402       * @param string $data a string containing the XML document

 403       * @return null

 404       **/
 405      function setInputString($data)
 406      {
 407          $this->fp = $data;
 408          return null;
 409      }
 410      
 411      // }}}

 412      // {{{ setInput()

 413  
 414      /**

 415       * Sets the file handle to use with parse().

 416       *

 417       * You should use setInputFile() or setInputString() if you

 418       * pass a string 

 419       *

 420       * @param    mixed  $fp  Can be either a resource returned from fopen(),

 421       *                       a URL, a local filename or a string.

 422       * @access   public

 423       * @see      parse()

 424       * @uses     setInputString(), setInputFile()

 425       */
 426      function setInput($fp)
 427      {
 428          if (is_resource($fp)) {
 429              $this->fp = $fp;
 430              return true;
 431          }
 432          // see if it's an absolute URL (has a scheme at the beginning)

 433          elseif (eregi('^[a-z]+://', substr($fp, 0, 10))) {
 434              return $this->setInputFile($fp);
 435          }
 436          // see if it's a local file

 437          elseif (file_exists($fp)) {
 438              return $this->setInputFile($fp);
 439          }
 440          // it must be a string

 441          else {
 442              $this->fp = $fp;
 443              return true;
 444          }
 445  
 446          return $this->raiseError('Illegal input format', XML_PARSER_ERROR_INVALID_INPUT);
 447      }
 448  
 449      // }}}

 450      // {{{ parse()

 451  
 452      /**

 453       * Central parsing function.

 454       *

 455       * @return   true|object PEAR error     returns true on success, or a PEAR_Error otherwise

 456       * @access   public

 457       */
 458      function parse()
 459      {
 460          /**

 461           * reset the parser

 462           */
 463          $result = $this->reset();
 464          if ($this->isError($result)) {
 465              return $result;
 466          }
 467          // if $this->fp was fopened previously

 468          if (is_resource($this->fp)) {
 469          
 470              while ($data = fread($this->fp, 4096)) {
 471                  if (!$this->_parseString($data, feof($this->fp))) {
 472                      return $this->raiseError();
 473                  }
 474              }
 475          // otherwise, $this->fp must be a string

 476          } else {
 477              if (!$this->_parseString($this->fp, true)) {
 478                  return $this->raiseError();
 479              }
 480          }
 481          $this->free();
 482  
 483          return true;
 484      }
 485  
 486      /**

 487       * XML_Parser::_parseString()

 488       * 

 489       * @param string $data

 490       * @param boolean $eof

 491       * @return bool

 492       * @access private

 493       * @see parseString()

 494       **/
 495      function _parseString($data, $eof = false)
 496      {
 497          return xml_parse($this->parser, $data, $eof);
 498      }
 499      
 500      // }}}

 501      // {{{ parseString()

 502  
 503      /**

 504       * XML_Parser::parseString()

 505       * 

 506       * Parses a string.

 507       *

 508       * @param    string  $data XML data

 509       * @param    boolean $eof  If set and TRUE, data is the last piece of data sent in this parser

 510       * @throws   XML_Parser_Error

 511       * @return   Pear Error|true   true on success or a PEAR Error

 512       * @see      _parseString()

 513       */
 514      function parseString($data, $eof = false)
 515      {
 516          if (!isset($this->parser) || !is_resource($this->parser)) {
 517              $this->reset();
 518          }
 519          
 520          if (!$this->_parseString($data, $eof)) {
 521             return $this->raiseError();
 522          }
 523  
 524          if ($eof === true) {
 525              $this->free();
 526          }
 527          return true;
 528      }
 529      
 530      /**

 531       * XML_Parser::free()

 532       * 

 533       * Free the internal resources associated with the parser

 534       * 

 535       * @return null

 536       **/
 537      function free()
 538      {
 539          if (is_resource($this->parser)) {
 540              xml_parser_free($this->parser);
 541              unset( $this->parser );
 542          }
 543          if (isset($this->fp) && is_resource($this->fp)) {
 544              fclose($this->fp);
 545          }
 546          unset($this->fp);
 547          return null;
 548      }
 549      
 550      /**

 551       * XML_Parser::raiseError()

 552       * 

 553       * Trows a XML_Parser_Error and free's the internal resources

 554       * 

 555       * @param string  $msg   the error message

 556       * @param integer $ecode the error message code

 557       * @return XML_Parser_Error 

 558       **/
 559      function raiseError($msg = null, $ecode = 0)
 560      {
 561          $msg = !is_null($msg) ? $msg : $this->parser;
 562          $err = &new XML_Parser_Error($msg, $ecode);
 563          $this->free();
 564          
 565          return $err;
 566      }
 567      
 568      // }}}

 569      // {{{ funcStartHandler()

 570  
 571      function funcStartHandler($xp, $elem, $attribs)
 572      {
 573          $func = 'xmltag_' . $elem;
 574          if (method_exists($this->_handlerObj, $func)) {
 575              call_user_func(array(&$this->_handlerObj, $func), $xp, $elem, $attribs);
 576          }
 577      }
 578  
 579      // }}}

 580      // {{{ funcEndHandler()

 581  
 582      function funcEndHandler($xp, $elem)
 583      {
 584          $func = 'xmltag_' . $elem . '_';
 585          if (method_exists($this->_handlerObj, $func)) {
 586              call_user_func(array(&$this->_handlerObj, $func), $xp, $elem);
 587          }
 588      }
 589  
 590      // }}}

 591      // {{{ startHandler()

 592  
 593      /**

 594       *

 595       * @abstract

 596       */
 597      function startHandler($xp, $elem, &$attribs)
 598      {
 599          return NULL;
 600      }
 601  
 602      // }}}

 603      // {{{ endHandler()

 604  
 605      /**

 606       *

 607       * @abstract

 608       */
 609      function endHandler($xp, $elem)
 610      {
 611          return NULL;
 612      }
 613      
 614  	function isError( $obj )
 615      {
 616          return( is_a( $obj, "XML_Parser_Error" ));
 617      }
 618  
 619      // }}}me

 620  }
 621  
 622  /**

 623   * error class, replaces PEAR_Error

 624   *

 625   * An instance of this class will be returned

 626   * if an error occurs inside XML_Parser.

 627   *

 628   * There are three advantages over using the standard PEAR_Error:

 629   * - All messages will be prefixed

 630   * - check for XML_Parser error, using is_a( $error, 'XML_Parser_Error' )

 631   * - messages can be generated from the xml_parser resource

 632   *

 633   * @package XML_Parser

 634   * @access  public

 635   * @see     PEAR_Error

 636   */
 637  class XML_Parser_Error
 638  {
 639      // {{{ properties

 640  
 641     /**

 642      * prefix for all messages

 643      *

 644      * @var      string

 645      */    
 646      var $error_message_prefix = 'XML_Parser: ';
 647  
 648      // }}}

 649      // {{{ constructor()

 650     /**

 651      * construct a new error instance

 652      *

 653      * You may either pass a message or an xml_parser resource as first

 654      * parameter. If a resource has been passed, the last error that

 655      * happened will be retrieved and returned.

 656      *

 657      * @access   public

 658      * @param    string|resource     message or parser resource

 659      * @param    integer             error code

 660      * @param    integer             error handling

 661      * @param    integer             error level

 662      */    
 663      function XML_Parser_Error($msgorparser = 'unknown error', $code = 0, $mode = PEAR_ERROR_RETURN, $level = E_USER_NOTICE)
 664      {
 665          if (is_resource($msgorparser)) {
 666              $code = xml_get_error_code($msgorparser);
 667              $msgorparser = sprintf('%s at XML input line %d',
 668                                     xml_error_string($code),
 669                                     xml_get_current_line_number($msgorparser));
 670          }
 671          $this->msgorparser = $msgorparser;
 672          $this->code = $code;
 673          $this->mode = $mode;
 674          $this->level = $level;
 675      }
 676          
 677      // }}}

 678  }
 679  ?>


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