Skip to content

Commit c6b37db

Browse files
physikerweltGerrit Code Review
authored andcommitted
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
1 parent 1fcf985 commit c6b37db

File tree

2 files changed

+98
-10
lines changed

2 files changed

+98
-10
lines changed

includes/XmlTypeCheck.php

Lines changed: 68 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,52 @@ class XmlTypeCheck {
4040
public $rootElement = '';
4141

4242
/**
43-
* @param string $file filename
44-
* @param $filterCallback callable (optional)
43+
* @param string $input a filename or string containing the XML element
44+
* @param callable $filterCallback (optional)
4545
* Function to call to do additional custom validity checks from the
4646
* SAX element handler event. This gives you access to the element
4747
* namespace, name, and attributes, but not to text contents.
4848
* Filter should return 'true' to toggle on $this->filterMatch
49+
* @param boolean $isFile (optional) indicates if the first parameter is a
50+
* filename (default, true) or if it is a string (false)
4951
*/
50-
function __construct( $file, $filterCallback = null ) {
52+
function __construct( $input, $filterCallback = null, $isFile = true ) {
5153
$this->filterCallback = $filterCallback;
52-
$this->run( $file );
54+
if ( $isFile ) {
55+
$this->validateFromFile( $input );
56+
} else {
57+
$this->validateFromString( $input );
58+
}
59+
}
60+
61+
/**
62+
* Alternative constructor: from filename
63+
*
64+
* @param string $input a filename or string containing the XML element
65+
* @param callable $filterCallback (optional)
66+
* Function to call to do additional custom validity checks from the
67+
* SAX element handler event. This gives you access to the element
68+
* namespace, name, and attributes, but not to text contents.
69+
* Filter should return 'true' to toggle on $this->filterMatch
70+
* @return XmlTypeCheck
71+
*/
72+
public static function newFromFilename( $fname, $filterCallback = null ) {
73+
return new self( $fname, $filterCallback, true );
74+
}
75+
76+
/**
77+
* Alternative constructor: from string
78+
*
79+
* @param string $input a filename or string containing the XML element
80+
* @param callable $filterCallback (optional)
81+
* Function to call to do additional custom validity checks from the
82+
* SAX element handler event. This gives you access to the element
83+
* namespace, name, and attributes, but not to text contents.
84+
* Filter should return 'true' to toggle on $this->filterMatch
85+
* @return XmlTypeCheck
86+
*/
87+
public static function newFromString( $string, $filterCallback = null ) {
88+
return new self( $string, $filterCallback, false );
5389
}
5490

5591
/**
@@ -62,15 +98,23 @@ public function getRootElement() {
6298
}
6399

64100
/**
65-
* @param $fname
101+
* Get an XML parser with the root element handler.
102+
* @see XmlTypeCheck::rootElementOpen()
103+
* @return resource a resource handle for the XML parser
66104
*/
67-
private function run( $fname ) {
105+
private function getParser() {
68106
$parser = xml_parser_create_ns( 'UTF-8' );
69-
70107
// case folding violates XML standard, turn it off
71108
xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, false );
72-
73109
xml_set_element_handler( $parser, array( $this, 'rootElementOpen' ), false );
110+
return $parser;
111+
}
112+
113+
/**
114+
* @param string $fname the filename
115+
*/
116+
private function validateFromFile( $fname ) {
117+
$parser = $this->getParser();
74118

75119
if ( file_exists( $fname ) ) {
76120
$file = fopen( $fname, "rb" );
@@ -79,7 +123,7 @@ private function run( $fname ) {
79123
$chunk = fread( $file, 32768 );
80124
$ret = xml_parse( $parser, $chunk, feof( $file ) );
81125
if ( $ret == 0 ) {
82-
// XML isn't well-formed!
126+
$this->wellFormed = false;
83127
fclose( $file );
84128
xml_parser_free( $parser );
85129
return;
@@ -89,12 +133,26 @@ private function run( $fname ) {
89133
fclose( $file );
90134
}
91135
}
92-
93136
$this->wellFormed = true;
94137

95138
xml_parser_free( $parser );
96139
}
97140

141+
/**
142+
*
143+
* @param string $string the XML-input-string to be checked.
144+
*/
145+
private function validateFromString( $string ) {
146+
$parser = $this->getParser();
147+
$ret = xml_parse( $parser, $string, true );
148+
xml_parser_free( $parser );
149+
if ( $ret == 0 ) {
150+
$this->wellFormed = false;
151+
return;
152+
}
153+
$this->wellFormed = true;
154+
}
155+
98156
/**
99157
* @param $parser
100158
* @param $name
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
/**
3+
* PHPUnit tests for XMLTypeCheck.
4+
* @author physikerwelt
5+
* @group ?
6+
* @covers XMLTypeCheck
7+
*/
8+
class XmlTypeCheckTest extends MediaWikiTestCase {
9+
const WELL_FORMED_XML = "<root><child /></root>";
10+
const MAL_FORMED_XML = "<root><child /></error>";
11+
12+
/**
13+
* @covers XMLTypeCheck::newFromString
14+
* @covers XMLTypeCheck::getRootElement
15+
*/
16+
public function testWellFormedXML() {
17+
$testXML = XmlTypeCheck::newFromString( self::WELL_FORMED_XML );
18+
$this->assertTrue( $testXML->wellFormed );
19+
$this->assertEquals( 'root', $testXML->getRootElement() );
20+
}
21+
22+
/**
23+
* @covers XMLTypeCheck::newFromString
24+
*/
25+
public function testMalFormedXML() {
26+
$testXML = XmlTypeCheck::newFromString( self::MAL_FORMED_XML );
27+
$this->assertFalse( $testXML->wellFormed );
28+
}
29+
30+
}

0 commit comments

Comments
 (0)