2 /* vim: set expandtab tabstop=4 shiftwidth=4: */
4 // Copyright (c) 2003 Laurent Bedubourg
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.
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.
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
20 // Authors: Laurent Bedubourg <laurent.bedubourg@free.fr>
23 require_once PT_IP
. "/Types/Errors.php";
26 * PHPTAL internal xml parser.
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
42 * - onElementStart($tag, $attributes)
43 * - onElementClose($tag)
44 * - onElementData($data)
47 * Here's an exemple of xml parser implementation.
50 * require_once PT_IP . "/PHPTAL/XML_Parser.php";
52 * class MyParser extends PHPTAL_XML_Parser
54 * function onElementStart($tag, $attributes)
56 * echo "new tag $tag with attributes :", endl;
57 * print_r($attributes);
60 * function onElementClose($tag)
62 * echo "tag ",$tag," is closed", endl;
65 * function onElementData($data)
67 * echo "some plain text : ", $data, endl;
70 * function onSpecific($data)
72 * echo "non xml data maybe <?xml...?> :", $data, endl;
77 * $p = new MyParser();
78 * $p->parse( $myString );
82 * @author Laurent Bedubourg <laurent.bedubourg@free.fr>
84 class PHPTAL_XML_Parser
86 var $_file = '#string';
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('&','&', $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]
153 .' around line '.$this->getLineNumber());
155 if (PEAR
::isError($this->_error
)) {
156 return $this->_error
;
161 function parseString($data)
163 return $this->_parse($data, true);
166 function parseFile($path)
168 $this->_file
= $path;
169 $fp = @fopen
($path, "r");
171 return PEAR
::raiseError($php_errormsg);
173 while ($data = fread($fp, 1024)) {
174 $err = $this->_parse($data, feof($fp));
175 if (PEAR
::isError($err)) {
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.
212 function getLineNumber()
214 return xml_get_current_line_number($this->_parser
);
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
249 * @param string data strange data content.
251 function onSpecific($data){}