Completed
Push — master ( 3e5da4...d14e75 )
by Michael
12s
created

SaxParser::getXmlError()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 2
1
<?php
2
3
/**
4
 *
5
 * Location: xml/SaxParser.class
6
 *
7
 * Provides basic functionality to read and parse XML documents.  Subclasses
8
 * must implement all the their custom handlers by using add* function methods.
9
 * They may also use the handle*() methods to parse a specific XML begin and end
10
 * tags, but this is not recommended as it is more difficult.
11
 *
12
 * Copyright &copy; 2001 eXtremePHP.  All rights reserved.
13
 *
14
 * @author Ken Egervari
15
 */
16
17
class SaxParser
18
{
19
    public $level;
20
    public $parser;
21
22
    public $isCaseFolding;
23
    public $targetEncoding;
24
25
    /* Custom Handler Variables */
26
    public $tagHandlers = array();
27
28
    /* Tag stack */
29
    public $tags = array();
30
31
    /* Xml Source Input */
32
    public $xmlInput;
33
34
    public $errors = array();
35
36
    /**
37
     * Creates a SaxParser object using a FileInput to represent the stream
38
     * of XML data to parse.  Use the static methods createFileInput or
39
     * createStringInput to construct xml input source objects to supply
40
     * to the constructor, or the implementor can construct them individually.
41
     *
42
     * @param $input
43
     */
44 60
    public function __construct(&$input)
45
    {
46 60
        $this->level = 0;
47 60
        $this->parser = xml_parser_create('UTF-8');
48 60
        xml_set_object($this->parser, $this);
49 60
        $this->input = $input;
0 ignored issues
show
Bug introduced by
The property input does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
50 60
        $this->setCaseFolding(false);
51 60
        $this->useUtfEncoding();
52 60
        xml_set_element_handler($this->parser, 'handleBeginElement', 'handleEndElement');
53 60
        xml_set_character_data_handler($this->parser, 'handleCharacterData');
54 60
        xml_set_processing_instruction_handler($this->parser, 'handleProcessingInstruction');
55 60
        xml_set_default_handler($this->parser, 'handleDefault');
56 60
        xml_set_unparsed_entity_decl_handler($this->parser, 'handleUnparsedEntityDecl');
57 60
        xml_set_notation_decl_handler($this->parser, 'handleNotationDecl');
58 60
        xml_set_external_entity_ref_handler($this->parser, 'handleExternalEntityRef');
59 60
    }
60
61
    /*---------------------------------------------------------------------------
62
        Property Methods
63
    ---------------------------------------------------------------------------*/
64
65
    /**
66
     * @return int
67
     */
68 4
    public function getCurrentLevel()
69
    {
70 4
        return $this->level;
71
    }
72
73
    /**
74
     * @param boolean $isCaseFolding
75
     * @return void
76
     */
77 60
    public function setCaseFolding($isCaseFolding)
78
    {
79 60
        assert(is_bool($isCaseFolding));
80
81 60
        $this->isCaseFolding = $isCaseFolding;
82 60
        xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, $this->isCaseFolding);
83 60
    }
84
85
    /**
86
     * @return void
87
     */
88
    public function useIsoEncoding()
89
    {
90
        $this->targetEncoding = 'ISO-8859-1';
91
        xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->targetEncoding);
92
    }
93
94
    /**
95
     * @return void
96
     */
97
    public function useAsciiEncoding()
98
    {
99
        $this->targetEncoding = 'US-ASCII';
100
        xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->targetEncoding);
101
    }
102
103
    /**
104
     * @return void
105
     */
106 60
    public function useUtfEncoding()
107
    {
108 60
        $this->targetEncoding = 'UTF-8';
109 60
        xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->targetEncoding);
110 60
    }
111
112
    /**
113
     * Returns the name of the xml tag being parsed
114
     * @return string
115
     */
116
    public function getCurrentTag()
117
    {
118
        return $this->tags[count($this->tags) - 1];
119
    }
120
121 11
    public function getParentTag()
122
    {
123 11
        if (isset($this->tags[count($this->tags) - 2])) {
124 11
            return $this->tags[count($this->tags) - 2];
125
        }
126
        return false;
127
    }
128
129
130
    /*---------------------------------------------------------------------------
131
        Parser methods
132
    ---------------------------------------------------------------------------*/
