- fix issue outlined by Emmanuel Engelhart <emmanuel@engelhart.org> on wikitech-l
[mediawiki.git] / PHPTAL-NP-0.7.0 / libs / PHPTAL / XML_Parser.php
blob6ceca738dfe6b1f698d34125660ea415cae7dc9a
1 <?php
2 /* vim: set expandtab tabstop=4 shiftwidth=4: */
3 //
4 // Copyright (c) 2003 Laurent Bedubourg
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 //
20 // Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
21 //
23 require_once PT_IP . "/Types/Errors.php";
25 /**
26 * PHPTAL internal xml parser.
28 * Note:
30 * I didn't use the XML/Parser package because of reference problems due to
31 * call_user_func and call_user_method.
33 * This problem should vanished with automatic object referencing in php4.4
34 * (ZendEngine2) remind me to remove this parser at this time.
37 * This class uses "xml_*" php functions to parse xml data.
39 * To create a new xml parser, extends this class and implements following
40 * methods.
42 * - onElementStart($tag, $attributes)
43 * - onElementClose($tag)
44 * - onElementData($data)
45 * - onSpecific($data)
47 * Here's an exemple of xml parser implementation.
49 * <?php
50 * require_once PT_IP . "/PHPTAL/XML_Parser.php";
52 * class MyParser extends PHPTAL_XML_Parser
53 * {
54 * function onElementStart($tag, $attributes)
55 * {
56 * echo "new tag $tag with attributes :", endl;
57 * print_r($attributes);
58 * }
60 * function onElementClose($tag)
61 * {
62 * echo "tag ",$tag," is closed", endl;
63 * }
65 * function onElementData($data)
66 * {
67 * echo "some plain text : ", $data, endl;
68 * }
70 * function onSpecific($data)
71 * {
72 * echo "non xml data maybe <?xml...?> :", $data, endl;
73 * }
74 * };
76 * // MyParser usage :
77 * $p = new MyParser();
78 * $p->parse( $myString );
80 * ?>
82 * @author Laurent Bedubourg <laurent.bedubourg@free.fr>
84 class PHPTAL_XML_Parser
86 var $_file = '#string';
87 var $_tags = array();
88 var $_parser;
89 var $_error;
90 var $_xmlErrors = array(
91 XML_ERROR_NONE => "XML_ERROR_NONE",
92 XML_ERROR_NO_MEMORY => "XML_ERROR_NO_MEMORY",
93 XML_ERROR_SYNTAX => "XML_ERROR_SYNTAX",
94 XML_ERROR_NO_ELEMENTS => "XML_ERROR_NO_ELEMENTS",
95 XML_ERROR_INVALID_TOKEN => "XML_ERROR_INVALID_TOKEN",
96 XML_ERROR_UNCLOSED_TOKEN => "XML_ERROR_UNCLOSED_TOKEN",
97 XML_ERROR_PARTIAL_CHAR => "XML_ERROR_PARTIAL_CHAR",
98 XML_ERROR_TAG_MISMATCH => "XML_ERROR_TAG_MISMATCH",
99 XML_ERROR_DUPLICATE_ATTRIBUTE => "XML_ERROR_DUPLICATE_ATTRIBUTE",
100 XML_ERROR_JUNK_AFTER_DOC_ELEMENT => "XML_ERROR_JUNK_AFTER_DOC_ELEMENT",
101 XML_ERROR_PARAM_ENTITY_REF => "XML_ERROR_PARAM_ENTITY_REF",
102 XML_ERROR_UNDEFINED_ENTITY => "XML_ERROR_UNDEFINED_ENTITY",
103 XML_ERROR_RECURSIVE_ENTITY_REF => "XML_ERROR_RECURSIVE_ENTITY_REF",
104 XML_ERROR_ASYNC_ENTITY => "XML_ERROR_ASYNC_ENTITY",
105 XML_ERROR_BAD_CHAR_REF => "XML_ERROR_BAD_CHAR_REF",
106 XML_ERROR_BINARY_ENTITY_REF => "XML_ERROR_BINARY_ENTITY_REF",
107 XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF => "XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF",
108 XML_ERROR_MISPLACED_XML_PI => "XML_ERROR_MISPLACED_XML_PI",
109 XML_ERROR_UNKNOWN_ENCODING => "XML_ERROR_UNKNOWN_ENCODING",
110 XML_ERROR_INCORRECT_ENCODING => "XML_ERROR_INCORRECT_ENCODING",
111 XML_ERROR_UNCLOSED_CDATA_SECTION => "XML_ERROR_UNCLOSED_CDATA_SECTION",
112 XML_ERROR_EXTERNAL_ENTITY_HANDLING => "XML_ERROR_EXTERNAL_ENTITY_HANDLING",
116 * XML parser constructor.
118 function PHPTAL_XML_Parser()
120 $this->__construct();
124 * XML parser php4.4 constructor.
126 function __construct()
128 $this->_parser = xml_parser_create();
129 xml_set_object($this->_parser, $this);
130 xml_set_element_handler($this->_parser, "_onElementStart", "_onElementClose");
131 xml_set_character_data_handler($this->_parser, "_onElementData");
132 xml_set_default_handler($this->_parser, "_onSpecific");
133 xml_parser_set_option($this->_parser, XML_OPTION_CASE_FOLDING, 0);
137 * Parse specified data and call parser implementation of callback methods.
139 * @param data string Xml data to parse.
141 function _parse($data, $eof=true)
143 $data = str_replace('&','&amp;', $data);
144 if (!xml_parse($this->_parser, $data)) {
145 // PHPTAL errors first
146 if (PEAR::isError($this->_error)) {
147 return $this->_error;
149 // then look for parser errors
150 $err = xml_get_error_code($this->_parser);
151 return PEAR::raiseError($this->_xmlErrors[$err]
152 .' in '.$this->_file
153 .' around line '.$this->getLineNumber());
155 if (PEAR::isError($this->_error)) {
156 return $this->_error;
158 return true;
161 function parseString($data)
163 return $this->_parse($data, true);
166 function parseFile($path)
168 $this->_file = $path;
169 $fp = @fopen($path, "r");
170 if (!$fp) {
171 return PEAR::raiseError($php_errormsg);
173 while ($data = fread($fp, 1024)) {
174 $err = $this->_parse($data, feof($fp));
175 if (PEAR::isError($err)) {
176 fclose($fp);
177 return $err;
180 fclose($fp);
183 function _onElementStart($parser, $tag, $attributes)
185 if (PEAR::isError($this->_error)) return;
186 $this->_error = $this->onElementStart($tag, $attributes);
189 function _onElementClose($parser, $tag)
191 if (PEAR::isError($this->_error)) return;
192 $this->_error = $this->onElementClose($tag);
195 function _onElementData($parser, $data)
197 if (PEAR::isError($this->_error)) return;
198 $this->_error = $this->onElementData($data);
201 function _onSpecific($parser, $data)
203 if (PEAR::isError($this->_error)) return;
204 $this->_error = $this->onSpecific($data);
208 * Return current parser line number.
210 * @return int
212 function getLineNumber()
214 return xml_get_current_line_number($this->_parser);
218 // ABSTRACT METHODS
222 * Abstract callback called when a new xml tag is opened.
224 * @param string tag Tag name
225 * @param hashtable attributes Associative array of attributes
227 function onElementStart($tag, $attributes){}
230 * Abstract callback called when a tag is closed.
232 * @param string tag Tag name
234 function onElementClose($tag){}
237 * Abstract callback called when some #cdata is found.
239 * @param string data Content
241 function onElementData($data){}
244 * Abstract callback called when non tags entities appear in the document.
246 * This method is called by <?xml ...?> <% %> and other specific things like
247 * <?php ?>.
249 * @param string data strange data content.
251 function onSpecific($data){}