XOOPS 2.5.6  Final
 All Classes Namespaces Files Functions Variables Pages
saxparser.php
Go to the documentation of this file.
1 <?php
2 // $Id: saxparser.php 8066 2011-11-06 05:09:33Z beckmi $
3 /*******************************************************************************
4  Location: <strong>xml/SaxParser.class</strong><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 
16 class SaxParser
17 {
18  var $level;
19  var $parser;
20 
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  ****************************************************************************/
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  }
166  else {
167  $this->__destruct();
168  }
169  }
170 
171  /****************************************************************************
172  * @private
173  * @returns 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  Functions that are added must be of the form:<br>
187  <strong>functionName( $attributes )</strong>
188  * @param $tagName string. The name of the tag currently being parsed.
189  * @param $functionName string. The name of the function in XmlDocument's
190  subclass.
191  * @returns void
192  ****************************************************************************/
193  function addTagHandler(&$tagHandler)
194  {
195  $name = $tagHandler->getName();
196  if (is_array($name)) {
197  foreach ($name as $n) {
198  $this->tagHandlers[$n] =& $tagHandler;
199  }
200  } else {
201  $this->tagHandlers[$name] =& $tagHandler;
202  }
203  }
204 
205 
206  /*---------------------------------------------------------------------------
207  Private Handler Methods
208  ---------------------------------------------------------------------------*/
209 
210  /****************************************************************************
211  Callback function that executes whenever a the start of a tag
212  occurs when being parsed.
213  * @param $parser int. The handle to the parser.
214  * @param $tagName string. The name of the tag currently being parsed.
215  * @param $attributesArray attay. The list of attributes associated with
216  the tag.
217  * @private
218  * @returns void
219  ****************************************************************************/
220  function handleBeginElement($parser, $tagName, $attributesArray)
221  {
222  array_push($this->tags, $tagName);
223  $this->level++;
224  if (isset($this->tagHandlers[$tagName]) && is_subclass_of($this->tagHandlers[$tagName], 'xmltaghandler')) {
225  $this->tagHandlers[$tagName]->handleBeginElement($this, $attributesArray);
226  } else {
227  $this->handleBeginElementDefault($parser, $tagName, $attributesArray);
228  }
229  }
230 
231  /****************************************************************************
232  Callback function that executes whenever the end of a tag
233  occurs when being parsed.
234  * @param $parser int. The handle to the parser.
235  * @param $tagName string. The name of the tag currently being parsed.
236  * @private
237  * @returns void
238  ****************************************************************************/
239  function handleEndElement($parser, $tagName)
240  {
241  array_pop($this->tags);
242  if (isset($this->tagHandlers[$tagName]) && is_subclass_of($this->tagHandlers[$tagName], 'xmltaghandler')) {
243  $this->tagHandlers[$tagName]->handleEndElement($this);
244  } else {
245  $this->handleEndElementDefault($parser, $tagName);
246  }
247  $this->level--;
248  }
249 
250  /****************************************************************************
251  Callback function that executes whenever character data is encountered
252  while being parsed.
253  * @param $parser int. The handle to the parser.
254  * @param $data string. Character data inside the tag
255  * @returns void
256  ****************************************************************************/
257  function handleCharacterData($parser, $data)
258  {
259  $tagHandler =& $this->tagHandlers[$this->getCurrentTag()];
260  if (isset($tagHandler) && is_subclass_of($tagHandler, 'xmltaghandler')) {
261  $tagHandler->handleCharacterData($this, $data);
262  } else {
263  $this->handleCharacterDataDefault($parser, $data);
264  }
265  }
266 
267  /****************************************************************************
268  * @param $parser int. The handle to the parser.
269  * @returns void
270  ****************************************************************************/
272  {
273 // if($target == 'php') {
274 // eval($data);
275 // }
276  }
277 
278  /****************************************************************************
279  * @param $parser int. The handle to the parser.
280  * @returns void
281  ****************************************************************************/
282  function handleDefault($parser, $data)
283  {
284 
285  }
286 
287  /****************************************************************************
288  * @param $parser int. The handle to the parser.
289  * @returns void
290  ****************************************************************************/
291  function handleUnparsedEntityDecl($parser, $entityName, $base, $systemId, $publicId, $notationName)
292  {
293 
294  }
295 
296  /****************************************************************************
297  * @param $parser int. The handle to the parser.
298  * @returns void
299  ****************************************************************************/
300  function handleNotationDecl($parser, $notationName, $base, $systemId, $publicId)
301  {
302 
303  }
304 
305  /****************************************************************************
306  * @param $parser int. The handle to the parser.
307  * @returns void
308  ****************************************************************************/
309  function handleExternalEntityRef($parser, $openEntityNames, $base, $systemId, $publicId)
310  {
311 
312  }
313 
319  function handleBeginElementDefault($parser, $tagName, $attributesArray)
320  {
321  }
322 
328  function handleEndElementDefault($parser, $tagName)
329  {
330  }
331 
338  {
339  }
340 
346  function setErrors($error)
347  {
348  $this->errors[] = trim($error);
349  }
350 
357  function &getErrors($ashtml = true)
358  {
359  if (!$ashtml) {
360  return $this->errors;
361  } else {
362  $ret = '';
363  if (count($this->errors) > 0) {
364  foreach ($this->errors as $error) {
365  $ret .= $error.'<br />';
366  }
367  }
368  return $ret;
369  }
370  }
371 }
372 
373 ?>