source: temp/test-xoops.ec-cube.net/html/class/xml/saxparser.php @ 405

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