home *** CD-ROM | disk | FTP | other *** search
/ Enter 2004 June / ENTER.ISO / files / xampp-win32-1.4.5-installer.exe / xampp / Parser.php < prev    next >
Encoding:
PHP Script  |  2004-03-24  |  9.2 KB  |  356 lines

  1. <?php
  2. //
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 4                                                        |
  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. // | Author: Stig Bakken <ssb@fast.no>                                    |
  17. // +----------------------------------------------------------------------+
  18. //
  19. // $Id: Parser.php,v 1.5 2003/02/23 10:48:31 ssb Exp $
  20.  
  21. require_once 'PEAR.php';
  22.  
  23. /**
  24.  * XML Parser class.  This is an XML parser based on PHP's "xml" extension,
  25.  * based on the bundled expat library.
  26.  *
  27.  * @author  Stig Bakken <ssb@fast.no>
  28.  * @todo    Tests that need to be made:
  29.  *          - error class
  30.  *          - mixing character encodings
  31.  *          - a test using all expat handlers
  32.  *          - options (folding, output charset)
  33.  *          - different parsing modes
  34.  *
  35.  * @notes   - It requires PHP 4.0.4pl1 or greater
  36.  *          - From revision 1.17, the function names used by the 'func' mode
  37.  *            are in the format "xmltag_$elem", for example: use "xmltag_name"
  38.  *            to handle the <name></name> tags of your xml file.
  39.  */
  40. class XML_Parser extends PEAR
  41. {
  42.     // {{{ properties
  43.  
  44.     /**
  45.      * @var  resource  XML parser handle
  46.      */
  47.     var $parser;
  48.  
  49.     /**
  50.      * @var  resource  File handle if parsing from a file
  51.      */
  52.     var $fp;
  53.  
  54.     /**
  55.      * @var  boolean  Whether to do case folding
  56.      */
  57.     var $folding = true;
  58.  
  59.     /**
  60.      * @var  string  Mode of operation, one of "event" or "func"
  61.      */
  62.     var $mode;
  63.  
  64.     /**
  65.      * Mapping from expat handler function to class method.
  66.      *
  67.      * @var  array
  68.      */
  69.     var $handler = array(
  70.         'character_data_handler'            => 'cdataHandler',
  71.         'default_handler'                   => 'defaultHandler',
  72.         'processing_instruction_handler'    => 'piHandler',
  73.         'unparsed_entity_decl_handler'      => 'unparsedHandler',
  74.         'notation_decl_handler'             => 'notationHandler',
  75.         'external_entity_ref_handler'       => 'entityrefHandler'
  76.     );
  77.  
  78.     /**
  79.      * @var string source encoding
  80.      */
  81.     var $srcenc;
  82.  
  83.     /**
  84.      * @var string target encoding
  85.      */
  86.     var $tgtenc;
  87.  
  88.     /*
  89.      * Use call_user_func when php >= 4.0.7
  90.      * @var boolean
  91.      * @see setMode()
  92.      */
  93.     var $use_call_user_func = true;
  94.  
  95.     // }}}
  96.     // {{{ constructor
  97.  
  98.     /**
  99.      * Creates an XML parser.
  100.      *
  101.      * @param    string  source charset encoding, use NULL (default) to use
  102.      *                   whatever the document specifies
  103.      * @param    string  how this parser object should work, "event" for
  104.      *                   startelement/endelement-type events, "func"
  105.      *                   to have it call functions named after elements
  106.      *
  107.      * @see xml_parser_create
  108.      */
  109.     function XML_Parser($srcenc = null, $mode = "event", $tgtenc = null)
  110.     {
  111.         $this->PEAR('XML_Parser_Error');
  112.  
  113.         if ($srcenc === null) {
  114.             $xp = @xml_parser_create();
  115.         } else {
  116.             $xp = @xml_parser_create($srcenc);
  117.         }
  118.         if (is_resource($xp)) {
  119.             if ($tgtenc !== null) {
  120.                 if (!@xml_parser_set_option($xp, XML_OPTION_TARGET_ENCODING,
  121.                                             $tgtenc)) {
  122.                     return $this->raiseError("invalid target encoding");
  123.                 }
  124.             }
  125.             $this->parser = $xp;
  126.             $this->setMode($mode);
  127.             xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, $this->folding);
  128.         }
  129.         $this->srcenc = $srcenc;
  130.         $this->tgtenc = $tgtenc;
  131.     }
  132.     // }}}
  133.  
  134.     // {{{ setMode()
  135.  
  136.     /**
  137.      * Sets the mode and all handler.
  138.      *
  139.      * @param    string
  140.      * @see      $handler
  141.      */
  142.     function setMode($mode)
  143.     {
  144.  
  145.         $this->mode = $mode;
  146.  
  147.         xml_set_object($this->parser, $this);
  148.  
  149.         switch ($mode) {
  150.  
  151.             case "func":
  152.                 // use call_user_func() when php >= 4.0.7
  153.                 // or call_user_method() if not
  154.                 if (version_compare(phpversion(), '4.0.7', 'lt')) {
  155.                     $this->use_call_user_func = false;
  156.                 } else {
  157.                     $this->use_call_user_func = true;
  158.                 }
  159.  
  160.                 xml_set_element_handler($this->parser, "funcStartHandler", "funcEndHandler");
  161.                 break;
  162.  
  163.             case "event":
  164.                 xml_set_element_handler($this->parser, "startHandler", "endHandler");
  165.                 break;
  166.         }
  167.  
  168.         foreach ($this->handler as $xml_func => $method)
  169.             if (method_exists($this, $method)) {
  170.                 $xml_func = "xml_set_" . $xml_func;
  171.                 $xml_func($this->parser, $method);
  172.             }
  173.  
  174.     }
  175.  
  176.     // }}}
  177.     // {{{ setInputFile()
  178.  
  179.     /**
  180.      * Defines
  181.      *
  182.      * @param    string      Filename (full path)
  183.      * @return   resource    fopen handle of the given file
  184.      * @throws   XML_Parser_Error
  185.      * @see      setInput(), parse()
  186.      * @access   public
  187.      */
  188.     function setInputFile($file)
  189.     {
  190.  
  191.         $fp = @fopen($file, "rb");
  192.         if (is_resource($fp)) {
  193.             $this->fp = $fp;
  194.             return $fp;
  195.         }
  196.  
  197.         return $this->raiseError($php_errormsg);
  198.     }
  199.  
  200.     // }}}
  201.     // {{{ setInput()
  202.  
  203.     /**
  204.      * Sets the file handle to use with parse().
  205.      *
  206.      * @param    resource    fopen
  207.      * @access   public
  208.      * @see      parse(), setInputFile()
  209.      */
  210.     function setInput($fp)
  211.     {
  212.         if (is_resource($fp)) {
  213.             $this->fp = $fp;
  214.             return true;
  215.         }
  216.  
  217.         return $this->raiseError("not a file resource");
  218.     }
  219.  
  220.     // }}}
  221.     // {{{ parse()
  222.  
  223.     /**
  224.      * Central parsing function.
  225.      *
  226.      * @throws   XML_Parser_Error
  227.      * @return   boolean true on success
  228.      * @see      parseString()
  229.      * @access   public
  230.      */
  231.     function parse()
  232.     {
  233.         if (!is_resource($this->fp)) {
  234.             return $this->raiseError("no input");
  235.         }
  236.  
  237.         while ($data = fread($this->fp, 2048)) {
  238.  
  239.             $err = $this->parseString($data, feof($this->fp));
  240.             if (PEAR::isError($err)) {
  241.                 fclose($this->fp);
  242.                 return $err;
  243.             }
  244.  
  245.         }
  246.  
  247.         fclose($this->fp);
  248.  
  249.         return true;
  250.     }
  251.  
  252.     // }}}
  253.     // {{{ parseString()
  254.  
  255.     /**
  256.      * Parses a string.
  257.      *
  258.      * @param    string  XML data
  259.      * @param    boolean ???
  260.      * @throws   XML_Parser_Error
  261.      * @return   mixed   true on success or a string with the xml parser error
  262.      */
  263.     function parseString($data, $eof = false)
  264.     {
  265.         if (!xml_parse($this->parser, $data, $eof)) {
  266.             $err = $this->raiseError($this->parser);
  267.             xml_parser_free($this->parser);
  268.             return $err;
  269.         }
  270.  
  271.         return true;
  272.     }
  273.  
  274.     // }}}
  275.     // {{{ funcStartHandler()
  276.  
  277.     function funcStartHandler($xp, $elem, $attribs)
  278.     {
  279.         $func = 'xmltag_' . $elem;
  280.         if (method_exists($this, $func)) {
  281.             if ($this->use_call_user_func) {
  282.                 call_user_func(array(&$this, $func), $xp, $elem, $attribs);
  283.             } else {
  284.                 call_user_method($func, $this, $xp, $elem, $attribs);
  285.             }
  286.         }
  287.  
  288.     }
  289.  
  290.     // }}}
  291.     // {{{ funcEndHandler()
  292.  
  293.     function funcEndHandler($xp, $elem)
  294.     {
  295.         $func = 'xmltag_' . $elem . '_';
  296.         if (method_exists($this, $func)) {
  297.             if ($this->use_call_user_func) {
  298.                 call_user_func(array(&$this, $func), $xp, $elem);
  299.             } else {
  300.                 call_user_method($func, $this, $xp, $elem);
  301.             }
  302.         }
  303.     }
  304.  
  305.     // }}}
  306.     // {{{ startHandler()
  307.  
  308.     /**
  309.      *
  310.      * @abstract
  311.      */
  312.     function startHandler($xp, $elem, &$attribs)
  313.     {
  314.         return NULL;
  315.     }
  316.  
  317.     // }}}
  318.     // {{{ endHandler()
  319.  
  320.     /**
  321.      *
  322.      * @abstract
  323.      */
  324.     function endHandler($xp, $elem)
  325.     {
  326.         return NULL;
  327.     }
  328.  
  329.  
  330.     // }}}
  331. }
  332.  
  333. class XML_Parser_Error extends PEAR_Error
  334. {
  335.     // {{{ properties
  336.  
  337.     var $error_message_prefix = 'XML_Parser: ';
  338.  
  339.     // }}}
  340.     // {{{ constructor()
  341.  
  342.     function XML_Parser_Error($msgorparser = 'unknown error', $code = 0, $mode = PEAR_ERROR_RETURN, $level = E_USER_NOTICE)
  343.     {
  344.         if (is_resource($msgorparser)) {
  345.             $code = xml_get_error_code($msgorparser);
  346.             $msgorparser = sprintf("%s at XML input line %d",
  347.                                    xml_error_string($code),
  348.                                    xml_get_current_line_number($msgorparser));
  349.         }
  350.         $this->PEAR_Error($msgorparser, $code, $mode, $level);
  351.  
  352.     }
  353.  
  354.     // }}}
  355. }
  356. ?>