From c6b37dbee57263303ddaae9c40e7c61084588735 Mon Sep 17 00:00:00 2001 From: physikerwelt Date: Sun, 2 Jun 2013 17:24:32 +0000 Subject: [PATCH] Enhancement: Allow XmlTypeCheck for strings This change allows that the class XmlTypeCheck can be used to check strings as well as files. Therefore the constructor has been extended to one further element that indicates if the input to be checked is a file or a string. The functionality is tested with php unit tests. Change-Id: I7432a754a512e0324c171667c3eac9d8e7838e0e --- includes/XmlTypeCheck.php | 78 ++++++++++++++++++--- tests/phpunit/includes/XmlTypeCheckTest.php | 30 ++++++++ 2 files changed, 98 insertions(+), 10 deletions(-) create mode 100644 tests/phpunit/includes/XmlTypeCheckTest.php diff --git a/includes/XmlTypeCheck.php b/includes/XmlTypeCheck.php index 25dde7dd79..da2ff464d1 100644 --- a/includes/XmlTypeCheck.php +++ b/includes/XmlTypeCheck.php @@ -40,16 +40,52 @@ class XmlTypeCheck { public $rootElement = ''; /** - * @param string $file filename - * @param $filterCallback callable (optional) + * @param string $input a filename or string containing the XML element + * @param callable $filterCallback (optional) * Function to call to do additional custom validity checks from the * SAX element handler event. This gives you access to the element * namespace, name, and attributes, but not to text contents. * Filter should return 'true' to toggle on $this->filterMatch + * @param boolean $isFile (optional) indicates if the first parameter is a + * filename (default, true) or if it is a string (false) */ - function __construct( $file, $filterCallback = null ) { + function __construct( $input, $filterCallback = null, $isFile = true ) { $this->filterCallback = $filterCallback; - $this->run( $file ); + if ( $isFile ) { + $this->validateFromFile( $input ); + } else { + $this->validateFromString( $input ); + } + } + + /** + * Alternative constructor: from filename + * + * @param string $input a filename or string containing the XML element + * @param callable $filterCallback (optional) + * Function to call to do additional custom validity checks from the + * SAX element handler event. This gives you access to the element + * namespace, name, and attributes, but not to text contents. + * Filter should return 'true' to toggle on $this->filterMatch + * @return XmlTypeCheck + */ + public static function newFromFilename( $fname, $filterCallback = null ) { + return new self( $fname, $filterCallback, true ); + } + + /** + * Alternative constructor: from string + * + * @param string $input a filename or string containing the XML element + * @param callable $filterCallback (optional) + * Function to call to do additional custom validity checks from the + * SAX element handler event. This gives you access to the element + * namespace, name, and attributes, but not to text contents. + * Filter should return 'true' to toggle on $this->filterMatch + * @return XmlTypeCheck + */ + public static function newFromString( $string, $filterCallback = null ) { + return new self( $string, $filterCallback, false ); } /** @@ -62,15 +98,23 @@ class XmlTypeCheck { } /** - * @param $fname + * Get an XML parser with the root element handler. + * @see XmlTypeCheck::rootElementOpen() + * @return resource a resource handle for the XML parser */ - private function run( $fname ) { + private function getParser() { $parser = xml_parser_create_ns( 'UTF-8' ); - // case folding violates XML standard, turn it off xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, false ); - xml_set_element_handler( $parser, array( $this, 'rootElementOpen' ), false ); + return $parser; + } + + /** + * @param string $fname the filename + */ + private function validateFromFile( $fname ) { + $parser = $this->getParser(); if ( file_exists( $fname ) ) { $file = fopen( $fname, "rb" ); @@ -79,7 +123,7 @@ class XmlTypeCheck { $chunk = fread( $file, 32768 ); $ret = xml_parse( $parser, $chunk, feof( $file ) ); if ( $ret == 0 ) { - // XML isn't well-formed! + $this->wellFormed = false; fclose( $file ); xml_parser_free( $parser ); return; @@ -89,12 +133,26 @@ class XmlTypeCheck { fclose( $file ); } } - $this->wellFormed = true; xml_parser_free( $parser ); } + /** + * + * @param string $string the XML-input-string to be checked. + */ + private function validateFromString( $string ) { + $parser = $this->getParser(); + $ret = xml_parse( $parser, $string, true ); + xml_parser_free( $parser ); + if ( $ret == 0 ) { + $this->wellFormed = false; + return; + } + $this->wellFormed = true; + } + /** * @param $parser * @param $name diff --git a/tests/phpunit/includes/XmlTypeCheckTest.php b/tests/phpunit/includes/XmlTypeCheckTest.php new file mode 100644 index 0000000000..18f363fa7c --- /dev/null +++ b/tests/phpunit/includes/XmlTypeCheckTest.php @@ -0,0 +1,30 @@ +"; + const MAL_FORMED_XML = ""; + + /** + * @covers XMLTypeCheck::newFromString + * @covers XMLTypeCheck::getRootElement + */ + public function testWellFormedXML() { + $testXML = XmlTypeCheck::newFromString( self::WELL_FORMED_XML ); + $this->assertTrue( $testXML->wellFormed ); + $this->assertEquals( 'root', $testXML->getRootElement() ); + } + + /** + * @covers XMLTypeCheck::newFromString + */ + public function testMalFormedXML() { + $testXML = XmlTypeCheck::newFromString( self::MAL_FORMED_XML ); + $this->assertFalse( $testXML->wellFormed ); + } + +} \ No newline at end of file -- 2.20.1