133
134
    /**
135
     * @return bool
136
     */
137
    public function parse()
138
    {
139
        if (!is_resource($this->input)) {
140
            if (!xml_parse($this->parser, $this->input)) {
141
                $this->setErrors($this->getXmlError());
142
                return false;
143
            }
144
            //if (!$fp = fopen($this->input, 'r')) {
145
            //    $this->setErrors('Could not open file: '.$this->input);
146
            //    return false;
147
            //}
148
        } else {
149
            while ($data = fread($this->input, 4096)) {
150
                if (!xml_parse($this->parser, str_replace("'", "&apos;", $data), feof($this->input))) {
151
                    $this->setErrors($this->getXmlError());
152
                    fclose($this->input);
153
                    return false;
154
                }
155
            }
156
            fclose($this->input);
157
        }
158
        return true;
159
    }
160
161
    /**
162
     * @return void
163
     */
164
    public function free()
165
    {
166
        xml_parser_free($this->parser);
167
    }
168
169
    /**
170
     * @private
171
     * @return string
172
     */
173
    public function getXmlError()
174
    {
175
        return sprintf("XmlParse error: %s at line %d", xml_error_string(xml_get_error_code($this->parser)), xml_get_current_line_number($this->parser));
176
    }
177
178
    /*---------------------------------------------------------------------------
179
        Custom Handler Methods
180
    ---------------------------------------------------------------------------*/
181
182
    /**
183
     * Adds a callback function to be called when a tag is encountered.<br>
184
     * @param XmlTagHandler $tagHandler
185
     * @return void
186
     */
187 60
    public function addTagHandler(XmlTagHandler $tagHandler)
188
    {
189 60
        $name = $tagHandler->getName();
190 60
        if (is_array($name)) {
191 35
            foreach ($name as $n) {
192 35
                $this->tagHandlers[$n] = $tagHandler;
193
            }
194
        } else {
195 60
            $this->tagHandlers[$name] = $tagHandler;
196
        }
197 60
    }
198
199
200
    /*---------------------------------------------------------------------------
201
        Private Handler Methods
202
    ---------------------------------------------------------------------------*/
203
204
    /**
205
     * Callback function that executes whenever a the start of a tag
206
     * occurs when being parsed.
207
     * @param int    $parser          The handle to the parser.
208
     * @param string $tagName         The name of the tag currently being parsed.
209
     * @param array  $attributesArray The list of attributes associated with the tag.
210
     * @private
211
     * @return void
212
     */
213
    public function handleBeginElement($parser, $tagName, $attributesArray)
214
    {
215
        array_push($this->tags, $tagName);
216
        $this->level++;
217 View Code Duplication
        if (isset($this->tagHandlers[$tagName]) && is_subclass_of($this->tagHandlers[$tagName], 'xmltaghandler')) {
218
            $this->tagHandlers[$tagName]->handleBeginElement($this, $attributesArray);
219
        } else {
220
            $this->handleBeginElementDefault($parser, $tagName, $attributesArray);
221
        }
222
    }
223
224
    /**
225
     * Callback function that executes whenever the end of a tag
226
     * occurs when being parsed.
227
     * @param int    $parser  The handle to the parser.
228
     * @param string $tagName The name of the tag currently being parsed.
229
     * @private
230
     * @return void
231
     */
232
    public function handleEndElement($parser, $tagName)
233
    {
234
        array_pop($this->tags);
235 View Code Duplication
        if (isset($this->tagHandlers[$tagName]) && is_subclass_of($this->tagHandlers[$tagName], 'xmltaghandler')) {
236
            $this->tagHandlers[$tagName]->handleEndElement($this);
237
        } else {
238
            $this->handleEndElementDefault($parser, $tagName);
239
        }
240
        $this->level--;
241
    }
242
243
    /**
244
     * Callback function that executes whenever character data is encountered
245
     * while being parsed.
246
     * @param int    $parser The handle to the parser.
247
     * @param string $data   Character data inside the tag
248
     * @return void
249
     */
250
    public function handleCharacterData($parser, $data)
