package.xml0000644000175000017500000004213311461312050013753 0ustar clockwerxclockwerx XML_Parser pear.php.net XML parsing class based on PHP's bundled expat This is an XML parser based on PHPs built-in xml extension. It supports two basic modes of operation: "func" and "event". In "func" mode, it will look for a function named after each element (xmltag_ELEMENT for start tags and xmltag_ELEMENT_ for end tags), and in "event" mode it uses a set of generic callbacks. Since version 1.2.0 there's a new XML_Parser_Simple class that makes parsing of most XML documents easier, by automatically providing a stack for the elements. Furthermore its now possible to split the parser from the handler object, so you do not have to extend XML_Parser anymore in order to parse a document with it. Stephan Schmidt schst schst@php-tools.net no Chuck Burgess ashnazg ashnazg@php.net yes Stig Sæther Bakken ssb stig@php.net no Tomas V.V.Cox cox cox@php.net no 2010-10-26 1.3.4 1.3.0 stable stable BSD License Remove package.php from release 4.2.0 1.4.0b1 PEAR pear.php.net 1.1.0beta1 1.1.0beta1 beta beta 2004-04-16 PHP License - Fixed memory leaks parsing many documents or big files (mroch) - Fixed setInput() url detection regex (mroch) - Added setInputString() method, allowing strings to be passed as input (schst) - Error handling rewritten (cox) - Increased the overall parsing speed (cox) - Added free() method (schst - Added reset() method, that is called when parsing a document so it is possible to parse more than one document per instance (schst) - Added error codes (schst) - revamped documentation (cox, schst) - Fixed bug #516 (url fopen and safe mode) (schst) - Fixed bug #637 (dependency on PEAR) (schst) - improved parse() and parseString() to be able to parse more than one document (schst) - added PHP5 constructor (schst) - moved xml_parser_create() to _create() for PHP5 compatibility (schst) - added dependency on PHP 4.2 Thanks to Marshall Roch for commments and contributions and Tomas V.V. Cox for applying a lot of fixes and improvements. 1.1.0beta2 1.1.0beta2 beta beta 2004-04-18 PHP License beta2: - Fixed calling of __construct beta1: - Fixed memory leaks parsing many documents or big files (mroch) - Fixed setInput() url detection regex (mroch) - Added setInputString() method, allowing strings to be passed as input (schst) - Error handling rewritten (cox) - Increased the overall parsing speed (cox) - Added free() method (schst - Added reset() method, that is called when parsing a document so it is possible to parse more than one document per instance (schst) - Added error codes (schst) - revamped documentation (cox, schst) - Fixed bug #516 (url fopen and safe mode) (schst) - Fixed bug #637 (dependency on PEAR) (schst) - improved parse() and parseString() to be able to parse more than one document (schst) - added PHP5 constructor (schst) - moved xml_parser_create() to _create() for PHP5 compatibility (schst) - added dependency on PHP 4.2 Thanks to Marshall Roch for commments and contributions and Tomas V.V. Cox for applying a lot of fixes and improvements. 1.1.0 1.1.0 stable stable 2004-04-23 PHP License - Fixed memory leaks parsing many documents or big files (mroch) - Fixed setInput() url detection regex (mroch) - Added setInputString() method, allowing strings to be passed as input (schst) - Error handling rewritten (cox) - Increased the overall parsing speed (cox) - Added free() method (schst - Added reset() method, that is called when parsing a document so it is possible to parse more than one document per instance (schst) - Added error codes (schst) - revamped documentation (cox, schst) - Fixed bug #516 (url fopen and safe mode) (schst) - Fixed bug #637 (dependency on PEAR) (schst) - improved parse() and parseString() to be able to parse more than one document (schst) - added PHP5 constructor (schst) - moved xml_parser_create() to _create() for PHP5 compatibility (schst) - added dependency on PHP 4.2 Thanks to Marshall Roch for commments and contributions and Tomas V.V. Cox for applying a lot of fixes and improvements. 1.2.0beta1 1.2.0beta1 beta beta 2004-05-17 PHP License added new class XML_Parser_Simple that provides a stack for the elements so the user only needs to implement one method to handle the tag and cdata. 1.2.0beta2 1.2.0beta2 beta beta 2004-05-24 PHP License XML_Parser: - fixed bug with setMode() - moved the init routines for the handlers in _initHandlers() XML_Parser_Simple: - fixed bug with character data (did not get parsed) - fixed bug with setMode() - some refactoring - added getCurrentDepth() to retrieve the tag depth - added addToData() - added new example 1.2.0beta3 1.2.0beta3 beta beta 2004-05-25 PHP License - added setHandlerObj() which allows you to have the parser separate from the handler methods 1.2.0 1.2.0 stable stable 2004-05-28 PHP License - added setHandlerObj() which allows you to have the parser separate from the handler methods - fixed bug with setMode() - moved the init routines for the handlers in _initHandlers() - added new examples - fixed test files so they do not fail because of different resource ids XML_Parser_Simple: - added new class XML_Parser_Simple that provides a stack for the elements so the user only needs to implement one method to handle the tag and cdata. 1.2.1 1.2.1 stable stable 2004-10-04 PHP License fixed bug #2442: Call to "xmltag_ELEMENT_" not correctly managed in function funcEndHandler 1.2.2beta1 1.2.2beta1 beta beta 2004-12-22 PHP License - fixed small notice in XML_Parser::free(), - fixed Bug #2939: bug in error routine leads to segmentation fault (raiseError does not free the internal resources anymore) 1.2.2 1.2.2 stable stable 2004-12-22 PHP License - fixed small notice in XML_Parser::free(), - fixed Bug #2939: bug in error routine leads to segmentation fault (raiseError does not free the internal resources anymore) 1.2.3 1.2.3 stable stable 2005-01-17 PHP License - fixed a bug that occured when using 'func' mode and setHandlerObj() (schst) - added default handlers for 'func' mode (schst) 1.2.4 1.2.4 stable stable 2005-01-18 PHP License - fixed a bug in XML_Parser_Simple when trying to register more than the default handlers and a separate callback object (schst) 1.2.5 1.2.5 stable stable 2005-02-26 PHP License - fixed Bug #3557 (removed $attribs parameter, which caused a notice) - fixed Bug #3277 (remove obsolete ini_set('allow_url_fopen')) 1.2.6 1.2.6 stable stable 2005-03-25 PHP License - fixed Bug #3949: reset does not return true on success as the documentation states - implement Request #3905: replace "." with "_" in tagnames when using func mode 1.2.7 1.2.7 stable stable 2005-09-24 PHP License - implemented request #4774: Error message contains column number 1.2.8 1.2.8 stable stable 2006-12-01 PHP License - fixed bug #5557: Raise a more useful error message when using invalid source encoding - fixed bug #6078: func-mode does not handle all allowed letters in tags 1.3.0a1 1.3.0a1 alpha alpha 2008-08-24 PHP License - switch to BSD License - switch to package.xml v2 - PEAR CS cleanup - Fix Doc #13120: Mistake in example code 1.3.0 1.3.0 stable stable 2008-08-24 PHP License - switch to BSD License - switch to package.xml v2 - PEAR CS cleanup - Fix Doc #13120: Mistake in example code 1.3.1 1.3.0 stable stable 2008-09-15 BSD License - correct package.xml to reflect switch to BSD License 1.3.2 1.3.0 stable stable 2009-01-21 BSD License - Fix Bug #9328: assigned by reference error in XML_RSS parse - add an AllTests.php for PHPUnit usage 1.3.3 1.3.0 stable stable 2010-10-25 BSD License Automatically built QA release Bug #16467 Unit tests are broken - ashnazg Bug #17725 Patch Avoid deprecated eregi functions - olleolleolle 1.3.4 1.3.0 stable stable 2010-10-26 BSD License Remove package.php from release XML_Parser-1.3.4/examples/xml_parser_file.php0000600000175000017500000000203211461312050021737 0ustar clockwerxclockwerx * @package XML_Parser * @subpackage Examples */ /** * require the parser */ require_once 'XML/Parser.php'; class myParser extends XML_Parser { function myParser() { parent::XML_Parser(); } /** * handle start element * * @access private * @param resource xml parser resource * @param string name of the element * @param array attributes */ function startHandler($xp, $name, $attribs) { printf('handle start tag: %s
', $name); } /** * handle start element * * @access private * @param resource xml parser resource * @param string name of the element * @param array attributes */ function endHandler($xp, $name) { printf('handle end tag: %s
', $name); } } $p = &new myParser(); $result = $p->setInputFile('xml_parser_file.xml'); $result = $p->parse(); ?>XML_Parser-1.3.4/examples/xml_parser_file.xml0000600000175000017500000000012711461312050021753 0ustar clockwerxclockwerx content of bar test XML_Parser-1.3.4/examples/xml_parser_funcmode.php0000600000175000017500000000155311461312050022627 0ustar clockwerxclockwerx * @package XML_Parser * @subpackage Examples */ /** * require the parser */ require_once '../Parser.php'; class myParser extends XML_Parser { function xmltag_foo_bar($xp, $name, $attribs) { print "handle start foo-bar\n"; } function xmltag_foo_bar_($xp, $name) { print "handle end foo-bar\n"; } function xmltag_foo($xp, $name) { print "handle start foo\n"; } function xmltag_foo_($xp, $name) { print "handle end foo\n"; } } $p = &new myParser(null, 'func'); $result = $p->setInputString(''); if (PEAR::isError($result)) { print $result->getMessage() . "\n"; } $result = $p->parse(); if (PEAR::isError($result)) { print $result->getMessage() . "\n"; } ?>XML_Parser-1.3.4/examples/xml_parser_handler.php0000600000175000017500000000177611461312050022453 0ustar clockwerxclockwerx * @package XML_Parser * @subpackage Examples */ /** * require the parser */ require_once 'XML/Parser.php'; class myHandler { /** * handle start element * * @access private * @param resource xml parser resource * @param string name of the element * @param array attributes */ function startHandler($xp, $name, $attribs) { printf('handle start tag: %s
', $name); } /** * handle start element * * @access private * @param resource xml parser resource * @param string name of the element * @param array attributes */ function endHandler($xp, $name) { printf('handle end tag: %s
', $name); } } $p = &new XML_Parser(); $h = &new myHandler(); $result = $p->setInputFile('xml_parser_file.xml'); $result = $p->setHandlerObj($h); $result = $p->parse(); ?>XML_Parser-1.3.4/examples/xml_parser_simple1.php0000600000175000017500000000216411461312050022400 0ustar clockwerxclockwerx * @package XML_Parser * @subpackage Examples */ /** * require the parser */ require_once 'XML/Parser/Simple.php'; class myParser extends XML_Parser_Simple { function myParser() { $this->XML_Parser_Simple(); } /** * handle the element * * The element will be handled, once it's closed * * @access private * @param string name of the element * @param array attributes of the element * @param string character data of the element */ function handleElement($name, $attribs, $data) { printf('handling %s in tag depth %d
', $name, $this->getCurrentDepth()); printf('character data: %s
', $data ); print 'Attributes:
'; print '
';
        print_r( $attribs );
        print '
'; print '
'; } } $p = &new myParser(); $result = $p->setInputFile('xml_parser_simple1.xml'); $result = $p->parse(); ?>XML_Parser-1.3.4/examples/xml_parser_simple1.xml0000600000175000017500000000031711461312050022407 0ustar clockwerxclockwerx content of bar test pizza XML_Parser-1.3.4/examples/xml_parser_simple2.php0000600000175000017500000000252211461312050022377 0ustar clockwerxclockwerx * @package XML_Parser * @subpackage Examples */ /** * require the parser */ require_once 'XML/Parser/Simple.php'; class myParser2 extends XML_Parser_Simple { function myParser() { $this->XML_Parser_Simple(); } /** * handle the category element * * The element will be handled, once it's closed * * @access private * @param string name of the element * @param array attributes of the element * @param string character data of the element */ function handleElement_category($name, $attribs, $data) { printf( 'Category is %s
', $data ); } /** * handle the name element * * The element will be handled, once it's closed * * @access private * @param string name of the element * @param array attributes of the element * @param string character data of the element */ function handleElement_name($name, $attribs, $data) { printf( 'Name is %s
', $data ); } } $p = &new myParser2(); $result = $p->setInputFile('xml_parser_simple2.xml'); $p->setMode('func'); $result = $p->parse(); ?>XML_Parser-1.3.4/examples/xml_parser_simple2.xml0000600000175000017500000000023011461312050022402 0ustar clockwerxclockwerx XML XML_Parser XML_Parser-1.3.4/examples/xml_parser_simple_handler.php0000600000175000017500000000247011461312050024014 0ustar clockwerxclockwerx * @package XML_Parser * @subpackage Examples */ /** * require the parser */ require_once 'XML/Parser/Simple.php'; class myHandlerSimple { /** * handle the category element * * The element will be handled, once it's closed * * @access private * @param string name of the element * @param array attributes of the element * @param string character data of the element */ function handleElement_category($name, $attribs, $data) { printf( 'Category is %s
', $data ); } /** * handle the name element * * The element will be handled, once it's closed * * @access private * @param string name of the element * @param array attributes of the element * @param string character data of the element */ function handleElement_name($name, $attribs, $data) { printf( 'Name is %s
', $data ); } } $p = &new XML_Parser_Simple(); $h = &new myHandlerSimple(); $p->setHandlerObj($h); $result = $p->setInputFile('xml_parser_simple2.xml'); $p->setMode('func'); $result = $p->parse(); ?>XML_Parser-1.3.4/Parser/Simple.php0000600000175000017500000002155511461312050017446 0ustar clockwerxclockwerx * @copyright 2004-2008 Stephan Schmidt * @license http://opensource.org/licenses/bsd-license New BSD License * @version CVS: $Id: Simple.php 265444 2008-08-24 21:48:21Z ashnazg $ * @link http://pear.php.net/package/XML_Parser */ /** * built on XML_Parser */ require_once 'XML/Parser.php'; /** * Simple XML parser class. * * This class is a simplified version of XML_Parser. * In most XML applications the real action is executed, * when a closing tag is found. * * XML_Parser_Simple allows you to just implement one callback * for each tag that will receive the tag with its attributes * and CData. * * * require_once '../Parser/Simple.php'; * * class myParser extends XML_Parser_Simple * { * function myParser() * { * $this->XML_Parser_Simple(); * } * * function handleElement($name, $attribs, $data) * { * printf('handle %s
', $name); * } * } * * $p = &new myParser(); * * $result = $p->setInputFile('myDoc.xml'); * $result = $p->parse(); *
* * @category XML * @package XML_Parser * @author Stephan Schmidt * @copyright 2004-2008 The PHP Group * @license http://opensource.org/licenses/bsd-license New BSD License * @version Release: @package_version@ * @link http://pear.php.net/package/XML_Parser */ class XML_Parser_Simple extends XML_Parser { /** * element stack * * @access private * @var array */ var $_elStack = array(); /** * all character data * * @access private * @var array */ var $_data = array(); /** * element depth * * @access private * @var integer */ var $_depth = 0; /** * Mapping from expat handler function to class method. * * @var array */ var $handler = array( 'default_handler' => 'defaultHandler', 'processing_instruction_handler' => 'piHandler', 'unparsed_entity_decl_handler' => 'unparsedHandler', 'notation_decl_handler' => 'notationHandler', 'external_entity_ref_handler' => 'entityrefHandler' ); /** * Creates an XML parser. * * This is needed for PHP4 compatibility, it will * call the constructor, when a new instance is created. * * @param string $srcenc source charset encoding, use NULL (default) to use * whatever the document specifies * @param string $mode how this parser object should work, "event" for * handleElement(), "func" to have it call functions * named after elements (handleElement_$name()) * @param string $tgtenc a valid target encoding */ function XML_Parser_Simple($srcenc = null, $mode = 'event', $tgtenc = null) { $this->XML_Parser($srcenc, $mode, $tgtenc); } /** * inits the handlers * * @return mixed * @access private */ function _initHandlers() { if (!is_object($this->_handlerObj)) { $this->_handlerObj = &$this; } if ($this->mode != 'func' && $this->mode != 'event') { return $this->raiseError('Unsupported mode given', XML_PARSER_ERROR_UNSUPPORTED_MODE); } xml_set_object($this->parser, $this->_handlerObj); xml_set_element_handler($this->parser, array(&$this, 'startHandler'), array(&$this, 'endHandler')); xml_set_character_data_handler($this->parser, array(&$this, 'cdataHandler')); /** * set additional handlers for character data, entities, etc. */ foreach ($this->handler as $xml_func => $method) { if (method_exists($this->_handlerObj, $method)) { $xml_func = 'xml_set_' . $xml_func; $xml_func($this->parser, $method); } } } /** * Reset the parser. * * This allows you to use one parser instance * to parse multiple XML documents. * * @access public * @return boolean|object true on success, PEAR_Error otherwise */ function reset() { $this->_elStack = array(); $this->_data = array(); $this->_depth = 0; $result = $this->_create(); if ($this->isError($result)) { return $result; } return true; } /** * start handler * * Pushes attributes and tagname onto a stack * * @param resource $xp xml parser resource * @param string $elem element name * @param array &$attribs attributes * * @return mixed * @access private * @final */ function startHandler($xp, $elem, &$attribs) { array_push($this->_elStack, array( 'name' => $elem, 'attribs' => $attribs )); $this->_depth++; $this->_data[$this->_depth] = ''; } /** * end handler * * Pulls attributes and tagname from a stack * * @param resource $xp xml parser resource * @param string $elem element name * * @return mixed * @access private * @final */ function endHandler($xp, $elem) { $el = array_pop($this->_elStack); $data = $this->_data[$this->_depth]; $this->_depth--; switch ($this->mode) { case 'event': $this->_handlerObj->handleElement($el['name'], $el['attribs'], $data); break; case 'func': $func = 'handleElement_' . $elem; if (strchr($func, '.')) { $func = str_replace('.', '_', $func); } if (method_exists($this->_handlerObj, $func)) { call_user_func(array(&$this->_handlerObj, $func), $el['name'], $el['attribs'], $data); } break; } } /** * handle character data * * @param resource $xp xml parser resource * @param string $data data * * @return void * @access private * @final */ function cdataHandler($xp, $data) { $this->_data[$this->_depth] .= $data; } /** * handle a tag * * Implement this in your parser * * @param string $name element name * @param array $attribs attributes * @param string $data character data * * @return void * @access public * @abstract */ function handleElement($name, $attribs, $data) { } /** * get the current tag depth * * The root tag is in depth 0. * * @access public * @return integer */ function getCurrentDepth() { return $this->_depth; } /** * add some string to the current ddata. * * This is commonly needed, when a document is parsed recursively. * * @param string $data data to add * * @return void * @access public */ function addToData($data) { $this->_data[$this->_depth] .= $data; } } ?> XML_Parser-1.3.4/tests/001.phpt0000600000175000017500000000243311461312050016601 0ustar clockwerxclockwerx--TEST-- XML Parser: parse simple string --SKIPIF-- --FILE-- XML_Parser(); } function startHandler($xp, $element, $attribs) { print "<$element"; reset($attribs); while (list($key, $val) = each($attribs)) { $enc = htmlentities($val); print " $key=\"$enc\""; } print ">"; } function endHandler($xp, $element) { print "\n"; } function cdataHandler($xp, $cdata) { print ""; } function defaultHandler($xp, $cdata) { } } error_reporting(1023); print "new __TestParser1 "; var_dump(strtolower(get_class($o = new __TestParser1()))); print "parseString "; var_dump($o->parseString("foo", 1)); ?> --EXPECT-- new __TestParser1 string(13) "__testparser1" parseString bool(true) XML_Parser-1.3.4/tests/002.phpt0000600000175000017500000000245311461312050016604 0ustar clockwerxclockwerx--TEST-- XML Parser: parse from file --SKIPIF-- --FILE-- XML_Parser(); } function startHandler($xp, $element, $attribs) { print "<$element"; reset($attribs); while (list($key, $val) = each($attribs)) { $enc = htmlentities($val); print " $key=\"$enc\""; } print ">"; } function endHandler($xp, $element) { print "\n"; } function cdataHandler($xp, $cdata) { print ""; } function defaultHandler($xp, $cdata) { } } print "new __TestParser2 "; var_dump(strtolower(get_class($o = new __TestParser2()))); print "setInputFile "; print is_resource($o->setInputFile("test2.xml"))."\n"; print "parse "; var_dump($o->parse()); ?> --EXPECT-- new __TestParser2 string(13) "__testparser2" setInputFile 1 parse bool(true) XML_Parser-1.3.4/tests/003.phpt0000600000175000017500000000256311461312050016607 0ustar clockwerxclockwerx--TEST-- XML Parser: parse from file resource --SKIPIF-- --FILE-- XML_Parser(); } function startHandler($xp, $element, $attribs) { print "<$element"; reset($attribs); while (list($key, $val) = each($attribs)) { $enc = htmlentities($val); print " $key=\"$enc\""; } print ">"; } function endHandler($xp, $element) { print "\n"; } function cdataHandler($xp, $cdata) { print ""; } function defaultHandler($xp, $cdata) { } } print "new __TestParser3 "; var_dump(strtolower(get_class($o = new __TestParser3()))); print "fopen "; print is_resource($fp = fopen("test3.xml", "r"))."\n"; print "setInput "; var_dump($o->setInput($fp)); print "parse "; var_dump($o->parse()); ?> --EXPECT-- new __TestParser3 string(13) "__testparser3" fopen 1 setInput bool(true) parse bool(true) XML_Parser-1.3.4/tests/004.phpt0000600000175000017500000000126611461312050016607 0ustar clockwerxclockwerx--TEST-- XML Parser: error class (PHP4 behavior) --SKIPIF-- --FILE-- parseString("\n", true); if (PEAR::isError($e)) { printf("Error message: %s" . PHP_EOL, $e->getMessage()); } else { print "No error" . PHP_EOL; } ?> --EXPECT-- New XML_Parser: string(10) "xml_parser" Error message: XML_Parser: mismatched tag at XML input line 2:7 XML_Parser-1.3.4/tests/004b.phpt0000600000175000017500000000126711461312050016752 0ustar clockwerxclockwerx--TEST-- XML Parser: error class (PHP5 behavior) --SKIPIF-- --FILE-- parseString("\n", true); if (PEAR::isError($e)) { printf("Error message: %s" . PHP_EOL, $e->getMessage()); } else { print "No error" . PHP_EOL; } ?> --EXPECT-- New XML_Parser: string(10) "xml_parser" Error message: XML_Parser: Mismatched tag at XML input line 2:12 XML_Parser-1.3.4/tests/005.phpt0000600000175000017500000000441211461312050016604 0ustar clockwerxclockwerx--TEST-- XML Parser: mixing character encodings --SKIPIF-- --FILE-- ISO-8859-1 * 2 UTF-8 -> US-ASCII * 3 ISO-8859-1 -> UTF-8 * 4 ISO-8859-1 -> US-ASCII * 5 US-ASCII -> UTF-8 * 6 US-ASCII -> ISO-8859-1 */ require_once 'XML/Parser.php'; class TestEncodings1 extends XML_Parser { var $output = ''; function TestEncodings1($to, $mode, $from) { $this->XML_Parser($from, $mode, $to); } function startHandler($xp, $elem, $attribs) { $this->output .= "<$elem>"; } function endHandler($xp, $elem) { $this->output .= ""; } function cdataHandler($xp, $data) { $this->output .= $data; } function test($data) { $result = $this->parseString($data, true); if (PEAR::isError($result)) { return $result; } } } $xml = ""; $input = array( "UTF-8" => "abcæøå", /* are these special chars allowed in ISO-8859-1 context??? */ "ISO-8859-1" => "abc���", // "ISO-8859-1" => "abc�", "US-ASCII" => "abcaoa" ); $encodings = array_keys($input); foreach ($input as $srcenc => $string) { foreach ($encodings as $tgtenc) { if ($srcenc == $tgtenc) { continue; } print "Testing $srcenc -> $tgtenc: "; $p =& new TestEncodings1($tgtenc, 'event', $srcenc); $e = $p->test($input[$srcenc]); if (PEAR::isError($e)) { printf("OOPS: %s\n", $e->getMessage()); } else { var_dump($p->output); } } } ?> --EXPECT-- Testing UTF-8 -> ISO-8859-1: string(13) "abc���" Testing UTF-8 -> US-ASCII: string(13) "abc???" Testing ISO-8859-1 -> UTF-8: string(16) "abcæøå" Testing ISO-8859-1 -> US-ASCII: string(13) "abc???" Testing US-ASCII -> UTF-8: string(13) "abcaoa" Testing US-ASCII -> ISO-8859-1: string(13) "abcaoa" XML_Parser-1.3.4/tests/AllTests.php0000600000175000017500000000710611461312050017652 0ustar clockwerxclockwerx * @license http://www.opensource.org/licenses/bsd-license.php New BSD License * @version CVS: $Id: AllTests.php 274147 2009-01-22 00:23:26Z ashnazg $ * @link http://pear.php.net/package/XML_Parser * @since 1.3.2 */ /** * Check PHP version... PhpUnit v3+ requires at least PHP v5.1.4 */ if (version_compare(PHP_VERSION, "5.1.4") < 0) { // Cannnot run test suites echo 'Cannot run test suite via PhpUnit... requires at least PHP v5.1.4.' . PHP_EOL; echo 'Use "pear run-tests -p xml_util" to run the PHPT tests directly.' . PHP_EOL ; exit(1); } /** * Derive the "main" method name * @internal PhpUnit would have to rename PHPUnit_MAIN_METHOD to PHPUNIT_MAIN_METHOD * to make this usage meet the PEAR CS... we cannot rename it here. */ if (!defined('PHPUnit_MAIN_METHOD')) { define('PHPUnit_MAIN_METHOD', 'XML_Parser_AllTests::main'); } /* * Files needed by PhpUnit */ require_once 'PHPUnit/Framework.php'; require_once 'PHPUnit/TextUI/TestRunner.php'; require_once 'PHPUnit/Extensions/PhptTestSuite.php'; /* * You must add each additional class-level test suite file here */ // there are no PhpUnit test files... only PHPTs.. so nothing is listed here /** * directory where PHPT tests are located */ define('XML_PARSER_DIR_PHPT', dirname(__FILE__)); /** * Master Unit Test Suite class for XML_Parser * * This top-level test suite class organizes * all class test suite files, * so that the full suite can be run * by PhpUnit or via "pear run-tests -up xml_util". * * @category XML * @package XML_Parser * @subpackage UnitTesting * @author Chuck Burgess * @license http://www.opensource.org/licenses/bsd-license.php New BSD License * @version Release: @package_version@ * @link http://pear.php.net/package/XML_Parser * @since 1.2.0a1 */ class XML_Parser_AllTests { /** * Launches the TextUI test runner * * @return void * @uses PHPUnit_TextUI_TestRunner */ public static function main() { PHPUnit_TextUI_TestRunner::run(self::suite()); } /** * Adds all class test suites into the master suite * * @return PHPUnit_Framework_TestSuite a master test suite * containing all class test suites * @uses PHPUnit_Framework_TestSuite */ public static function suite() { $suite = new PHPUnit_Framework_TestSuite( 'XML_Parser Full Suite of Unit Tests'); /* * You must add each additional class-level test suite name here */ // there are no PhpUnit test files... only PHPTs.. so nothing is listed here /* * add PHPT tests */ $phpt = new PHPUnit_Extensions_PhptTestSuite(XML_PARSER_DIR_PHPT); $suite->addTestSuite($phpt); return $suite; } } /** * Call the main method if this file is executed directly * @internal PhpUnit would have to rename PHPUnit_MAIN_METHOD to PHPUNIT_MAIN_METHOD * to make this usage meet the PEAR CS... we cannot rename it here. */ if (PHPUnit_MAIN_METHOD == 'XML_Parser_AllTests::main') { XML_Parser_AllTests::main(); } /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ ?> XML_Parser-1.3.4/tests/bug-9328.phpt0000600000175000017500000000150411461312050017457 0ustar clockwerxclockwerx--TEST-- XML Parser: test for Bug #9328 "assigned by reference error in XML_RSS parse" --SKIPIF-- --FILE-- parse(); echo $error->getMessage() . PHP_EOL; ?> --EXPECT-- XML_Parser: syntax error at XML input line 1:0 XML_Parser-1.3.4/tests/bug-9328b.phpt0000600000175000017500000000161711461312050017626 0ustar clockwerxclockwerx--TEST-- XML Parser: test for Bug #9328 "assigned by reference error in XML_RSS parse" --SKIPIF-- --FILE-- parse(); echo $error->getMessage() . PHP_EOL; ?> --EXPECT-- XML_Parser: Empty document at XML input line 1:1 XML_Parser-1.3.4/tests/bug-9328c.phpt0000600000175000017500000000162211461312050017623 0ustar clockwerxclockwerx--TEST-- XML Parser: test for Bug #9328 "assigned by reference error in XML_RSS parse" --SKIPIF-- --FILE-- parse(); echo $error->getMessage() . PHP_EOL; ?> --EXPECT-- XML_Parser: Invalid document end at XML input line 1:1 XML_Parser-1.3.4/tests/bug-9328d.phpt0000600000175000017500000000155011461312050017624 0ustar clockwerxclockwerx--TEST-- XML Parser: test for Bug #9328 "assigned by reference error in XML_RSS parse" --SKIPIF-- --FILE-- parse(); echo $error->getMessage() . PHP_EOL; ?> --EXPECT-- XML_Parser: Not well-formed (invalid token) at XML input line 1:1 XML_Parser-1.3.4/tests/test2.xml0000600000175000017500000000004711461312050017166 0ustar clockwerxclockwerx fooXML_Parser-1.3.4/tests/test3.xml0000600000175000017500000000004711461312050017167 0ustar clockwerxclockwerx fooXML_Parser-1.3.4/Parser.php0000600000175000017500000005140011461312050016205 0ustar clockwerxclockwerx * @author Tomas V.V.Cox * @author Stephan Schmidt * @copyright 2002-2008 The PHP Group * @license http://opensource.org/licenses/bsd-license New BSD License * @version CVS: $Id: Parser.php 302733 2010-08-24 01:09:09Z clockwerx $ * @link http://pear.php.net/package/XML_Parser */ /** * uses PEAR's error handling */ require_once 'PEAR.php'; /** * resource could not be created */ define('XML_PARSER_ERROR_NO_RESOURCE', 200); /** * unsupported mode */ define('XML_PARSER_ERROR_UNSUPPORTED_MODE', 201); /** * invalid encoding was given */ define('XML_PARSER_ERROR_INVALID_ENCODING', 202); /** * specified file could not be read */ define('XML_PARSER_ERROR_FILE_NOT_READABLE', 203); /** * invalid input */ define('XML_PARSER_ERROR_INVALID_INPUT', 204); /** * remote file cannot be retrieved in safe mode */ define('XML_PARSER_ERROR_REMOTE', 205); /** * XML Parser class. * * This is an XML parser based on PHP's "xml" extension, * based on the bundled expat library. * * Notes: * - It requires PHP 4.0.4pl1 or greater * - From revision 1.17, the function names used by the 'func' mode * are in the format "xmltag_$elem", for example: use "xmltag_name" * to handle the tags of your xml file. * - different parsing modes * * @category XML * @package XML_Parser * @author Stig Bakken * @author Tomas V.V.Cox * @author Stephan Schmidt * @copyright 2002-2008 The PHP Group * @license http://opensource.org/licenses/bsd-license New BSD License * @version Release: @package_version@ * @link http://pear.php.net/package/XML_Parser * @todo create XML_Parser_Namespace to parse documents with namespaces * @todo create XML_Parser_Pull * @todo Tests that need to be made: * - mixing character encodings * - a test using all expat handlers * - options (folding, output charset) */ class XML_Parser extends PEAR { // {{{ properties /** * XML parser handle * * @var resource * @see xml_parser_create() */ var $parser; /** * File handle if parsing from a file * * @var resource */ var $fp; /** * Whether to do case folding * * If set to true, all tag and attribute names will * be converted to UPPER CASE. * * @var boolean */ var $folding = true; /** * Mode of operation, one of "event" or "func" * * @var string */ var $mode; /** * Mapping from expat handler function to class method. * * @var array */ var $handler = array( 'character_data_handler' => 'cdataHandler', 'default_handler' => 'defaultHandler', 'processing_instruction_handler' => 'piHandler', 'unparsed_entity_decl_handler' => 'unparsedHandler', 'notation_decl_handler' => 'notationHandler', 'external_entity_ref_handler' => 'entityrefHandler' ); /** * source encoding * * @var string */ var $srcenc; /** * target encoding * * @var string */ var $tgtenc; /** * handler object * * @var object */ var $_handlerObj; /** * valid encodings * * @var array */ var $_validEncodings = array('ISO-8859-1', 'UTF-8', 'US-ASCII'); // }}} // {{{ php4 constructor /** * Creates an XML parser. * * This is needed for PHP4 compatibility, it will * call the constructor, when a new instance is created. * * @param string $srcenc source charset encoding, use NULL (default) to use * whatever the document specifies * @param string $mode how this parser object should work, "event" for * startelement/endelement-type events, "func" * to have it call functions named after elements * @param string $tgtenc a valid target encoding */ function XML_Parser($srcenc = null, $mode = 'event', $tgtenc = null) { XML_Parser::__construct($srcenc, $mode, $tgtenc); } // }}} // {{{ php5 constructor /** * PHP5 constructor * * @param string $srcenc source charset encoding, use NULL (default) to use * whatever the document specifies * @param string $mode how this parser object should work, "event" for * startelement/endelement-type events, "func" * to have it call functions named after elements * @param string $tgtenc a valid target encoding */ function __construct($srcenc = null, $mode = 'event', $tgtenc = null) { $this->PEAR('XML_Parser_Error'); $this->mode = $mode; $this->srcenc = $srcenc; $this->tgtenc = $tgtenc; } // }}} /** * Sets the mode of the parser. * * Possible modes are: * - func * - event * * You can set the mode using the second parameter * in the constructor. * * This method is only needed, when switching to a new * mode at a later point. * * @param string $mode mode, either 'func' or 'event' * * @return boolean|object true on success, PEAR_Error otherwise * @access public */ function setMode($mode) { if ($mode != 'func' && $mode != 'event') { $this->raiseError('Unsupported mode given', XML_PARSER_ERROR_UNSUPPORTED_MODE); } $this->mode = $mode; return true; } /** * Sets the object, that will handle the XML events * * This allows you to create a handler object independent of the * parser object that you are using and easily switch the underlying * parser. * * If no object will be set, XML_Parser assumes that you * extend this class and handle the events in $this. * * @param object &$obj object to handle the events * * @return boolean will always return true * @access public * @since v1.2.0beta3 */ function setHandlerObj(&$obj) { $this->_handlerObj = &$obj; return true; } /** * Init the element handlers * * @return mixed * @access private */ function _initHandlers() { if (!is_resource($this->parser)) { return false; } if (!is_object($this->_handlerObj)) { $this->_handlerObj = &$this; } switch ($this->mode) { case 'func': xml_set_object($this->parser, $this->_handlerObj); xml_set_element_handler($this->parser, array(&$this, 'funcStartHandler'), array(&$this, 'funcEndHandler')); break; case 'event': xml_set_object($this->parser, $this->_handlerObj); xml_set_element_handler($this->parser, 'startHandler', 'endHandler'); break; default: return $this->raiseError('Unsupported mode given', XML_PARSER_ERROR_UNSUPPORTED_MODE); break; } /** * set additional handlers for character data, entities, etc. */ foreach ($this->handler as $xml_func => $method) { if (method_exists($this->_handlerObj, $method)) { $xml_func = 'xml_set_' . $xml_func; $xml_func($this->parser, $method); } } } // {{{ _create() /** * create the XML parser resource * * Has been moved from the constructor to avoid * problems with object references. * * Furthermore it allows us returning an error * if something fails. * * NOTE: uses '@' error suppresion in this method * * @return bool|PEAR_Error true on success, PEAR_Error otherwise * @access private * @see xml_parser_create */ function _create() { if ($this->srcenc === null) { $xp = @xml_parser_create(); } else { $xp = @xml_parser_create($this->srcenc); } if (is_resource($xp)) { if ($this->tgtenc !== null) { if (!@xml_parser_set_option($xp, XML_OPTION_TARGET_ENCODING, $this->tgtenc) ) { return $this->raiseError('invalid target encoding', XML_PARSER_ERROR_INVALID_ENCODING); } } $this->parser = $xp; $result = $this->_initHandlers($this->mode); if ($this->isError($result)) { return $result; } xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, $this->folding); return true; } if (!in_array(strtoupper($this->srcenc), $this->_validEncodings)) { return $this->raiseError('invalid source encoding', XML_PARSER_ERROR_INVALID_ENCODING); } return $this->raiseError('Unable to create XML parser resource.', XML_PARSER_ERROR_NO_RESOURCE); } // }}} // {{{ reset() /** * Reset the parser. * * This allows you to use one parser instance * to parse multiple XML documents. * * @access public * @return boolean|object true on success, PEAR_Error otherwise */ function reset() { $result = $this->_create(); if ($this->isError($result)) { return $result; } return true; } // }}} // {{{ setInputFile() /** * Sets the input xml file to be parsed * * @param string $file Filename (full path) * * @return resource fopen handle of the given file * @access public * @throws XML_Parser_Error * @see setInput(), setInputString(), parse() */ function setInputFile($file) { /** * check, if file is a remote file */ if (preg_match('/^(http|ftp):\/\//i', substr($file, 0, 10))) { if (!ini_get('allow_url_fopen')) { return $this-> raiseError('Remote files cannot be parsed, as safe mode is enabled.', XML_PARSER_ERROR_REMOTE); } } $fp = @fopen($file, 'rb'); if (is_resource($fp)) { $this->fp = $fp; return $fp; } return $this->raiseError('File could not be opened.', XML_PARSER_ERROR_FILE_NOT_READABLE); } // }}} // {{{ setInputString() /** * XML_Parser::setInputString() * * Sets the xml input from a string * * @param string $data a string containing the XML document * * @return null */ function setInputString($data) { $this->fp = $data; return null; } // }}} // {{{ setInput() /** * Sets the file handle to use with parse(). * * You should use setInputFile() or setInputString() if you * pass a string * * @param mixed $fp Can be either a resource returned from fopen(), * a URL, a local filename or a string. * * @return mixed * @access public * @see parse() * @uses setInputString(), setInputFile() */ function setInput($fp) { if (is_resource($fp)) { $this->fp = $fp; return true; } elseif (preg_match('/^[a-z]+:\/\//i', substr($fp, 0, 10))) { // see if it's an absolute URL (has a scheme at the beginning) return $this->setInputFile($fp); } elseif (file_exists($fp)) { // see if it's a local file return $this->setInputFile($fp); } else { // it must be a string $this->fp = $fp; return true; } return $this->raiseError('Illegal input format', XML_PARSER_ERROR_INVALID_INPUT); } // }}} // {{{ parse() /** * Central parsing function. * * @return bool|PEAR_Error returns true on success, or a PEAR_Error otherwise * @access public */ function parse() { /** * reset the parser */ $result = $this->reset(); if ($this->isError($result)) { return $result; } // if $this->fp was fopened previously if (is_resource($this->fp)) { while ($data = fread($this->fp, 4096)) { if (!$this->_parseString($data, feof($this->fp))) { $error = &$this->raiseError(); $this->free(); return $error; } } } else { // otherwise, $this->fp must be a string if (!$this->_parseString($this->fp, true)) { $error = &$this->raiseError(); $this->free(); return $error; } } $this->free(); return true; } /** * XML_Parser::_parseString() * * @param string $data data * @param bool $eof end-of-file flag * * @return bool * @access private * @see parseString() **/ function _parseString($data, $eof = false) { return xml_parse($this->parser, $data, $eof); } // }}} // {{{ parseString() /** * XML_Parser::parseString() * * Parses a string. * * @param string $data XML data * @param boolean $eof If set and TRUE, data is the last piece * of data sent in this parser * * @return bool|PEAR_Error true on success or a PEAR Error * @throws XML_Parser_Error * @see _parseString() */ function parseString($data, $eof = false) { if (!isset($this->parser) || !is_resource($this->parser)) { $this->reset(); } if (!$this->_parseString($data, $eof)) { $error = &$this->raiseError(); $this->free(); return $error; } if ($eof === true) { $this->free(); } return true; } /** * XML_Parser::free() * * Free the internal resources associated with the parser * * @return null **/ function free() { if (isset($this->parser) && is_resource($this->parser)) { xml_parser_free($this->parser); unset( $this->parser ); } if (isset($this->fp) && is_resource($this->fp)) { fclose($this->fp); } unset($this->fp); return null; } /** * XML_Parser::raiseError() * * Throws a XML_Parser_Error * * @param string $msg the error message * @param integer $ecode the error message code * * @return XML_Parser_Error reference to the error object **/ function &raiseError($msg = null, $ecode = 0) { $msg = !is_null($msg) ? $msg : $this->parser; $err = &new XML_Parser_Error($msg, $ecode); return parent::raiseError($err); } // }}} // {{{ funcStartHandler() /** * derives and calls the Start Handler function * * @param mixed $xp ?? * @param mixed $elem ?? * @param mixed $attribs ?? * * @return void */ function funcStartHandler($xp, $elem, $attribs) { $func = 'xmltag_' . $elem; $func = str_replace(array('.', '-', ':'), '_', $func); if (method_exists($this->_handlerObj, $func)) { call_user_func(array(&$this->_handlerObj, $func), $xp, $elem, $attribs); } elseif (method_exists($this->_handlerObj, 'xmltag')) { call_user_func(array(&$this->_handlerObj, 'xmltag'), $xp, $elem, $attribs); } } // }}} // {{{ funcEndHandler() /** * derives and calls the End Handler function * * @param mixed $xp ?? * @param mixed $elem ?? * * @return void */ function funcEndHandler($xp, $elem) { $func = 'xmltag_' . $elem . '_'; $func = str_replace(array('.', '-', ':'), '_', $func); if (method_exists($this->_handlerObj, $func)) { call_user_func(array(&$this->_handlerObj, $func), $xp, $elem); } elseif (method_exists($this->_handlerObj, 'xmltag_')) { call_user_func(array(&$this->_handlerObj, 'xmltag_'), $xp, $elem); } } // }}} // {{{ startHandler() /** * abstract method signature for Start Handler * * @param mixed $xp ?? * @param mixed $elem ?? * @param mixed &$attribs ?? * * @return null * @abstract */ function startHandler($xp, $elem, &$attribs) { return null; } // }}} // {{{ endHandler() /** * abstract method signature for End Handler * * @param mixed $xp ?? * @param mixed $elem ?? * * @return null * @abstract */ function endHandler($xp, $elem) { return null; } // }}}me } /** * error class, replaces PEAR_Error * * An instance of this class will be returned * if an error occurs inside XML_Parser. * * There are three advantages over using the standard PEAR_Error: * - All messages will be prefixed * - check for XML_Parser error, using is_a( $error, 'XML_Parser_Error' ) * - messages can be generated from the xml_parser resource * * @category XML * @package XML_Parser * @author Stig Bakken * @author Tomas V.V.Cox * @author Stephan Schmidt * @copyright 2002-2008 The PHP Group * @license http://opensource.org/licenses/bsd-license New BSD License * @version Release: @package_version@ * @link http://pear.php.net/package/XML_Parser * @see PEAR_Error */ class XML_Parser_Error extends PEAR_Error { // {{{ properties /** * prefix for all messages * * @var string */ var $error_message_prefix = 'XML_Parser: '; // }}} // {{{ constructor() /** * construct a new error instance * * You may either pass a message or an xml_parser resource as first * parameter. If a resource has been passed, the last error that * happened will be retrieved and returned. * * @param string|resource $msgorparser message or parser resource * @param integer $code error code * @param integer $mode error handling * @param integer $level error level * * @access public * @todo PEAR CS - can't meet 85char line limit without arg refactoring */ function XML_Parser_Error($msgorparser = 'unknown error', $code = 0, $mode = PEAR_ERROR_RETURN, $level = E_USER_NOTICE) { if (is_resource($msgorparser)) { $code = xml_get_error_code($msgorparser); $msgorparser = sprintf('%s at XML input line %d:%d', xml_error_string($code), xml_get_current_line_number($msgorparser), xml_get_current_column_number($msgorparser)); } $this->PEAR_Error($msgorparser, $code, $mode, $level); } // }}} } ?>