1<?php 2 3/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ 4 5/** 6 * XML_Parser 7 * 8 * XML Parser's Simple parser class 9 * 10 * PHP versions 4 and 5 11 * 12 * LICENSE: 13 * 14 * Copyright (c) 2002-2008 The PHP Group 15 * All rights reserved. 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions 19 * are met: 20 * 21 * * Redistributions of source code must retain the above copyright 22 * notice, this list of conditions and the following disclaimer. 23 * * Redistributions in binary form must reproduce the above copyright 24 * notice, this list of conditions and the following disclaimer in the 25 * documentation and/or other materials provided with the distribution. 26 * * The name of the author may not be used to endorse or promote products 27 * derived from this software without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 30 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 31 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 32 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 33 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 34 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 35 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 36 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 37 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 38 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 39 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40 * 41 * @category XML 42 * @package XML_Parser 43 * @author Stephan Schmidt <schst@php.net> 44 * @copyright 2004-2008 Stephan Schmidt <schst@php.net> 45 * @license http://opensource.org/licenses/bsd-license New BSD License 46 * @version CVS: $Id$ 47 * @link http://pear.php.net/package/XML_Parser 48 */ 49 50/** 51 * built on XML_Parser 52 */ 53require_once 'XML/Parser.php'; 54 55/** 56 * Simple XML parser class. 57 * 58 * This class is a simplified version of XML_Parser. 59 * In most XML applications the real action is executed, 60 * when a closing tag is found. 61 * 62 * XML_Parser_Simple allows you to just implement one callback 63 * for each tag that will receive the tag with its attributes 64 * and CData. 65 * 66 * <code> 67 * require_once '../Parser/Simple.php'; 68 * 69 * class myParser extends XML_Parser_Simple 70 * { 71 * function myParser() 72 * { 73 * $this->XML_Parser_Simple(); 74 * } 75 * 76 * function handleElement($name, $attribs, $data) 77 * { 78 * printf('handle %s<br>', $name); 79 * } 80 * } 81 * 82 * $p = new myParser(); 83 * 84 * $result = $p->setInputFile('myDoc.xml'); 85 * $result = $p->parse(); 86 * </code> 87 * 88 * @category XML 89 * @package XML_Parser 90 * @author Stephan Schmidt <schst@php.net> 91 * @copyright 2004-2008 The PHP Group 92 * @license http://opensource.org/licenses/bsd-license New BSD License 93 * @version Release: @package_version@ 94 * @link http://pear.php.net/package/XML_Parser 95 */ 96class XML_Parser_Simple extends XML_Parser 97{ 98 /** 99 * element stack 100 * 101 * @access private 102 * @var array 103 */ 104 var $_elStack = array(); 105 106 /** 107 * all character data 108 * 109 * @access private 110 * @var array 111 */ 112 var $_data = array(); 113 114 /** 115 * element depth 116 * 117 * @access private 118 * @var integer 119 */ 120 var $_depth = 0; 121 122 /** 123 * Mapping from expat handler function to class method. 124 * 125 * @var array 126 */ 127 var $handler = array( 128 'default_handler' => 'defaultHandler', 129 'processing_instruction_handler' => 'piHandler', 130 'unparsed_entity_decl_handler' => 'unparsedHandler', 131 'notation_decl_handler' => 'notationHandler', 132 'external_entity_ref_handler' => 'entityrefHandler' 133 ); 134 135 /** 136 * Creates an XML parser. 137 * 138 * This is needed for PHP4 compatibility, it will 139 * call the constructor, when a new instance is created. 140 * 141 * @param string $srcenc source charset encoding, use NULL (default) to use 142 * whatever the document specifies 143 * @param string $mode how this parser object should work, "event" for 144 * handleElement(), "func" to have it call functions 145 * named after elements (handleElement_$name()) 146 * @param string $tgtenc a valid target encoding 147 */ 148 function __construct($srcenc = null, $mode = 'event', $tgtenc = null) 149 { 150 parent::__construct($srcenc, $mode, $tgtenc); 151 } 152 153 /** 154 * inits the handlers 155 * 156 * @return mixed 157 * @access private 158 */ 159 function _initHandlers() 160 { 161 if (!is_object($this->_handlerObj)) { 162 $this->_handlerObj = $this; 163 } 164 165 if ($this->mode != 'func' && $this->mode != 'event') { 166 return $this->raiseError('Unsupported mode given', 167 XML_PARSER_ERROR_UNSUPPORTED_MODE); 168 } 169 xml_set_object($this->parser, $this->_handlerObj); 170 171 xml_set_element_handler($this->parser, array($this, 'startHandler'), 172 array($this, 'endHandler')); 173 xml_set_character_data_handler($this->parser, array($this, 'cdataHandler')); 174 175 /** 176 * set additional handlers for character data, entities, etc. 177 */ 178 foreach ($this->handler as $xml_func => $method) { 179 if (method_exists($this->_handlerObj, $method)) { 180 $xml_func = 'xml_set_' . $xml_func; 181 $xml_func($this->parser, $method); 182 } 183 } 184 } 185 186 /** 187 * Reset the parser. 188 * 189 * This allows you to use one parser instance 190 * to parse multiple XML documents. 191 * 192 * @access public 193 * @return boolean|object true on success, PEAR_Error otherwise 194 */ 195 function reset() 196 { 197 $this->_elStack = array(); 198 $this->_data = array(); 199 $this->_depth = 0; 200 201 $result = $this->_create(); 202 if ($this->isError($result)) { 203 return $result; 204 } 205 return true; 206 } 207 208 /** 209 * start handler 210 * 211 * Pushes attributes and tagname onto a stack 212 * 213 * @param resource $xp xml parser resource 214 * @param string $elem element name 215 * @param array &$attribs attributes 216 * 217 * @return mixed 218 * @access private 219 * @final 220 */ 221 function startHandler($xp, $elem, &$attribs) 222 { 223 array_push($this->_elStack, array( 224 'name' => $elem, 225 'attribs' => $attribs 226 )); 227 $this->_depth++; 228 $this->_data[$this->_depth] = ''; 229 } 230 231 /** 232 * end handler 233 * 234 * Pulls attributes and tagname from a stack 235 * 236 * @param resource $xp xml parser resource 237 * @param string $elem element name 238 * 239 * @return mixed 240 * @access private 241 * @final 242 */ 243 function endHandler($xp, $elem) 244 { 245 $el = array_pop($this->_elStack); 246 $data = $this->_data[$this->_depth]; 247 $this->_depth--; 248 249 switch ($this->mode) { 250 case 'event': 251 $this->_handlerObj->handleElement($el['name'], $el['attribs'], $data); 252 break; 253 case 'func': 254 $func = 'handleElement_' . $elem; 255 if (strchr($func, '.')) { 256 $func = str_replace('.', '_', $func); 257 } 258 if (method_exists($this->_handlerObj, $func)) { 259 call_user_func(array($this->_handlerObj, $func), 260 $el['name'], $el['attribs'], $data); 261 } 262 break; 263 } 264 } 265 266 /** 267 * handle character data 268 * 269 * @param resource $xp xml parser resource 270 * @param string $data data 271 * 272 * @return void 273 * @access private 274 * @final 275 */ 276 function cdataHandler($xp, $data) 277 { 278 $this->_data[$this->_depth] .= $data; 279 } 280 281 /** 282 * handle a tag 283 * 284 * Implement this in your parser 285 * 286 * @param string $name element name 287 * @param array $attribs attributes 288 * @param string $data character data 289 * 290 * @return void 291 * @access public 292 * @abstract 293 */ 294 function handleElement($name, $attribs, $data) 295 { 296 } 297 298 /** 299 * get the current tag depth 300 * 301 * The root tag is in depth 0. 302 * 303 * @access public 304 * @return integer 305 */ 306 function getCurrentDepth() 307 { 308 return $this->_depth; 309 } 310 311 /** 312 * add some string to the current ddata. 313 * 314 * This is commonly needed, when a document is parsed recursively. 315 * 316 * @param string $data data to add 317 * 318 * @return void 319 * @access public 320 */ 321 function addToData($data) 322 { 323 $this->_data[$this->_depth] .= $data; 324 } 325} 326?> 327