251
    {
252
        $tagHandler = isset($this->tagHandlers[$this->getCurrentTag()]) ? $this->tagHandlers[$this->getCurrentTag()] : null;
253
        if (null != $tagHandler && is_subclass_of($tagHandler, 'xmltaghandler')) {
254
            $tagHandler->handleCharacterData($this, $data);
255
        } else {
256
            $this->handleCharacterDataDefault($parser, $data);
257
        }
258
    }
259
260
    /**
261
     * @param int $parser The handle to the parser.
262
     * @param $target
263
     * @param $data
264
     * @return void
265
     */
266
    public function handleProcessingInstruction($parser, &$target, &$data)
0 ignored issues
show
Unused Code introduced by
The parameter $parser is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $target is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $data is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
267
    {
268
        //        if($target == 'php') {
269
        //            eval($data);
270
        //        }
271
    }
272
273
    /**
274
     * @param $parser
275
     * @param $data
276
     * @return void
277
     */
278
    public function handleDefault($parser, $data)
0 ignored issues
show
Unused Code introduced by
The parameter $parser is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $data is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
279
    {
280
281
    }
282
283
    /**
284
     * @param $parser
285
     * @param $entityName
286
     * @param $base
287
     * @param $systemId
288
     * @param $publicId
289
     * @param $notationName
290
     * @return void
291
     */
292
    public function handleUnparsedEntityDecl($parser, $entityName, $base, $systemId, $publicId, $notationName)
0 ignored issues
show
Unused Code introduced by
The parameter $parser is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $entityName is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $base is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $systemId is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $publicId is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $notationName is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
293
    {
294
295
    }
296
297
    /**
298
     * @param $parser
299
     * @param $notationName
300
     * @param $base
301
     * @param $systemId
302
     * @param $publicId
303
     * @return void
304
     */
305
    public function handleNotationDecl($parser, $notationName, $base, $systemId, $publicId)
0 ignored issues
show
Unused Code introduced by
The parameter $parser is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $notationName is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $base is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $systemId is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $publicId is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
306
    {
307
308
    }
309
310
    /**
311
     * @param $parser
312
     * @param $openEntityNames
313
     * @param $base
314
     * @param $systemId
315
     * @param $publicId
316
     * @return void
317
     */
318
    public function handleExternalEntityRef($parser, $openEntityNames, $base, $systemId, $publicId)
0 ignored issues
show
Unused Code introduced by
The parameter $parser is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $openEntityNames is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $base is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $systemId is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $publicId is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
319
    {
320
321
    }
322
323
    /**
324
     * The default tag handler method for a tag with no handler
325
     *
326
     * @param $parser
327
     * @param $tagName
328
     * @param $attributesArray
329
     * @return void
330
     */
331
    public function handleBeginElementDefault($parser, $tagName, $attributesArray)
0 ignored issues
show
Unused Code introduced by
The parameter $parser is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $tagName is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $attributesArray is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
332
    {
333
    }
334
335
    /**
336
     * The default tag handler method for a tag with no handler
337
     *
338
     * @param $parser
339
     * @param $tagName
340
     * @return void
341
     */
342
    public function handleEndElementDefault($parser, $tagName)
0 ignored issues
show
Unused Code introduced by
The parameter $parser is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $tagName is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
343
    {
344
    }
345
346
    /**
347
     * The default tag handler method for a tag with no handler
348
     *
349
     * @abstract
350
     *
351
     * @param $parser
352
     * @param $data
353
     * @return void
354
     */
355
    public function handleCharacterDataDefault($parser, $data)
0 ignored issues
show
Unused Code introduced by
The parameter $parser is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $data is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
356
    {
357
    }
358
359
    /**
360
     * Sets error messages
361
     *
362
     * @param    string $error    string    an error message
363
     */
364
    public function setErrors($error)
365
    {
366
        $this->errors[] = trim($error);
367
    }
368
369
    /**
370
     * Gets all the error messages
371
     *
372
     * @param bool $ashtml return as html?
373
     * @return mixed
374
     */
375
    public function getErrors($ashtml = true)
376
    {
377
        if (!$ashtml) {
378
            return $this->errors;
379
        } else {
380
            $ret = '';
381
            if (count($this->errors) > 0) {
382
                foreach ($this->errors as $error) {
383
                    $ret .= $error . '<br />';
384
                }
385
            }
386
            return $ret;
387
        }
388
    }
389
}
390