[ Index ]
 

Code source de phpMyVisites 2.3

Accédez au Source d'autres logiciels libres

Classes | Fonctions | Variables | Constantes | Tables

title

Body

[fermer]

/libs/Xml/ -> 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.1 2005/12/06 01:50:39 matthieu_ 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   * XML Parser class.

  73   *

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

  75   * based on the bundled expat library.

  76   *

  77   * Notes:

  78   * - It requires PHP 4.0.4pl1 or greater

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

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

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

  82   *

  83   * @category XML

  84   * @package XML_Parser

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

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

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

  88   * @todo    create XML_Parser_Namespace to parse documents with namespaces

  89   * @todo    create XML_Parser_Pull

  90   * @todo    Tests that need to be made:

  91   *          - mixing character encodings

  92   *          - a test using all expat handlers

  93   *          - options (folding, output charset)

  94   *          - different parsing modes

  95   */
  96  class XML_Parser extends PEAR
  97  {
  98      // {{{ properties

  99  
 100     /**

 101       * XML parser handle

 102       *

 103       * @var  resource

 104       * @see  xml_parser_create()

 105       */
 106      var $parser;
 107  
 108      /**

 109       * File handle if parsing from a file

 110       *

 111       * @var  resource

 112       */
 113      var $fp;
 114  
 115      /**

 116       * Whether to do case folding

 117       *

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

 119       * be converted to UPPER CASE.

 120       *

 121       * @var  boolean

 122       */
 123      var $folding = true;
 124  
 125      /**

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

 127       *

 128       * @var  string

 129       */
 130      var $mode;
 131  
 132      /**

 133       * Mapping from expat handler function to class method.

 134       *

 135       * @var  array

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

 147       * source encoding

 148       *

 149       * @var string

 150       */
 151      var $srcenc;
 152  
 153      /**

 154       * target encoding

 155       *

 156       * @var string

 157       */
 158      var $tgtenc;
 159  
 160      /**

 161       * handler object

 162       *

 163       * @var object

 164       */
 165      var $_handlerObj;
 166  
 167      // }}}

 168      // {{{ constructor

 169  
 170      /**

 171       * Creates an XML parser.

 172       *

 173       * This is needed for PHP4 compatibility, it will

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

 175       *

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

 177       *                       whatever the document specifies

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

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

 180       *                       to have it call functions named after elements

 181       * @param string $tgenc  a valid target encoding

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

 188  
 189      /**

 190       * PHP5 constructor

 191       *

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

 193       *                       whatever the document specifies

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

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

 196       *                       to have it call functions named after elements

 197       * @param string $tgenc  a valid target encoding

 198       */
 199      function __construct($srcenc = null, $mode = 'event', $tgtenc = null)
 200      {
 201          $this->PEAR('XML_Parser_Error');
 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->_handlerObj);
 275                  xml_set_element_handler($this->parser, array(&$this, 'funcStartHandler'), array(&$this, '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          return true;
 360      }
 361  
 362      // }}}

 363      // {{{ setInputFile()

 364  
 365      /**

 366       * Sets the input xml file to be parsed

 367       *

 368       * @param    string      Filename (full path)

 369       * @return   resource    fopen handle of the given file

 370       * @throws   XML_Parser_Error

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

 372       * @access   public

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

 377           * check, if file is a remote file

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

 394      // {{{ setInputString()

 395      
 396      /**

 397       * XML_Parser::setInputString()

 398       * 

 399       * Sets the xml input from a string

 400       * 

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

 402       * @return null

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

 411      // {{{ setInput()

 412  
 413      /**

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

 415       *

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

 417       * pass a string 

 418       *

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

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

 421       * @access   public

 422       * @see      parse()

 423       * @uses     setInputString(), setInputFile()

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

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

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

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

 449      // {{{ parse()

 450  
 451      /**

 452       * Central parsing function.

 453       *

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

 455       * @access   public

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

 460           * reset the parser

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

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

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

 490       * XML_Parser::_parseString()

 491       * 

 492       * @param string $data

 493       * @param boolean $eof

 494       * @return bool

 495       * @access private

 496       * @see parseString()

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

 504      // {{{ parseString()

 505  
 506      /**

 507       * XML_Parser::parseString()

 508       * 

 509       * Parses a string.

 510       *

 511       * @param    string  $data XML data

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

 513       * @throws   XML_Parser_Error

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

 515       * @see      _parseString()

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

 536       * XML_Parser::free()

 537       * 

 538       * Free the internal resources associated with the parser

 539       * 

 540       * @return null

 541       **/
 542      function free()
 543      {
 544          if (isset($this->parser) && is_resource($this->parser)) {
 545              xml_parser_free($this->parser);
 546              unset( $this->parser );
 547          }
 548          if (isset($this->fp) && is_resource($this->fp)) {
 549              fclose($this->fp);
 550          }
 551          unset($this->fp);
 552          return null;
 553      }
 554      
 555      /**

 556       * XML_Parser::raiseError()

 557       * 

 558       * Throws a XML_Parser_Error

 559       * 

 560       * @param string  $msg   the error message

 561       * @param integer $ecode the error message code

 562       * @return XML_Parser_Error 

 563       **/
 564      function raiseError($msg = null, $ecode = 0)
 565      {
 566          $msg = !is_null($msg) ? $msg : $this->parser;
 567          $err = &new XML_Parser_Error($msg, $ecode);
 568          return parent::raiseError($err);
 569      }
 570      
 571      // }}}

 572      // {{{ funcStartHandler()

 573  
 574      function funcStartHandler($xp, $elem, $attribs)
 575      {
 576          $func = 'xmltag_' . $elem;
 577          if (strchr($func, '.')) {
 578              $func = str_replace('.', '_', $func);
 579          }
 580          if (method_exists($this->_handlerObj, $func)) {
 581              call_user_func(array(&$this->_handlerObj, $func), $xp, $elem, $attribs);
 582          } elseif (method_exists($this->_handlerObj, 'xmltag')) {
 583              call_user_func(array(&$this->_handlerObj, 'xmltag'), $xp, $elem, $attribs);
 584          }
 585      }
 586  
 587      // }}}

 588      // {{{ funcEndHandler()

 589  
 590      function funcEndHandler($xp, $elem)
 591      {
 592          $func = 'xmltag_' . $elem . '_';
 593          if (strchr($func, '.')) {
 594              $func = str_replace('.', '_', $func);
 595          }
 596          if (method_exists($this->_handlerObj, $func)) {
 597              call_user_func(array(&$this->_handlerObj, $func), $xp, $elem);
 598          } elseif (method_exists($this->_handlerObj, 'xmltag_')) {
 599              call_user_func(array(&$this->_handlerObj, 'xmltag_'), $xp, $elem);
 600          }
 601      }
 602  
 603      // }}}

 604      // {{{ startHandler()

 605  
 606      /**

 607       *

 608       * @abstract

 609       */
 610      function startHandler($xp, $elem, &$attribs)
 611      {
 612          return NULL;
 613      }
 614  
 615      // }}}

 616      // {{{ endHandler()

 617  
 618      /**

 619       *

 620       * @abstract

 621       */
 622      function endHandler($xp, $elem)
 623      {
 624          return NULL;
 625      }
 626  
 627  
 628      // }}}me

 629  }
 630  
 631  /**

 632   * error class, replaces PEAR_Error

 633   *

 634   * An instance of this class will be returned

 635   * if an error occurs inside XML_Parser.

 636   *

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

 638   * - All messages will be prefixed

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

 640   * - messages can be generated from the xml_parser resource

 641   *

 642   * @package XML_Parser

 643   * @access  public

 644   * @see     PEAR_Error

 645   */
 646  class XML_Parser_Error extends PEAR_Error
 647  {
 648      // {{{ properties

 649  
 650     /**

 651      * prefix for all messages

 652      *

 653      * @var      string

 654      */    
 655      var $error_message_prefix = 'XML_Parser: ';
 656  
 657      // }}}

 658      // {{{ constructor()

 659     /**

 660      * construct a new error instance

 661      *

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

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

 664      * happened will be retrieved and returned.

 665      *

 666      * @access   public

 667      * @param    string|resource     message or parser resource

 668      * @param    integer             error code

 669      * @param    integer             error handling

 670      * @param    integer             error level

 671      */    
 672      function XML_Parser_Error($msgorparser = 'unknown error', $code = 0, $mode = PEAR_ERROR_RETURN, $level = E_USER_NOTICE)
 673      {
 674          if (is_resource($msgorparser)) {
 675              $code = xml_get_error_code($msgorparser);
 676              $msgorparser = sprintf('%s at XML input line %d',
 677                                     xml_error_string($code),
 678                                     xml_get_current_line_number($msgorparser));
 679          }
 680          $this->PEAR_Error($msgorparser, $code, $mode, $level);
 681      }
 682      // }}}

 683  }
 684  ?>


Généré le : Mon Nov 26 14:10:01 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics