[ Index ]

PHP Cross Reference of Joomla 1.5.26 DE

title

Body

[close]

/libraries/domit/ -> xml_saxy_parser.php (source)

   1  <?php
   2  /**
   3  * SAXY is a non-validating, but lightweight and fast SAX parser for PHP, modelled on the Expat parser
   4  * @package saxy-xmlparser
   5  * @subpackage saxy-xmlparser-main
   6  * @version 1.0
   7  * @copyright (C) 2004 John Heinstein. All rights reserved
   8  * @license http://www.gnu.org/copyleft/lesser.html LGPL License
   9  * @author John Heinstein <johnkarl@nbnet.nb.ca>
  10  * @link http://www.engageinteractive.com/saxy/ SAXY Home Page
  11  * SAXY is Free Software
  12  **/
  13  
  14  if (!defined('SAXY_INCLUDE_PATH')) {
  15      define('SAXY_INCLUDE_PATH', (dirname(__FILE__) . "/"));
  16  }
  17  
  18  /** current version of SAXY */
  19  define ('SAXY_VERSION', '1.0');
  20  
  21  /** default XML namespace */
  22  define ('SAXY_XML_NAMESPACE', 'http://www.w3.org/xml/1998/namespace');
  23  
  24  /** saxy parse state, before prolog is encountered */
  25  define('SAXY_STATE_PROLOG_NONE', 0);
  26  /** saxy parse state, in processing instruction */
  27  define('SAXY_STATE_PROLOG_PROCESSINGINSTRUCTION', 1);
  28  /** saxy parse state, an exclamation mark has been encountered */
  29  define('SAXY_STATE_PROLOG_EXCLAMATION', 2);
  30  /** saxy parse state, in DTD */
  31  define('SAXY_STATE_PROLOG_DTD', 3);
  32  /** saxy parse state, an inline DTD */
  33  define('SAXY_STATE_PROLOG_INLINEDTD', 4);
  34  /** saxy parse state, a comment */
  35  define('SAXY_STATE_PROLOG_COMMENT', 5);
  36  /** saxy parse state, processing main document */
  37  define('SAXY_STATE_PARSING', 6);
  38  /** saxy parse state, processing comment in main document */
  39  define('SAXY_STATE_PARSING_COMMENT', 7);
  40  
  41  //SAXY error codes; same as EXPAT error codes
  42  /** no error */
  43  define('SAXY_XML_ERROR_NONE', 0);
  44  /** out of memory error */
  45  define('SAXY_XML_ERROR_NO_MEMORY', 1);
  46  /** syntax error */
  47  define('SAXY_XML_ERROR_SYNTAX', 2);
  48  /** no elements in document */
  49  define('SAXY_XML_ERROR_NO_ELEMENTS', 3);
  50  /** invalid token encountered error */
  51  define('SAXY_XML_ERROR_INVALID_TOKEN', 4);
  52  /** unclosed token error */
  53  define('SAXY_XML_ERROR_UNCLOSED_TOKEN', 5);
  54  /** partial character error */
  55  define('SAXY_XML_ERROR_PARTIAL_CHAR', 6);
  56  /** mismatched tag error */
  57  define('SAXY_XML_ERROR_TAG_MISMATCH', 7);
  58  /** duplicate attribute error */
  59  define('SAXY_XML_ERROR_DUPLICATE_ATTRIBUTE', 8);
  60  /** junk after document element error */
  61  define('SAXY_XML_ERROR_JUNK_AFTER_DOC_ELEMENT', 9);
  62  /** parameter enitity reference error */
  63  define('SAXY_XML_ERROR_PARAM_ENTITY_REF', 10);
  64  /** undefined entity error */
  65  define('SAXY_XML_ERROR_UNDEFINED_ENTITY', 11);
  66  /** recursive entity error */
  67  define('SAXY_XML_ERROR_RECURSIVE_ENTITY_REF', 12);
  68  /** asynchronous entity error */
  69  define('SAXY_XML_ERROR_ASYNC_ENTITY', 13);
  70  /** bad character reference error */
  71  define('SAXY_XML_ERROR_BAD_CHAR_REF', 14);
  72  /** binary entity reference error */
  73  define('SAXY_XML_ERROR_BINARY_ENTITY_REF', 15);
  74  /** attribute external entity error */
  75  define('SAXY_XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF', 16);
  76  /** misplaced processing instruction error */
  77  define('SAXY_XML_ERROR_MISPLACED_XML_PI', 17);
  78  /** unknown encoding error */
  79  define('SAXY_XML_ERROR_UNKNOWN_ENCODING', 18);
  80  /** incorrect encoding error */
  81  define('SAXY_XML_ERROR_INCORRECT_ENCODING', 19);
  82  /** unclosed CDATA Section error */
  83  define('SAXY_XML_ERROR_UNCLOSED_CDATA_SECTION', 20);
  84  /** external entity handling error */
  85  define('SAXY_XML_ERROR_EXTERNAL_ENTITY_HANDLING', 21);
  86  
  87  require_once (SAXY_INCLUDE_PATH . 'xml_saxy_shared.php');
  88  
  89  /**
  90  * The SAX Parser class
  91  *
  92  * @package saxy-xmlparser
  93  * @subpackage saxy-xmlparser-main
  94  * @author John Heinstein <johnkarl@nbnet.nb.ca>
  95  */
  96  class SAXY_Parser extends SAXY_Parser_Base {
  97      /** @var int The current error number */
  98      var $errorCode = SAXY_XML_ERROR_NONE;
  99      /** @var Object A reference to the DocType event handler */
 100      var $DTDHandler = null;
 101      /** @var Object A reference to the Comment event handler */
 102      var $commentHandler = null;
 103      /** @var Object A reference to the Processing Instruction event handler */
 104      var $processingInstructionHandler = null;
 105      /** @var Object A reference to the Start Namespace Declaration event handler */
 106      var $startNamespaceDeclarationHandler = null;
 107      /** @var Object A reference to the End Namespace Declaration event handler */
 108      var $endNamespaceDeclarationHandler = null;
 109      /** @var boolean True if SAXY takes namespaces into consideration when parsing element tags */
 110      var $isNamespaceAware = false;
 111      /** @var array An indexed array containing associative arrays of namespace prefixes mapped to their namespace URIs */
 112      var $namespaceMap = array();
 113      /** @var array A stack used to determine when an end namespace event should be fired */
 114      var $namespaceStack = array();
 115      /** @var array A track used to track the uri of the current default namespace */
 116      var $defaultNamespaceStack = array();
 117      /** @var array A stack containing tag names of unclosed elements */
 118      var $elementNameStack = array();
 119  
 120      /**
 121      * Constructor for SAX parser
 122      */
 123  	function SAXY_Parser() {
 124          $this->SAXY_Parser_Base();
 125          $this->state = SAXY_STATE_PROLOG_NONE;
 126      } //SAXY_Parser
 127  
 128      /**
 129      * Sets a reference to the handler for the DocType event
 130      * @param mixed A reference to the DocType handler
 131      */
 132  	function xml_set_doctype_handler($handler) {
 133          $this->DTDHandler =& $handler;
 134      } //xml_set_doctype_handler
 135  
 136      /**
 137      * Sets a reference to the handler for the Comment event
 138      * @param mixed A reference to the Comment handler
 139      */
 140  	function xml_set_comment_handler($handler) {
 141          $this->commentHandler =& $handler;
 142      } //xml_set_comment_handler
 143  
 144      /**
 145      * Sets a reference to the handler for the Processing Instruction event
 146      * @param mixed A reference to the Processing Instruction handler
 147      */
 148  	function xml_set_processing_instruction_handler($handler) {
 149          $this->processingInstructionHandler =& $handler;
 150      } //xml_set_processing_instruction_handler
 151  
 152      /**
 153      * Sets a reference to the handler for the Start Namespace Declaration event
 154      * @param mixed A reference to the Start Namespace Declaration handler
 155      */
 156  	function xml_set_start_namespace_decl_handler($handler) {
 157          $this->startNamespaceDeclarationHandler =& $handler;
 158      } //xml_set_start_namespace_decl_handler
 159  
 160      /**
 161      * Sets a reference to the handler for the End Namespace Declaration event
 162      * @param mixed A reference to the Start Namespace Declaration handler
 163      */
 164  	function xml_set_end_namespace_decl_handler($handler) {
 165          $this->endNamespaceDeclarationHandler =& $handler;
 166      } //xml_set_end_namespace_decl_handler
 167  
 168      /**
 169      * Specifies whether SAXY is namespace sensitive
 170      * @param boolean True if SAXY is namespace aware
 171      */
 172  	function setNamespaceAwareness($isNamespaceAware) {
 173          $this->isNamespaceAware =& $isNamespaceAware;
 174      } //setNamespaceAwareness
 175  
 176      /**
 177      * Returns the current version of SAXY
 178      * @return Object The current version of SAXY
 179      */
 180  	function getVersion() {
 181          return SAXY_VERSION;
 182      } //getVersion
 183  
 184      /**
 185      * Processes the xml prolog, doctype, and any other nodes that exist outside of the main xml document
 186      * @param string The xml text to be processed
 187      * @return string The preprocessed xml text
 188      */
 189  	function preprocessXML($xmlText) {
 190          //strip prolog
 191          $xmlText = trim($xmlText);
 192          $startChar = -1;
 193          $total = strlen($xmlText);
 194  
 195          for ($i = 0; $i < $total; $i++) {
 196  //            $currentChar = $xmlText{$i};
 197              $currentChar = substr($xmlText, $i, 1);
 198  
 199              switch ($this->state) {
 200                  case SAXY_STATE_PROLOG_NONE:
 201                      if ($currentChar == '<') {
 202                          $nextChar = $xmlText{($i + 1)};
 203  
 204                          if ($nextChar == '?')  {
 205                              $this->state = SAXY_STATE_PROLOG_PROCESSINGINSTRUCTION;
 206                              $this->charContainer = '';
 207                          }
 208                          else if ($nextChar == '!') {
 209                              $this->state = SAXY_STATE_PROLOG_EXCLAMATION;
 210                              $this->charContainer .= $currentChar;
 211                              break;
 212                          }
 213                          else {
 214                              $this->charContainer = '';
 215                              $startChar  = $i;
 216                              $this->state = SAXY_STATE_PARSING;
 217                              return (substr($xmlText, $startChar));
 218                          }
 219                      }
 220  
 221                      break;
 222  
 223                  case SAXY_STATE_PROLOG_EXCLAMATION:
 224                      if ($currentChar == 'D') {
 225                          $this->state = SAXY_STATE_PROLOG_DTD;
 226                          $this->charContainer .= $currentChar;
 227                      }
 228                      else if ($currentChar == '-') {
 229                          $this->state = SAXY_STATE_PROLOG_COMMENT;
 230                          $this->charContainer = '';
 231                      }
 232                      else {
 233                          //will trap ! and add it
 234                          $this->charContainer .= $currentChar;
 235                      }
 236  
 237                      break;
 238  
 239                  case SAXY_STATE_PROLOG_PROCESSINGINSTRUCTION:
 240                      if ($currentChar == '>') {
 241                          $this->state = SAXY_STATE_PROLOG_NONE;
 242                          $this->parseProcessingInstruction($this->charContainer);
 243                          $this->charContainer = '';
 244                      }
 245                      else {
 246                          $this->charContainer .= $currentChar;
 247                      }
 248  
 249                      break;
 250  
 251                  case SAXY_STATE_PROLOG_COMMENT:
 252                      if ($currentChar == '>') {
 253                          $this->state = SAXY_STATE_PROLOG_NONE;
 254                          $this->parseComment($this->charContainer);
 255                          $this->charContainer = '';
 256                      }
 257                      else if ($currentChar == '-') {
 258                          if ((($xmlText{($i + 1)} == '-')  && ($xmlText{($i + 2)} == '>')) ||
 259                              ($xmlText{($i + 1)} == '>') ||
 260                              (($xmlText{($i - 1)} == '-')  && ($xmlText{($i - 2)}== '!')) ){
 261                              //do nothing
 262                          }
 263                          else {
 264                              $this->charContainer .= $currentChar;
 265                          }
 266                      }
 267                      else {
 268                          $this->charContainer .= $currentChar;
 269                      }
 270  
 271                      break;
 272  
 273                  case SAXY_STATE_PROLOG_DTD:
 274                      if ($currentChar == '[') {
 275                          $this->charContainer .= $currentChar;
 276                          $this->state = SAXY_STATE_PROLOG_INLINEDTD;
 277                      }
 278                      else if ($currentChar == '>') {
 279                          $this->state = SAXY_STATE_PROLOG_NONE;
 280  
 281                          if ($this->DTDHandler != null) {
 282                              $this->fireDTDEvent($this->charContainer . $currentChar);
 283                          }
 284  
 285                          $this->charContainer = '';
 286                      }
 287                      else {
 288                          $this->charContainer .= $currentChar;
 289                      }
 290  
 291                      break;
 292  
 293                  case SAXY_STATE_PROLOG_INLINEDTD:
 294                      $previousChar = $xmlText{($i - 1)};
 295  
 296                      if (($currentChar == '>') && ($previousChar == ']')){
 297                          $this->state = SAXY_STATE_PROLOG_NONE;
 298  
 299                          if ($this->DTDHandler != null) {
 300                              $this->fireDTDEvent($this->charContainer . $currentChar);
 301                          }
 302  
 303                          $this->charContainer = '';
 304                      }
 305                      else {
 306                          $this->charContainer .= $currentChar;
 307                      }
 308  
 309                      break;
 310  
 311              }
 312          }
 313      } //preprocessXML
 314  
 315      /**
 316      * The controlling method for the parsing process
 317      * @param string The xml text to be processed
 318      * @return boolean True if parsing is successful
 319      */
 320  	function parse ($xmlText) {
 321          $xmlText = $this->preprocessXML($xmlText);
 322          $total = strlen($xmlText);
 323  
 324          for ($i = 0; $i < $total; $i++) {
 325  //            $currentChar = $xmlText{$i};
 326              $currentChar = substr($xmlText, $i, 1);
 327  
 328              switch ($this->state) {
 329                  case SAXY_STATE_PARSING:
 330                      switch ($currentChar) {
 331                          case '<':
 332                              if (substr($this->charContainer, 0, SAXY_CDATA_LEN) == SAXY_SEARCH_CDATA) {
 333                                  $this->charContainer .= $currentChar;
 334                              }
 335                              else {
 336                                  $this->parseBetweenTags($this->charContainer);
 337                                  $this->charContainer = '';
 338                              }
 339                              break;
 340  
 341                          case '-':
 342                              if (($xmlText{($i - 1)} == '-') && ($xmlText{($i - 2)} == '!')
 343                                  && ($xmlText{($i - 3)} == '<')) {
 344                                  $this->state = SAXY_STATE_PARSING_COMMENT;
 345                                  $this->charContainer = '';
 346                              }
 347                              else {
 348                                  $this->charContainer .= $currentChar;
 349                              }
 350                              break;
 351  
 352                          case '>':
 353                              if ((substr($this->charContainer, 0, SAXY_CDATA_LEN) == SAXY_SEARCH_CDATA) &&
 354                                  !(($this->getCharFromEnd($this->charContainer, 0) == ']') &&
 355                                  ($this->getCharFromEnd($this->charContainer, 1) == ']'))) {
 356                                  $this->charContainer .= $currentChar;
 357                              }
 358                              else {
 359                                  $this->parseTag($this->charContainer);
 360                                  $this->charContainer = '';
 361                              }
 362                              break;
 363  
 364                          default:
 365                              $this->charContainer .= $currentChar;
 366                      }
 367  
 368                      break;
 369  
 370                  case SAXY_STATE_PARSING_COMMENT:
 371                      switch ($currentChar) {
 372                          case '>':
 373                              if (($xmlText{($i - 1)} == '-') && ($xmlText{($i - 2)} == '-')) {
 374                                  $this->fireCommentEvent(substr($this->charContainer, 0,
 375                                                      (strlen($this->charContainer) - 2)));
 376                                  $this->charContainer = '';
 377                                  $this->state = SAXY_STATE_PARSING;
 378                              }
 379                              else {
 380                                  $this->charContainer .= $currentChar;
 381                              }
 382                              break;
 383  
 384                          default:
 385                              $this->charContainer .= $currentChar;
 386                      }
 387  
 388                      break;
 389              }
 390          }
 391  
 392          return ($this->errorCode == 0);
 393      } //parse
 394  
 395      /**
 396      * Parses an element tag
 397      * @param string The interior text of the element tag
 398      */
 399  	function parseTag($tagText) {
 400          $tagText = trim($tagText);
 401          $firstChar = $tagText{0};
 402          $myAttributes = array();
 403  
 404          switch ($firstChar) {
 405              case '/':
 406                  $tagName = substr($tagText, 1);
 407                  $this->_fireEndElementEvent($tagName);
 408                  break;
 409  
 410              case '!':
 411                  $upperCaseTagText = strtoupper($tagText);
 412  
 413                  if (strpos($upperCaseTagText, SAXY_SEARCH_CDATA) !== false) { //CDATA Section
 414                      $total = strlen($tagText);
 415                      $openBraceCount = 0;
 416                      $textNodeText = '';
 417  
 418                      for ($i = 0; $i < $total; $i++) {
 419  //                        $currentChar = $tagText{$i};
 420                          $currentChar = substr($tagText, $i, 1);
 421  
 422                          if (($currentChar == ']') && ($tagText{($i + 1)} == ']')) {
 423                              break;
 424                          }
 425                          else if ($openBraceCount > 1) {
 426                              $textNodeText .= $currentChar;
 427                          }
 428                          else if ($currentChar == '[') { //this won't be reached after the first open brace is found
 429                              $openBraceCount ++;
 430                          }
 431                      }
 432  
 433                      if ($this->cDataSectionHandler == null) {
 434                          $this->fireCharacterDataEvent($textNodeText);
 435                      }
 436                      else {
 437                          $this->fireCDataSectionEvent($textNodeText);
 438                      }
 439                  }
 440                  else if (strpos($upperCaseTagText, SAXY_SEARCH_NOTATION) !== false) { //NOTATION node, discard
 441                      return;
 442                  }
 443                  /*
 444                  else if (substr($tagText, 0, 2) == '!-') { //comment node
 445                      if ($this->commentHandler != null) {
 446                          $this->fireCommentEvent(substr($tagText, 3, (strlen($tagText) - 5)));
 447                      }
 448                  }
 449                  */
 450                  break;
 451  
 452              case '?':
 453                  //Processing Instruction node
 454                  $this->parseProcessingInstruction($tagText);
 455                  break;
 456  
 457              default:
 458                  if ((strpos($tagText, '"') !== false) || (strpos($tagText, "'") !== false)) {
 459                      $total = strlen($tagText);
 460                      $tagName = '';
 461  
 462                      for ($i = 0; $i < $total; $i++) {
 463  //                        $currentChar = $tagText{$i};
 464                          $currentChar = substr($tagText, $i, 1);
 465  
 466                          if (($currentChar == ' ') || ($currentChar == "\t") ||
 467                              ($currentChar == "\n") || ($currentChar == "\r") ||
 468                              ($currentChar == "\x0B")) {
 469                              $myAttributes = $this->parseAttributes(substr($tagText, $i));
 470                              break;
 471                          }
 472                          else {
 473                              $tagName .= $currentChar;
 474                          }
 475                      }
 476  
 477                      if (strrpos($tagText, '/') == (strlen($tagText) - 1)) { //check $tagText, but send $tagName
 478                          $this->_fireStartElementEvent($tagName, $myAttributes);
 479                          $this->_fireEndElementEvent($tagName);
 480                      }
 481                      else {
 482                          $this->_fireStartElementEvent($tagName, $myAttributes);
 483                      }
 484                  }
 485                  else {
 486                      if (strpos($tagText, '/') !== false) {
 487                          $tagText = trim(substr($tagText, 0, (strrchr($tagText, '/') - 1)));
 488                          $this->_fireStartElementEvent($tagText, $myAttributes);
 489                          $this->_fireEndElementEvent($tagText);
 490                      }
 491                      else {
 492                          $this->_fireStartElementEvent($tagText, $myAttributes);
 493                      }
 494                  }
 495          }
 496      } //parseTag
 497  
 498       /**
 499      * Fires a start element event and pushes the element name onto the elementName stack
 500      * @param string The start element tag name
 501      * @param Array The start element attributes
 502      */
 503  	function _fireStartElementEvent($tagName, &$myAttributes) {
 504          $this->elementNameStack[] = $tagName;
 505  
 506          if ($this->isNamespaceAware) {
 507              $this->detectStartNamespaceDeclaration($myAttributes);
 508              $tagName = $this->expandNamespacePrefix($tagName);
 509  
 510              $this->expandAttributePrefixes($myAttributes);
 511          }
 512  
 513          $this->fireStartElementEvent($tagName, $myAttributes);
 514      } //_fireStartElementEvent
 515  
 516      /**
 517      * Expands attribute prefixes to full namespace uri
 518      * @param Array The start element attributes
 519      */
 520  	function expandAttributePrefixes(&$myAttributes) {
 521          $arTransform = array();
 522  
 523          foreach ($myAttributes as $key => $value) {
 524              if (strpos($key, 'xmlns') === false) {
 525                  if (strpos($key, ':') !== false) {
 526                      $expandedTag = $this->expandNamespacePrefix($key);
 527                      $arTransform[$key] = $expandedTag;
 528                  }
 529              }
 530          }
 531  
 532          foreach ($arTransform as $key => $value) {
 533              $myAttributes[$value] = $myAttributes[$key];
 534              unset($myAttributes[$key]);
 535          }
 536      } //expandAttributePrefixes
 537  
 538      /**
 539      * Expands the namespace prefix (if one exists) to the full namespace uri
 540      * @param string The tagName with the namespace prefix
 541      * @return string The tagName, with the prefix expanded to the namespace uri
 542      */
 543  	function expandNamespacePrefix($tagName) {
 544          $stackLen = count($this->defaultNamespaceStack);
 545          $defaultNamespace = $this->defaultNamespaceStack[($stackLen - 1)];
 546  
 547          $colonIndex = strpos($tagName, ':');
 548  
 549          if ($colonIndex !== false) {
 550              $prefix = substr($tagName, 0, $colonIndex);
 551  
 552              if ($prefix != 'xml') {
 553                  $tagName = $this->getNamespaceURI($prefix) . substr($tagName, $colonIndex);
 554              }
 555              else {
 556                  $tagName = SAXY_XML_NAMESPACE . substr($tagName, $colonIndex);
 557              }
 558          }
 559          else if ($defaultNamespace != '') {
 560              $tagName = $defaultNamespace . ':' . $tagName;
 561          }
 562  
 563          return $tagName;
 564      } //expandNamespacePrefix
 565  
 566      /**
 567      * Searches the namespaceMap for the specified prefix, and returns the full namespace URI
 568      * @param string The namespace prefix
 569      * @return string The namespace uri
 570      */
 571  	function getNamespaceURI($prefix) {
 572          $total = count($this->namespaceMap);
 573          $uri = $prefix; //in case uri can't be found, just send back prefix
 574                          //should really generate an error, but worry about this later
 575          //reset($this->namespaceMap);
 576  
 577          for ($i = ($total - 1); $i >= 0; $i--) {
 578              $currMap =& $this->namespaceMap[$i];
 579  
 580              if (isset($currMap[$prefix])) {
 581                  $uri = $currMap[$prefix];
 582                  break;
 583              }
 584          }
 585  
 586          return $uri;
 587      } //getNamespaceURI
 588  
 589      /**
 590      * Searches the attributes array for an xmlns declaration and fires an event if found
 591      * @param Array The start element attributes
 592      */
 593  	function detectStartNamespaceDeclaration(&$myAttributes) {
 594          $namespaceExists = false;
 595          $namespaceMapUpper = 0;
 596          $userDefinedDefaultNamespace = false;
 597          $total = count($myAttributes);
 598  
 599          foreach ($myAttributes as $key => $value) {
 600              if (strpos($key, 'xmlns') !== false) {
 601                  //add an array to store all namespaces for the current element
 602                  if (!$namespaceExists) {
 603                      $this->namespaceMap[] = array();
 604                      $namespaceMapUpper = count($this->namespaceMap) - 1;
 605                  }
 606  
 607                  //check for default namespace override, i.e. xmlns='...'
 608                  if (strpos($key, ':') !== false) {
 609                      $prefix = $namespaceMapKey = substr($key, 6);
 610                      $this->namespaceMap[$namespaceMapUpper][$namespaceMapKey] = $value;
 611                  }
 612                  else {
 613                      $prefix = '';
 614                      $userDefinedDefaultNamespace = true;
 615  
 616                      //if default namespace '', store in map using key ':'
 617                      $this->namespaceMap[$namespaceMapUpper][':'] = $value;
 618                      $this->defaultNamespaceStack[] = $value;
 619                  }
 620  
 621                  $this->fireStartNamespaceDeclarationEvent($prefix, $value);
 622                  $namespaceExists = true;
 623  
 624                  unset($myAttributes[$key]);
 625              }
 626          }
 627  
 628          //store the default namespace (inherited from the parent elements so grab last one)
 629          if (!$userDefinedDefaultNamespace) {
 630              $stackLen = count($this->defaultNamespaceStack);
 631              if ($stackLen == 0) {
 632                  $this->defaultNamespaceStack[] = '';
 633              }
 634              else {
 635                  $this->defaultNamespaceStack[] =
 636                      $this->defaultNamespaceStack[($stackLen - 1)];
 637              }
 638          }
 639  
 640          $this->namespaceStack[] = $namespaceExists;
 641      } //detectStartNamespaceDeclaration
 642  
 643      /**
 644      * Fires an end element event and pops the element name from the elementName stack
 645      * @param string The end element tag name
 646      */
 647  	function _fireEndElementEvent($tagName) {
 648          $lastTagName = array_pop($this->elementNameStack);
 649  
 650          //check for mismatched tag error
 651          if ($lastTagName != $tagName) {
 652              $this->errorCode = SAXY_XML_ERROR_TAG_MISMATCH;
 653          }
 654  
 655          if ($this->isNamespaceAware) {
 656              $tagName = $this->expandNamespacePrefix($tagName);
 657              $this->fireEndElementEvent($tagName);
 658              $this->detectEndNamespaceDeclaration();
 659              $defaultNamespace = array_pop($this->defaultNamespaceStack);
 660          }
 661          else {
 662              $this->fireEndElementEvent($tagName);
 663          }
 664      } //_fireEndElementEvent
 665  
 666      /**
 667      * Determines whether an end namespace declaration event should be fired
 668      */
 669  	function detectEndNamespaceDeclaration() {
 670          $isNamespaceEnded = array_pop($this->namespaceStack);
 671  
 672          if ($isNamespaceEnded) {
 673              $map = array_pop($this->namespaceMap);
 674  
 675              foreach ($map as $key => $value) {
 676                  if ($key == ':') {
 677                      $key = '';
 678                  }
 679                  $this->fireEndNamespaceDeclarationEvent($key);
 680              }
 681          }
 682      } //detectEndNamespaceDeclaration
 683  
 684      /**
 685      * Parses a processing instruction
 686      * @param string The interior text of the processing instruction
 687      */
 688  	function parseProcessingInstruction($data) {
 689          $endTarget = 0;
 690          $total = strlen($data);
 691  
 692          for ($x = 2; $x < $total; $x++) {
 693  //            if (trim($data{$x}) == '') {
 694              if (trim(substr($data, $x, 1)) == '') {
 695                  $endTarget = $x;
 696                  break;
 697              }
 698          }
 699  
 700          $target = substr($data, 1, ($endTarget - 1));
 701          $data = substr($data, ($endTarget + 1), ($total - $endTarget - 2));
 702  
 703          if ($this->processingInstructionHandler != null) {
 704              $this->fireProcessingInstructionEvent($target, $data);
 705          }
 706      } //parseProcessingInstruction
 707  
 708      /**
 709      * Parses a comment
 710      * @param string The interior text of the comment
 711      */
 712  	function parseComment($data) {
 713          if ($this->commentHandler != null) {
 714              $this->fireCommentEvent($data);
 715          }
 716      } //parseComment
 717  
 718      /**
 719      * Fires a doctype event
 720      * @param string The doctype data
 721      */
 722  	function fireDTDEvent($data) {
 723          call_user_func($this->DTDHandler, $this, $data);
 724      } //fireDTDEvent
 725  
 726      /**
 727      * Fires a comment event
 728      * @param string The text of the comment
 729      */
 730  	function fireCommentEvent($data) {
 731          call_user_func($this->commentHandler, $this, $data);
 732      } //fireCommentEvent
 733  
 734      /**
 735      * Fires a processing instruction event
 736      * @param string The processing instruction data
 737      */
 738  	function fireProcessingInstructionEvent($target, $data) {
 739          call_user_func($this->processingInstructionHandler, $this, $target, $data);
 740      } //fireProcessingInstructionEvent
 741  
 742      /**
 743      * Fires a start namespace declaration event
 744      * @param string The namespace prefix
 745      * @param string The namespace uri
 746      */
 747  	function fireStartNamespaceDeclarationEvent($prefix, $uri) {
 748          call_user_func($this->startNamespaceDeclarationHandler, $this, $prefix, $uri);
 749      } //fireStartNamespaceDeclarationEvent
 750  
 751      /**
 752      * Fires an end namespace declaration event
 753      * @param string The namespace prefix
 754      */
 755  	function fireEndNamespaceDeclarationEvent($prefix) {
 756          call_user_func($this->endNamespaceDeclarationHandler, $this, $prefix);
 757      } //fireEndNamespaceDeclarationEvent
 758  
 759      /**
 760      * Returns the current error code
 761      * @return int The current error code
 762      */
 763  	function xml_get_error_code() {
 764          return $this->errorCode;
 765      } //xml_get_error_code
 766  
 767      /**
 768      * Returns a textual description of the error code
 769      * @param int The error code
 770      * @return string The error message
 771      */
 772  	function xml_error_string($code) {
 773          switch ($code) {
 774              case SAXY_XML_ERROR_NONE:
 775                  return "No error";
 776                  break;
 777              case SAXY_XML_ERROR_NO_MEMORY:
 778                  return "Out of memory";
 779                  break;
 780              case SAXY_XML_ERROR_SYNTAX:
 781                  return "Syntax error";
 782                  break;
 783              case SAXY_XML_ERROR_NO_ELEMENTS:
 784                  return "No elements in document";
 785                  break;
 786              case SAXY_XML_ERROR_INVALID_TOKEN:
 787                  return "Invalid token";
 788                  break;
 789              case SAXY_XML_ERROR_UNCLOSED_TOKEN:
 790                  return "Unclosed token";
 791                  break;
 792              case SAXY_XML_ERROR_PARTIAL_CHAR:
 793                  return "Partial character";
 794                  break;
 795              case SAXY_XML_ERROR_TAG_MISMATCH:
 796                  return "Tag mismatch";
 797                  break;
 798              case SAXY_XML_ERROR_DUPLICATE_ATTRIBUTE:
 799                  return "Duplicate attribute";
 800                  break;
 801              case SAXY_XML_ERROR_JUNK_AFTER_DOC_ELEMENT:
 802                  return "Junk encountered after document element";
 803                  break;
 804              case SAXY_XML_ERROR_PARAM_ENTITY_REF:
 805                  return "Parameter entity reference error";
 806                  break;
 807              case SAXY_XML_ERROR_UNDEFINED_ENTITY:
 808                  return "Undefined entity";
 809                  break;
 810              case SAXY_XML_ERROR_RECURSIVE_ENTITY_REF:
 811                  return "Recursive entity reference";
 812                  break;
 813              case SAXY_XML_ERROR_ASYNC_ENTITY:
 814                  return "Asynchronous internal entity found in external entity";
 815                  break;
 816              case SAXY_XML_ERROR_BAD_CHAR_REF:
 817                  return "Bad character reference";
 818                  break;
 819              case SAXY_XML_ERROR_BINARY_ENTITY_REF:
 820                  return "Binary entity reference";
 821                  break;
 822              case SAXY_XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF:
 823                  return "Attribute external entity reference";
 824                  break;
 825              case SAXY_XML_ERROR_MISPLACED_XML_PI:
 826                  return "Misplaced processing instruction";
 827                  break;
 828              case SAXY_XML_ERROR_UNKNOWN_ENCODING:
 829                  return "Unknown encoding";
 830                  break;
 831              case SAXY_XML_ERROR_INCORRECT_ENCODING:
 832                  return "Incorrect encoding";
 833                  break;
 834              case SAXY_XML_ERROR_UNCLOSED_CDATA_SECTION:
 835                  return "Unclosed CDATA Section";
 836                  break;
 837              case SAXY_XML_ERROR_EXTERNAL_ENTITY_HANDLING:
 838                  return "Problem in external entity handling";
 839                  break;
 840              default:
 841                  return "No definition for error code " . $code;
 842                  break;
 843          }
 844      } //xml_error_string
 845  
 846  } //SAXY_Parser
 847  ?>


Generated: Wed Mar 28 15:54:07 2012 Cross-referenced by PHPXref 0.7.1