PageRenderTime 27ms CodeModel.GetById 13ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 0ms

/class/xml/saxparser.php

https://gitlab.com/VoyaTrax/vtCMS3
PHP | 392 lines | 319 code | 19 blank | 54 comment | 6 complexity | 1b8bbeea3c1d685a020ac2a1684bf145 MD5 | raw file
  1<?php
  2// $Id: saxparser.php 10761 2013-01-11 18:39:56Z trabis $
  3/*******************************************************************************
  4Location: <strong>xml/SaxParser.class</strong><br>
  5<br>
  6Provides basic functionality to read and parse XML documents.  Subclasses
  7must implement all the their custom handlers by using add* function methods.
  8They may also use the handle*() methods to parse a specific XML begin and end
  9tags, but this is not recommended as it is more difficult.<br>
 10<br>
 11Copyright &copy; 2001 eXtremePHP.  All rights reserved.<br>
 12<br>
 13@author Ken Egervari<br>
 14 *******************************************************************************/
 15
 16class SaxParser
 17{
 18    var $level;
 19    var $parser;
 20
 21    var $isCaseFolding;
 22    var $targetEncoding;
 23
 24    /* Custom Handler Variables */
 25    var $tagHandlers = array();
 26
 27    /* Tag stack */
 28    var $tags = array();
 29
 30    /* Xml Source Input */
 31    var $xmlInput;
 32
 33    var $errors = array();
 34
 35    /**
 36     * Creates a SaxParser object using a FileInput to represent the stream
 37     * of XML data to parse.  Use the static methods createFileInput or
 38     * createStringInput to construct xml input source objects to supply
 39     * to the constructor, or the implementor can construct them individually.
 40     *
 41     * @param $input
 42     */
 43    function __construct(&$input)
 44    {
 45        $this->level = 0;
 46        $this->parser = xml_parser_create('UTF-8');
 47        xml_set_object($this->parser, $this);
 48        $this->input = $input;
 49        $this->setCaseFolding(false);
 50        $this->useUtfEncoding();
 51        xml_set_element_handler($this->parser, 'handleBeginElement', 'handleEndElement');
 52        xml_set_character_data_handler($this->parser, 'handleCharacterData');
 53        xml_set_processing_instruction_handler($this->parser, 'handleProcessingInstruction');
 54        xml_set_default_handler($this->parser, 'handleDefault');
 55        xml_set_unparsed_entity_decl_handler($this->parser, 'handleUnparsedEntityDecl');
 56        xml_set_notation_decl_handler($this->parser, 'handleNotationDecl');
 57        xml_set_external_entity_ref_handler($this->parser, 'handleExternalEntityRef');
 58    }
 59
 60    /*---------------------------------------------------------------------------
 61        Property Methods
 62    ---------------------------------------------------------------------------*/
 63
 64    function getCurrentLevel()
 65    {
 66        return $this->level;
 67    }
 68
 69    /****************************************************************************
 70     * @param $isCaseFolding
 71     * @returns void
 72     ****************************************************************************/
 73    function setCaseFolding($isCaseFolding)
 74    {
 75        assert(is_bool($isCaseFolding));
 76
 77        $this->isCaseFolding = $isCaseFolding;
 78        xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, $this->isCaseFolding);
 79    }
 80
 81    /****************************************************************************
 82     * @returns void
 83     ****************************************************************************/
 84    function useIsoEncoding()
 85    {
 86        $this->targetEncoding = 'ISO-8859-1';
 87        xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->targetEncoding);
 88    }
 89
 90    /****************************************************************************
 91     * @returns void
 92     ****************************************************************************/
 93    function useAsciiEncoding()
 94    {
 95        $this->targetEncoding = 'US-ASCII';
 96        xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->targetEncoding);
 97    }
 98
 99    /****************************************************************************
100     * @returns void
101     ****************************************************************************/
102    function useUtfEncoding()
103    {
104        $this->targetEncoding = 'UTF-8';
105        xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->targetEncoding);
106    }
107
108    /****************************************************************************
109    Returns the name of the xml tag being parsed
110     * @returns string
111     ****************************************************************************/
112    function getCurrentTag()
113    {
114        return $this->tags[count($this->tags) - 1];
115    }
116
117    function getParentTag()
118    {
119        if (isset($this->tags[count($this->tags) - 2])) {
120            return $this->tags[count($this->tags) - 2];
121        }
122        return false;
123    }
124
125
126    /*---------------------------------------------------------------------------
127        Parser methods
128    ---------------------------------------------------------------------------*/
129
130    /**
131     * @return bool
132     */
133    function parse()
134    {
135        if (!is_resource($this->input)) {
136            if (!xml_parse($this->parser, $this->input)) {
137                $this->setErrors($this->getXmlError());
138                return false;
139            }
140            //if (!$fp = fopen($this->input, 'r')) {
141            //    $this->setErrors('Could not open file: '.$this->input);
142            //    return false;
143            //}
144        } else {
145            while ($data = fread($this->input, 4096)) {
146                if (!xml_parse($this->parser, str_replace("'", "&apos;", $data), feof($this->input))) {
147                    $this->setErrors($this->getXmlError());
148                    fclose($this->input);
149                    return false;
150                }
151            }
152            fclose($this->input);
153        }
154        return true;
155    }
156
157    /****************************************************************************
158     * @returns void
159     ****************************************************************************/
160    function free()
161    {
162        xml_parser_free($this->parser);
163
164        if (!method_exists($this, '__destruct')) {
165            unset($this);
166        } else {
167            $this->__destruct();
168        }
169    }
170
171    /**
172     * @private
173     * @return string
174     */
175    function getXmlError()
176    {
177        return sprintf("XmlParse error: %s at line %d", xml_error_string(xml_get_error_code($this->parser)), xml_get_current_line_number($this->parser));
178    }
179
180    /*---------------------------------------------------------------------------
181        Custom Handler Methods
182    ---------------------------------------------------------------------------*/
183
184    /**
185     * Adds a callback function to be called when a tag is encountered.<br>
186     * @param XmlTagHandler $tagHandler
187     * @return void
188     */
189    function addTagHandler(XmlTagHandler &$tagHandler)
190    {
191        $name = $tagHandler->getName();
192        if (is_array($name)) {
193            foreach ($name as $n) {
194                $this->tagHandlers[$n] = $tagHandler;
195            }
196        } else {
197            $this->tagHandlers[$name] = $tagHandler;
198        }
199    }
200
201
202    /*---------------------------------------------------------------------------
203        Private Handler Methods
204    ---------------------------------------------------------------------------*/
205
206    /****************************************************************************
207    Callback function that executes whenever a the start of a tag
208    occurs when being parsed.
209     * @param $parser int.  The handle to the parser.
210     * @param $tagName string.  The name of the tag currently being parsed.
211     * @param $attributesArray attay.  The list of attributes associated with
212    the tag.
213     * @private
214     * @returns void
215     ****************************************************************************/
216    function handleBeginElement($parser, $tagName, $attributesArray)
217    {
218        array_push($this->tags, $tagName);
219        $this->level++;
220        if (isset($this->tagHandlers[$tagName]) && is_subclass_of($this->tagHandlers[$tagName], 'xmltaghandler')) {
221            $this->tagHandlers[$tagName]->handleBeginElement($this, $attributesArray);
222        } else {
223            $this->handleBeginElementDefault($parser, $tagName, $attributesArray);
224        }
225    }
226
227    /****************************************************************************
228    Callback function that executes whenever the end of a tag
229    occurs when being parsed.
230     * @param $parser int.  The handle to the parser.
231     * @param $tagName string.  The name of the tag currently being parsed.
232     * @private
233     * @returns void
234     ****************************************************************************/
235    function handleEndElement($parser, $tagName)
236    {
237        array_pop($this->tags);
238        if (isset($this->tagHandlers[$tagName]) && is_subclass_of($this->tagHandlers[$tagName], 'xmltaghandler')) {
239            $this->tagHandlers[$tagName]->handleEndElement($this);
240        } else {
241            $this->handleEndElementDefault($parser, $tagName);
242        }
243        $this->level--;
244    }
245
246    /****************************************************************************
247    Callback function that executes whenever character data is encountered
248    while being parsed.
249     * @param $parser int.  The handle to the parser.
250     * @param $data string.  Character data inside the tag
251     * @returns void
252     ****************************************************************************/
253    function handleCharacterData($parser, $data)
254    {
255        $tagHandler = isset($this->tagHandlers[$this->getCurrentTag()]) ? $this->tagHandlers[$this->getCurrentTag()] : null;
256        if (null != $tagHandler && is_subclass_of($tagHandler, 'xmltaghandler')) {
257            $tagHandler->handleCharacterData($this, $data);
258        } else {
259            $this->handleCharacterDataDefault($parser, $data);
260        }
261    }
262
263    /**
264     * @param $parser int.  The handle to the parser.
265     * @param $target
266     * @param $data
267     * @return void
268     */
269    function handleProcessingInstruction($parser, &$target, &$data)
270    {
271        //        if($target == 'php') {
272        //            eval($data);
273        //        }
274    }
275
276    /**
277     * @param $parser
278     * @param $data
279     * @return void
280     */
281    function handleDefault($parser, $data)
282    {
283
284    }
285
286    /**
287     * @param $parser
288     * @param $entityName
289     * @param $base
290     * @param $systemId
291     * @param $publicId
292     * @param $notationName
293     * @return void
294     */
295    function handleUnparsedEntityDecl($parser, $entityName, $base, $systemId, $publicId, $notationName)
296    {
297
298    }
299
300    /**
301     * @param $parser
302     * @param $notationName
303     * @param $base
304     * @param $systemId
305     * @param $publicId
306     * @return void
307     */
308    function handleNotationDecl($parser, $notationName, $base, $systemId, $publicId)
309    {
310
311    }
312
313    /**
314     * @param $parser
315     * @param $openEntityNames
316     * @param $base
317     * @param $systemId
318     * @param $publicId
319     * @return void
320     */
321    function handleExternalEntityRef($parser, $openEntityNames, $base, $systemId, $publicId)
322    {
323
324    }
325
326    /**
327     * The default tag handler method for a tag with no handler
328     *
329     * @param $parser
330     * @param $tagName
331     * @param $attributesArray
332     * @return void
333     */
334    function handleBeginElementDefault($parser, $tagName, $attributesArray)
335    {
336    }
337
338    /**
339     * The default tag handler method for a tag with no handler
340     *
341     * @param $parser
342     * @param $tagName
343     * @return void
344     */
345    function handleEndElementDefault($parser, $tagName)
346    {
347    }
348
349    /**
350     * The default tag handler method for a tag with no handler
351     *
352     * @abstract
353     *
354     * @param $parser
355     * @param $data
356     * @return void
357     */
358    function handleCharacterDataDefault($parser, $data)
359    {
360    }
361
362    /**
363     * Sets error messages
364     *
365     * @param    $error    string    an error message
366     */
367    function setErrors($error)
368    {
369        $this->errors[] = trim($error);
370    }
371
372    /**
373     * Gets all the error messages
374     *
375     * @param    $ashtml    bool    return as html?
376     * @return    mixed
377     */
378    function getErrors($ashtml = true)
379    {
380        if (!$ashtml) {
381            return $this->errors;
382        } else {
383            $ret = '';
384            if (count($this->errors) > 0) {
385                foreach ($this->errors as $error) {
386                    $ret .= $error . '<br />';
387                }
388            }
389            return $ret;
390        }
391    }
392}