home *** CD-ROM | disk | FTP | other *** search
/ PC World 2003 March / PCWorld_2003-03_cd.bin / Software / Vyzkuste / phptriad / phptriad2-2-1.exe / php / pear / XML / Parser.php next >
Encoding:
PHP Script  |  2001-11-13  |  9.4 KB  |  344 lines

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