[ Index ]

PHP Cross Reference of Joomla 1.5.26 DE

title

Body

[close]

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

   1  <?php
   2  /**
   3  * @package domit-xmlparser
   4  * @subpackage domit-xmlparser-main
   5  * @copyright (C) 2004 John Heinstein. All rights reserved
   6  * @license http://www.gnu.org/copyleft/lesser.html LGPL License
   7  * @author John Heinstein <johnkarl@nbnet.nb.ca>
   8  * @link http://www.engageinteractive.com/domit/ DOMIT! Home Page
   9  * DOMIT! is Free Software
  10  **/
  11  
  12  if (!defined('DOMIT_INCLUDE_PATH')) {
  13      define('DOMIT_INCLUDE_PATH', (dirname(__FILE__) . "/"));
  14  }
  15  
  16  /** Separator for absolute path */
  17  define('DOMIT_XPATH_SEPARATOR_ABSOLUTE', '/');
  18  /** Separator for relative path */
  19  define('DOMIT_XPATH_SEPARATOR_RELATIVE', '//');
  20  /** OR separator for multiple patterns  */
  21  define('DOMIT_XPATH_SEPARATOR_OR', '|');
  22  
  23  /** Constant for an absolute path search (starting at the document root) */
  24  define('DOMIT_XPATH_SEARCH_ABSOLUTE', 0);
  25  /** Constant for a relative path search (starting at the level of the calling node) */
  26  define('DOMIT_XPATH_SEARCH_RELATIVE', 1);
  27  /** Constant for a variable path search (finds all matches, regardless of place in the hierarchy) */
  28  define('DOMIT_XPATH_SEARCH_VARIABLE', 2);
  29  
  30  
  31  /**
  32  * DOMIT! XPath is an XPath parser.
  33  */
  34  class DOMIT_XPath {
  35      /** @var Object The node from which the search is called */
  36      var $callingNode;
  37      /** @var Object The node that is the current parent of the search */
  38      var $searchType;
  39      /** @var array An array containing a series of path segments for which to search */
  40      var $arPathSegments = array();
  41      /** @var Object A DOMIT_NodeList of matching nodes */
  42      var $nodeList;
  43      /** @var string A temporary string container */
  44      var $charContainer;
  45      /** @var string The current character of the current pattern segment being parsed */
  46      var $currChar;
  47      /** @var string The current pattern segment being parsed */
  48      var $currentSegment;
  49      /** @var array A temporary node container for caching node references at the pattern level*/
  50      var $globalNodeContainer;
  51      /** @var array A temporary node container for caching node references at the pattern segment level */
  52      var $localNodeContainer;
  53      /** @var array Normalization table for XPath syntax */
  54      var $normalizationTable = array('child::' => '', 'self::' => '.',
  55                              'attribute::' => '@', 'descendant::' => '*//',
  56                              "\t" => ' ', "\x0B" => ' ');
  57      /** @var array A second-pass normalization table for XPath syntax */
  58      var $normalizationTable2 = array(' =' => '=', '= ' => '=', ' <' => '<',
  59                              ' >' => '>', '< ' => '<', '> ' => '>',
  60                              ' !' => '!', '( ' => '(',
  61                              ' )' => ')', ' ]' => ']', '] ' => ']',
  62                              ' [' => '[', '[ ' => '[', ' /' => '/',
  63                              '/ ' => '/', '"' => "'");
  64      /** @var array A third-pass normalization table for XPath syntax */
  65      var $normalizationTable3 = array('position()=' => '',
  66                              '/descendant-or-self::node()/' => "//", 'self::node()' => '.',
  67                              'parent::node()' => '..');
  68  
  69      /**
  70      * Constructor - creates an empty DOMIT_NodeList to store matching nodes
  71      */
  72  	function DOMIT_XPath() {
  73          require_once (DOMIT_INCLUDE_PATH . 'xml_domit_nodemaps.php');
  74          $this->nodeList = new DOMIT_NodeList();
  75      } //DOMIT_XPath
  76  
  77      /**
  78      * Parses the supplied "path"-based pattern
  79      * @param Object The node from which the search is called
  80      * @param string The pattern
  81      * @return Object The NodeList containing matching nodes
  82      */
  83      function &parsePattern(&$node, $pattern, $nodeIndex = 0) {
  84          $this->callingNode =& $node;
  85          $pattern = $this->normalize(trim($pattern));
  86  
  87          $this->splitPattern($pattern);
  88  
  89          $total = count($this->arPathSegments);
  90  
  91          //whole pattern level
  92          for ($i = 0; $i < $total; $i++) {
  93              $outerArray =& $this->arPathSegments[$i];
  94              $this->initSearch($outerArray);
  95  
  96              $outerTotal = count($outerArray);
  97              $isInitialMatchAttempt = true;
  98  
  99              //variable path segment level
 100              for ($j = 0; $j < $outerTotal; $j++) {
 101                  $innerArray =& $outerArray[$j];
 102                  $innerTotal = count($innerArray);
 103  
 104                  if (!$isInitialMatchAttempt) {
 105                      $this->searchType = DOMIT_XPATH_SEARCH_VARIABLE;
 106                  }
 107  
 108                  //pattern segment level
 109                  for ($k = 0; $k < $innerTotal; $k++) {
 110                      $currentPattern = $innerArray[$k];
 111  
 112                      if (($k == 0) && ($currentPattern == null)) {
 113                          if ($innerTotal == 1) {
 114                              $isInitialMatchAttempt = false;
 115                          }
 116                          //else just skip current step and don't alter searchType
 117                      }
 118                      else {
 119                          if (!$isInitialMatchAttempt && ($k > 0)) {
 120                              $this->searchType = DOMIT_XPATH_SEARCH_RELATIVE;
 121                          }
 122  
 123                          $this->currentSegment = $currentPattern;
 124                          $this->processPatternSegment();
 125                          $isInitialMatchAttempt = false;
 126                      }
 127                  }
 128              }
 129          }
 130  
 131          if ($nodeIndex > 0) {
 132              if ($nodeIndex <= count($this->globalNodeContainer)) {
 133                  return $this->globalNodeContainer[($nodeIndex - 1)];
 134              }
 135              else {
 136                  $null = null;
 137                  return $null;
 138              }
 139          }
 140  
 141          if (count($this->globalNodeContainer) != 0) {
 142              foreach ($this->globalNodeContainer as $key =>$value) {
 143                  $currNode =& $this->globalNodeContainer[$key];
 144                  $this->nodeList->appendNode($currNode);
 145              }
 146          }
 147  
 148          return $this->nodeList;
 149      } //parsePattern
 150  
 151      /**
 152      * Generates a new globalNodeContainer of matches
 153      */
 154  	function processPatternSegment() {
 155          $total = strlen($this->currentSegment);
 156          $this->charContainer = '';
 157          $this->localNodeContainer = array();
 158  
 159          for ($i = 0; $i < $total; $i++) {
 160  //            $this->currChar = $this->currentSegment{$i};
 161              $this->currChar = substr($this->currentSegment, $i, 1);
 162  
 163              switch ($this->currChar) {
 164                  case '@':
 165                      $this->selectAttribute(substr($this->currentSegment, ($this->currChar + 1)));
 166                      $this->updateNodeContainers();
 167                      return;
 168                      //break;
 169  
 170                  case '*':
 171                      if ($i == ($total - 1)) {
 172                          $this->selectNamedChild('*');
 173                      }
 174                      else {
 175                          $this->charContainer .= $this->currChar;
 176                      }
 177                      break;
 178  
 179                  case '.':
 180                      $this->charContainer .= $this->currChar;
 181  
 182                      if ($i == ($total - 1)) {
 183                          if ($this->charContainer == '..') {
 184                              $this->selectParent();
 185                          }
 186                          else {
 187                              return;
 188                          }
 189                      }
 190                      break;
 191  
 192                  case ')':
 193                      $this->charContainer .= $this->currChar;
 194                      $this->selectNodesByFunction();
 195                      break;
 196  
 197                  case '[':
 198                      $this->parsePredicate($this->charContainer,
 199                                      substr($this->currentSegment, ($i + 1)));
 200                      return;
 201                      //break;
 202  
 203                  default:
 204                      $this->charContainer .= $this->currChar;
 205  
 206              }
 207          }
 208  
 209          if ($this->charContainer != '') {
 210              $this->selectNamedChild($this->charContainer);
 211          }
 212  
 213          $this->updateNodeContainers();
 214      } //processPatternSegment
 215  
 216      /**
 217      * Replaces the global node container with the local node container
 218      */
 219  	function updateNodeContainers() {
 220          $this->globalNodeContainer =& $this->localNodeContainer;
 221          unset($this->localNodeContainer);
 222      } //updateNodeContainers
 223  
 224  
 225      /**
 226      * Parses a predicate expression [...]
 227      * @param string The pattern segment containing the node expression
 228      * @param string The pattern segment containing the predicate expression
 229      */
 230  	function parsePredicate($nodeName, $patternSegment) {
 231          $arPredicates =& explode('][', $patternSegment);
 232  
 233          $total = count($arPredicates);
 234  
 235          $lastIndex = $total - 1;
 236          $arPredicates[$lastIndex] = substr($arPredicates[$lastIndex],
 237                                          0, (strlen($arPredicates[$lastIndex]) - 1));
 238  
 239          for ($i = 0; $i < $total; $i++) {
 240              $isRecursive = ($this->searchType == DOMIT_XPATH_SEARCH_VARIABLE) ? true : false;
 241              $currPredicate = $arPredicates[$i];
 242  
 243              if (is_numeric($currPredicate)) {
 244                  if ($i == 0) {
 245                      $this->filterByIndex($nodeName, intval($currPredicate), $isRecursive);
 246                  }
 247                  else {
 248                      $this->refilterByIndex(intval($currPredicate));
 249                  }
 250              }
 251              else {
 252                  if ($i == 0) {
 253                      $this->selectNamedChild($nodeName);
 254                      $this->updateNodeContainers();
 255                  }
 256  
 257                  $phpExpression = $this->predicateToPHP($currPredicate);
 258                  $this->filterByPHPExpression($phpExpression);
 259              }
 260  
 261              $this->updateNodeContainers();
 262          }
 263  
 264          $this->charContainer = '';
 265      } //parsePredicate
 266  
 267      /**
 268      * Converts the predicate into PHP evaluable code
 269      * @param string The predicate
 270      * @return string The converted PHP expression
 271      */
 272  	function predicateToPHP($predicate) {
 273          $phpExpression = $predicate;
 274          $currChar = '';
 275          $charContainer = '';
 276          $totalChars = strlen($predicate);
 277  
 278          for ($i = 0; $i < $totalChars; $i++) {
 279              $currChar = substr($predicate, $i, 1);
 280  
 281              switch ($currChar) {
 282                  case '(':
 283                  case ')':
 284                  case ' ':
 285                      if ($charContainer != '') {
 286                          $convertedPredicate = $this->expressionToPHP($charContainer);
 287                          $phpExpression = str_replace($charContainer, $convertedPredicate, $phpExpression);
 288                          $charContainer = '';
 289                      }
 290                      break;
 291  
 292                  default:
 293                      $charContainer .= $currChar;
 294  
 295              }
 296          }
 297  
 298          if ($charContainer != '') {
 299              $convertedPredicate = $this->expressionToPHP($charContainer);
 300              $phpExpression = str_replace($charContainer, $convertedPredicate, $phpExpression);
 301          }
 302  
 303          return $phpExpression;
 304      } //predicateToPHP
 305  
 306  
 307      /**
 308      * Converts the predicate expression into a PHP expression
 309      * @param string The predicate expression
 310      * @return string The converted PHP expression
 311      */
 312  	function expressionToPHP($expression) {
 313          if ($expression == 'and') {
 314              $expression = '&&';
 315          }
 316          else if ($expression == 'or') {
 317              $expression = '||';
 318          }
 319          else if ($expression == 'not') {
 320              $expression = '!';
 321          }
 322          else {
 323              $expression = trim($expression);
 324  
 325              if (strpos($expression, '@') !== false) {
 326                  if (strpos($expression, '>=') !== false) {
 327                      $expression = str_replace('@', ('floatval($' . "contextNode->getAttribute('"), $expression);
 328                      $expression = str_replace('>=', "')) >= floatval(", $expression);
 329                      if (!is_numeric($expression)) $expression = str_replace('floatval', '', $expression);
 330                      $expression .= ')';
 331                  }
 332                  else if (strpos($expression, '<=') !== false) {
 333                      $expression = str_replace('@', ('floatval($' . "contextNode->getAttribute('"), $expression);
 334                      $expression = str_replace('<=', "')) <= floatval(", $expression);
 335                      if (!is_numeric($expression)) $expression = str_replace('floatval', '', $expression);
 336                      $expression .= ')';
 337                  }
 338                  else if (strpos($expression, '!=') !== false) {
 339                      $expression = str_replace('@', ('$' . "contextNode->getAttribute('"), $expression);
 340                      $expression = str_replace('!=', "') != ", $expression);
 341                  }
 342                  else if (strpos($expression, '=') !== false) {
 343                      $expression = str_replace('@', ('$' . "contextNode->getAttribute('"), $expression);
 344                      $expression = str_replace('=', "') == ", $expression);
 345                  }
 346                  else if (strpos($expression, '>') !== false) {
 347                      $expression = str_replace('>', "')) > floatval(", $expression); //reverse so > doesn't get replaced
 348                      $expression = str_replace('@', ('floatval($' . "contextNode->getAttribute('"), $expression);
 349                      if (!is_numeric($expression)) $expression = str_replace('floatval', '', $expression);
 350                      $expression .= ')';
 351                  }
 352                  else if (strpos($expression, '<') !== false) {
 353                      $expression = str_replace('@', ('floatval($' . "contextNode->getAttribute('"), $expression);
 354                      $expression = str_replace('<', "')) < floatval(", $expression);
 355                      if (!is_numeric($expression)) $expression = str_replace('floatval', '', $expression);
 356                      $expression .= ')';
 357                  }
 358                  else {
 359                      $expression = str_replace('@', ('$' . "contextNode->hasAttribute('"), $expression);
 360                      $expression.= "')";
 361                  }
 362              }
 363              else {
 364                  if (strpos($expression, '>=') !== false) {
 365                      $signPos = strpos($expression, '>=');
 366                      $elementName = trim(substr($expression, 0, $signPos));
 367                      $elementValue = trim(substr($expression, ($signPos + 2)));
 368  
 369                      $expression = '$' . "this->hasNamedChildElementGreaterThanOrEqualToValue(" .
 370                                      '$' . "contextNode, '" . $elementName . "', " .
 371                                      $elementValue . ')';
 372                  }
 373                  else if (strpos($expression, '<=') !== false) {
 374                      $signPos = strpos($expression, '>=');
 375                      $elementName = trim(substr($expression, 0, $signPos));
 376                      $elementValue = trim(substr($expression, ($signPos + 2)));
 377  
 378                      $expression = '$' . "this->hasNamedChildElementLessThanOrEqualToValue(" .
 379                                      '$' . "contextNode, '" . $elementName . "', " .
 380                                      $elementValue . ')';
 381                  }
 382                  else if (strpos($expression, '!=') !== false) {
 383                      $signPos = strpos($expression, '>=');
 384                      $elementName = trim(substr($expression, 0, $signPos));
 385                      $elementValue = trim(substr($expression, ($signPos + 2)));
 386  
 387                      $expression = '$' . "this->hasNamedChildElementNotEqualToValue(" .
 388                                      '$' . "contextNode, '" . $elementName . "', " .
 389                                      $elementValue . ')';
 390                  }
 391                  else if (strpos($expression, '=') !== false) {
 392                      $signPos = strpos($expression, '=');
 393                      $elementName = trim(substr($expression, 0, $signPos));
 394                      $elementValue = trim(substr($expression, ($signPos + 1)));
 395  
 396                      $expression = '$' . "this->hasNamedChildElementEqualToValue(" .
 397                                      '$' . "contextNode, '" . $elementName . "', " .
 398                                      $elementValue . ')';
 399  
 400                  }
 401                  else if (strpos($expression, '>') !== false) {
 402                      $signPos = strpos($expression, '=');
 403                      $elementName = trim(substr($expression, 0, $signPos));
 404                      $elementValue = trim(substr($expression, ($signPos + 1)));
 405  
 406                      $expression = '$' . "this->hasNamedChildElementGreaterThanValue(" .
 407                                      '$' . "contextNode, '" . $elementName . "', " .
 408                                      $elementValue . ')';
 409                  }
 410                  else if (strpos($expression, '<') !== false) {
 411                      $signPos = strpos($expression, '=');
 412                      $elementName = trim(substr($expression, 0, $signPos));
 413                      $elementValue = trim(substr($expression, ($signPos + 1)));
 414  
 415                      $expression = '$' . "this->hasNamedChildElementLessThanValue(" .
 416                                      '$' . "contextNode, '" . $elementName . "', " .
 417                                      $elementValue . ')';
 418                  }
 419                  else {
 420                      $expression = '$' . "this->hasNamedChildElement(" .
 421                                      '$' . "contextNode, '" . $expression . "')";
 422                  }
 423              }
 424          }
 425  
 426          return $expression;
 427      } //expressionToPHP
 428  
 429      /**
 430      * Selects nodes that match the predicate expression
 431      * @param string The predicate expression, formatted as a PHP expression
 432      */
 433  	function filterByPHPExpression($expression) {
 434          if (count($this->globalNodeContainer) != 0) {
 435              foreach ($this->globalNodeContainer as $key =>$value) {
 436                  $contextNode =& $this->globalNodeContainer[$key];
 437  
 438                  if ($contextNode->nodeType == DOMIT_ELEMENT_NODE) {
 439                      $evaluatedExpression = 'if (' . $expression . ") $" .
 440                                      'this->localNodeContainer[] =& $' . 'contextNode;';
 441                      eval($evaluatedExpression);
 442                  }
 443              }
 444          }
 445      } //filterByPHPExpression
 446  
 447      /**
 448      * Selects nodes with child elements that match the specified name
 449      * @param object The parent node of the child elements to match
 450      * @param string The tag name to match on
 451      * @return boolean True if a matching child element exists
 452      */
 453  	function hasNamedChildElement(&$parentNode, $nodeName) {
 454          $total = $parentNode->childCount;
 455  
 456          for ($i = 0; $i < $total; $i++) {
 457              $currNode =& $parentNode->childNodes[$i];
 458  
 459              if (($currNode->nodeType == DOMIT_ELEMENT_NODE) && ($currNode->nodeName == $nodeName)) {
 460                  return true;
 461              }
 462          }
 463  
 464          return false;
 465      } //hasNamedChildElement
 466  
 467      /**
 468      * Selects nodes with child elements that match the specified name and text value
 469      * @param object The parent node of the child elements to match
 470      * @param string The tag name to match on
 471      * @param string The text string to match on
 472      * @return boolean True if a matching child element exists
 473      */
 474  	function hasNamedChildElementEqualToValue(&$parentNode, $nodeName, $nodeValue) {
 475          $total = $parentNode->childCount;
 476  
 477          for ($i = 0; $i < $total; $i++) {
 478              $currNode =& $parentNode->childNodes[$i];
 479  
 480              if (($currNode->nodeType == DOMIT_ELEMENT_NODE) &&
 481                  ($currNode->nodeName == $nodeName) && ($currNode->getText() == $nodeValue)) {
 482                  return true;
 483              }
 484          }
 485  
 486          return false;
 487      } //hasNamedChildElementEqualToValue
 488  
 489      /**
 490      * Selects nodes with child elements that are greater than or equal to the specified name and value
 491      * @param object The parent node of the child elements to match
 492      * @param string The tag name to match on
 493      * @param string The text string to match on
 494      * @return boolean True if a matching child element exists
 495      */
 496  	function hasNamedChildElementGreaterThanOrEqualToValue(&$parentNode, $nodeName, $nodeValue) {
 497          $isNumeric = false;
 498  
 499          if (is_numeric($nodeValue)) {
 500              $isNumeric = true;
 501              $nodeValue = floatval($nodeValue);
 502          }
 503  
 504          $total = $parentNode->childCount;
 505  
 506          for ($i = 0; $i < $total; $i++) {
 507              $currNode =& $parentNode->childNodes[$i];
 508  
 509              if (($currNode->nodeType == DOMIT_ELEMENT_NODE) && ($currNode->nodeName == $nodeName)) {
 510                  if ($isNumeric) {$compareVal = floatval($currNode->getText());}
 511                  else {$compareVal = $currNode->getText();}
 512                  if ($compareVal >= $nodeValue) return true;
 513              }
 514          }
 515  
 516          return false;
 517      } //hasNamedChildElementGreaterThanOrEqualToValue
 518  
 519  
 520      /**
 521      * Selects nodes with child elements that are less than or equal to the specified name and value
 522      * @param object The parent node of the child elements to match
 523      * @param string The tag name to match on
 524      * @param string The text string to match on
 525      * @return boolean True if a matching child element exists
 526      */
 527  	function hasNamedChildElementLessThanOrEqualToValue(&$parentNode, $nodeName, $nodeValue) {
 528          $isNumeric = false;
 529  
 530          if (is_numeric($nodeValue)) {
 531              $isNumeric = true;
 532              $nodeValue = floatval($nodeValue);
 533          }
 534  
 535          $total = $parentNode->childCount;
 536  
 537          for ($i = 0; $i < $total; $i++) {
 538              $currNode =& $parentNode->childNodes[$i];
 539  
 540              if (($currNode->nodeType == DOMIT_ELEMENT_NODE) && ($currNode->nodeName == $nodeName)) {
 541                  if ($isNumeric) {$compareVal = floatval($currNode->getText());}
 542                  else {$compareVal = $currNode->getText();}
 543                  if ($compareVal <= $nodeValue) return true;
 544              }
 545          }
 546  
 547          return false;
 548      } //hasNamedChildElementLessThanOrEqualToValue
 549  
 550      /**
 551      * Selects nodes with child elements that are not equal to the specified name and value
 552      * @param object The parent node of the child elements to match
 553      * @param string The tag name to match on
 554      * @param string The text string to match on
 555      * @return boolean True if a matching child element exists
 556      */
 557  	function hasNamedChildElementNotEqualToValue(&$parentNode, $nodeName, $nodeValue) {
 558          $isNumeric = false;
 559  
 560          if (is_numeric($nodeValue)) {
 561              $isNumeric = true;
 562              $nodeValue = floatval($nodeValue);
 563          }
 564  
 565          $total = $parentNode->childCount;
 566  
 567          for ($i = 0; $i < $total; $i++) {
 568              $currNode =& $parentNode->childNodes[$i];
 569  
 570              if (($currNode->nodeType == DOMIT_ELEMENT_NODE) && ($currNode->nodeName == $nodeName)) {
 571                  if ($isNumeric) {$compareVal = floatval($currNode->getText());}
 572                  else {$compareVal = $currNode->getText();}
 573                  if ($compareVal != $nodeValue) return true;
 574              }
 575          }
 576  
 577          return false;
 578      } //hasNamedChildElementNotEqualToValue
 579  
 580          /**
 581      * Selects nodes with child elements that are greater than the specified name and value
 582      * @param object The parent node of the child elements to match
 583      * @param string The tag name to match on
 584      * @param string The text string to match on
 585      * @return boolean True if a matching child element exists
 586      */
 587  	function hasNamedChildElementGreaterThanValue(&$parentNode, $nodeName, $nodeValue) {
 588          $isNumeric = false;
 589  
 590          if (is_numeric($nodeValue)) {
 591              $isNumeric = true;
 592              $nodeValue = floatval($nodeValue);
 593          }
 594  
 595          $total = $parentNode->childCount;
 596  
 597          for ($i = 0; $i < $total; $i++) {
 598              $currNode =& $parentNode->childNodes[$i];
 599  
 600              if (($currNode->nodeType == DOMIT_ELEMENT_NODE) && ($currNode->nodeName == $nodeName)) {
 601                  if ($isNumeric) {$compareVal = floatval($currNode->getText());}
 602                  else {$compareVal = $currNode->getText();}
 603                  if ($compareVal > $nodeValue) return true;
 604              }
 605          }
 606  
 607          return false;
 608      } //hasNamedChildElementGreaterThanValue
 609  
 610  
 611      /**
 612      * Selects nodes with child elements that are less than the specified name and value
 613      * @param object The parent node of the child elements to match
 614      * @param string The tag name to match on
 615      * @param string The text string to match on
 616      * @return boolean True if a matching child element exists
 617      */
 618  	function hasNamedChildElementLessThanValue(&$parentNode, $nodeName, $nodeValue) {
 619          $isNumeric = false;
 620  
 621          if (is_numeric($nodeValue)) {
 622              $isNumeric = true;
 623              $nodeValue = floatval($nodeValue);
 624          }
 625  
 626          $total = $parentNode->childCount;
 627  
 628          for ($i = 0; $i < $total; $i++) {
 629              $currNode =& $parentNode->childNodes[$i];
 630  
 631              if (($currNode->nodeType == DOMIT_ELEMENT_NODE) && ($currNode->nodeName == $nodeName)) {
 632                  if ($isNumeric) {$compareVal = floatval($currNode->getText());}
 633                  else {$compareVal = $currNode->getText();}
 634                  if ($compareVal < $nodeValue) return true;
 635              }
 636          }
 637  
 638          return false;
 639      } //hasNamedChildElementLessThanValue
 640  
 641      /**
 642      * Selects named elements of the specified index
 643      * @param string The pattern segment containing the node expression
 644      * @param int The index (base 1) of the matching node
 645      * @param boolean True if the selection is to be performed recursively
 646      */
 647  	function refilterByIndex($index) {
 648          if ($index > 1) {
 649              if (count($this->globalNodeContainer) != 0) {
 650                  $counter = 0;
 651                  $lastParentID = null;
 652  
 653                  foreach ($this->globalNodeContainer as $key =>$value) {
 654                      $currNode =& $this->globalNodeContainer[$key];
 655  
 656                      if (($lastParentID != null) && ($currNode->parentNode->uid != $lastParentID)) {
 657                          $counter = 0;
 658                      }
 659  
 660                      $counter++;
 661  
 662                      if (($counter == $index) && ($currNode->parentNode->uid == $lastParentID)) {
 663                          $this->localNodeContainer[] =& $currNode;
 664                      }
 665  
 666                      $lastParentID = $currNode->parentNode->uid;
 667                  }
 668              }
 669          }
 670          else {
 671              $this->localNodeContainer =& $this->globalNodeContainer;
 672          }
 673      } //refilterByIndex
 674  
 675  
 676      /**
 677      * Selects named elements of the specified index
 678      * @param string The pattern segment containing the node expression
 679      * @param int The index (base 1) of the matching node
 680      * @param boolean True if the selection is to be performed recursively
 681      */
 682  	function filterByIndex($nodeName, $index, $deep) {
 683          if (count($this->globalNodeContainer) != 0) {
 684              foreach ($this->globalNodeContainer as $key =>$value) {
 685                  $currNode =& $this->globalNodeContainer[$key];
 686                  $this->_filterByIndex($currNode, $nodeName, $index, $deep);
 687              }
 688          }
 689      } //filterByIndex
 690  
 691      /**
 692      * Selects named elements of the specified index
 693      * @param object The context node
 694      * @param string The pattern segment containing the node expression
 695      * @param int The index (base 1) of the matching node
 696      * @param boolean True if the selection is to be performed recursively
 697      */
 698  	function _filterByIndex(&$contextNode, $nodeName, $index, $deep) {
 699          if (($contextNode->nodeType == DOMIT_ELEMENT_NODE) ||
 700              ($contextNode->nodeType == DOMIT_DOCUMENT_NODE)) {
 701              $total = $contextNode->childCount;
 702              $nodeCounter = 0;
 703  
 704              for ($i = 0; $i < $total; $i++) {
 705                  $currChildNode =& $contextNode->childNodes[$i];
 706  
 707                  if ($currChildNode->nodeName == $nodeName) {
 708                      $nodeCounter++;
 709  
 710                      if ($nodeCounter == $index) {
 711                          $this->localNodeContainer[] =& $currChildNode;
 712                      }
 713                  }
 714  
 715                  if ($deep) {
 716                      $this->_filterByIndex($currChildNode, $nodeName, $index, $deep);
 717                  }
 718              }
 719          }
 720      } //_filterByIndex
 721  
 722      /**
 723      * Selects named elements with the specified named child
 724      * @param string The pattern segment containing the node expression
 725      * @param string The tag name of the matching child
 726      * @param boolean True if the selection is to be performed recursively
 727      */
 728  	function filterByChildName($nodeName, $childName, $deep) {
 729          if (count($this->globalNodeContainer) != 0) {
 730              foreach ($this->globalNodeContainer as $key =>$value) {
 731                  $currNode =& $this->globalNodeContainer[$key];
 732                  $this->_filterByChildName($currNode, $nodeName, $childName, $deep);
 733              }
 734          }
 735      } //filterByChildName
 736  
 737      /**
 738      * Selects named elements with the specified named child
 739      * @param object The context node
 740      * @param string The pattern segment containing the node expression
 741      * @param string The tag name of the matching child
 742      * @param boolean True if the selection is to be performed recursively
 743      */
 744  	function _filterByChildName(&$contextNode, $nodeName, $childName, $deep) {
 745          if (($contextNode->nodeType == DOMIT_ELEMENT_NODE) ||
 746              ($contextNode->nodeType == DOMIT_DOCUMENT_NODE)) {
 747              $total = $contextNode->childCount;
 748  
 749              for ($i = 0; $i < $total; $i++) {
 750                  $currChildNode =& $contextNode->childNodes[$i];
 751  
 752                  if (($currChildNode->nodeName == $nodeName) &&
 753                      ($currChildNode->nodeType == DOMIT_ELEMENT_NODE)) {
 754                      $total2 = $currChildNode->childCount;
 755  
 756                      for ($j = 0; $j < $total2; $j++) {
 757                          $currChildChildNode =& $currChildNode->childNodes[$j];
 758  
 759                          if ($currChildChildNode->nodeName == $childName) {
 760                              $this->localNodeContainer[] =& $currChildNode;
 761                          }
 762                      }
 763                  }
 764  
 765                  if ($deep) {
 766                      $this->_filterByChildName($currChildNode, $nodeName, $childName, $deep);
 767                  }
 768              }
 769          }
 770      } //_filterByChildName
 771  
 772      /**
 773      * Selects named attributes of the current context nodes
 774      * @param string The attribute name, or * to match all attributes
 775      */
 776  	function selectAttribute($attrName) {
 777          if (count($this->globalNodeContainer) != 0) {
 778              foreach ($this->globalNodeContainer as $key =>$value) {
 779                  $currNode =& $this->globalNodeContainer[$key];
 780  
 781                  $isRecursive = ($this->searchType == DOMIT_XPATH_SEARCH_VARIABLE) ? true : false;
 782                  $this->_selectAttribute($currNode, $attrName, $isRecursive);
 783              }
 784          }
 785  
 786          $this->charContainer = '';
 787      } //selectAttribute
 788  
 789      /**
 790      * Selects all attributes of the context nodes
 791      * @param object The context node
 792      * @param string The attribute name, or * to match all attributes
 793      * @param boolean True if the selection is to be performed recursively
 794      */
 795  	function _selectAttribute(&$contextNode, $attrName, $deep) {
 796          if (($contextNode->nodeType == DOMIT_ELEMENT_NODE) ||
 797                  ($contextNode->nodeType == DOMIT_DOCUMENT_NODE)) {
 798              $total = $contextNode->childCount;
 799  
 800              for ($i = 0; $i < $total; $i++) {
 801                  $currNode =& $contextNode->childNodes[$i];
 802  
 803                  if ($currNode->nodeType == DOMIT_ELEMENT_NODE) {
 804                      if ($attrName == '*') {
 805                          $total2 = $currNode->attributes->getLength();
 806  
 807                          for ($j = 0; $j < $total2; $j++) {
 808                              $this->localNodeContainer[] =& $currNode->attributes->item($j);
 809                          }
 810                      }
 811                      else {
 812                          if ($currNode->hasAttribute($attrName)) {
 813                              $this->localNodeContainer[] =& $currNode->getAttributeNode($attrName);
 814                          }
 815                      }
 816                  }
 817  
 818                  if ($deep) {
 819                      $this->_selectAttribute($currNode, $attrName, $deep);
 820                  }
 821              }
 822          }
 823      } //_selectAttribute
 824  
 825  
 826      /**
 827      * Selects all child nodes of the current context nodes
 828      * @param string The element name
 829      */
 830  	function selectNamedChild($tagName) {
 831          if (count($this->globalNodeContainer) != 0) {
 832              foreach ($this->globalNodeContainer as $key =>$value) {
 833                  $currNode =& $this->globalNodeContainer[$key];
 834  
 835                  $isRecursive = ($this->searchType == DOMIT_XPATH_SEARCH_VARIABLE) ? true : false;
 836                  $this->_selectNamedChild($currNode, $tagName, $isRecursive);
 837              }
 838          }
 839  
 840          $this->charContainer = '';
 841      } //selectNamedChild
 842  
 843      /**
 844      * Selects all child nodes of the context node
 845      * @param object The context node
 846      * @param string The element name
 847      * @param boolean True if the selection is to be performed recursively
 848      */
 849  	function _selectNamedChild(&$contextNode, $tagName, $deep = false) {
 850          if (($contextNode->nodeType == DOMIT_ELEMENT_NODE) ||
 851              ($contextNode->nodeType == DOMIT_DOCUMENT_NODE)) {
 852              $total = $contextNode->childCount;
 853  
 854              for ($i = 0; $i < $total; $i++) {
 855                  $currChildNode =& $contextNode->childNodes[$i];
 856  
 857                  if (($currChildNode->nodeType == DOMIT_ELEMENT_NODE) ||
 858                      ($currChildNode->nodeType == DOMIT_DOCUMENT_NODE)) {
 859                      if (($tagName == '*') || ($tagName == $currChildNode->nodeName)) {
 860                          $this->localNodeContainer[] =& $currChildNode;
 861                      }
 862  
 863                      if ($deep) {
 864                          $this->_selectNamedChild($currChildNode, $tagName, $deep);
 865                      }
 866                  }
 867              }
 868          }
 869      } //_selectNamedChild
 870  
 871      /**
 872      * Selects parent node of the current context nodes
 873      */
 874  	function selectParent() {
 875          if (count($this->globalNodeContainer) != 0) {
 876              foreach ($this->globalNodeContainer as $key =>$value) {
 877                  $currNode =& $this->globalNodeContainer[$key];
 878  
 879                  $isRecursive = ($this->searchType == DOMIT_XPATH_SEARCH_VARIABLE) ? true : false;
 880                  $this->_selectParent($currNode, $isRecursive);
 881              }
 882          }
 883  
 884          $this->charContainer = '';
 885      } //selectParent
 886  
 887      /**
 888      * Selects parent node of the current context nodes
 889      * @param object The context node
 890      * @param boolean True if the selection is to be performed recursively
 891      */
 892  	function _selectParent(&$contextNode, $deep = false) {
 893          if ($contextNode->nodeType == DOMIT_ELEMENT_NODE) {
 894              if ($contextNode->parentNode != null) {
 895                  $this->localNodeContainer[] =& $contextNode->parentNode;
 896              }
 897          }
 898  
 899          if ($deep) {
 900              if (($contextNode->nodeType == DOMIT_ELEMENT_NODE) ||
 901                  ($contextNode->nodeType == DOMIT_DOCUMENT_NODE)) {
 902                  $total = $contextNode->childCount;
 903  
 904                  for ($i = 0; $i < $total; $i++) {
 905                      $currNode =& $contextNode->childNodes[$i];
 906  
 907                      if ($currNode->nodeType == DOMIT_ELEMENT_NODE) {
 908                          $this->_selectParent($contextNode, $deep);
 909                      }
 910                  }
 911              }
 912          }
 913      } //_selectParent
 914  
 915      /**
 916      * Selects any nodes of the current context nodes which match the given function
 917      */
 918  	function selectNodesByFunction() {
 919          $doProcess = false;
 920          $targetNodeType = -1;
 921  
 922          switch (strtolower(trim($this->charContainer))) {
 923              case 'last()':
 924                  if (count($this->globalNodeContainer) != 0) {
 925                      foreach ($this->globalNodeContainer as $key =>$value) {
 926                          $currNode =& $this->globalNodeContainer[$key];
 927  
 928                          if ($currNode->nodeType == DOMIT_ELEMENT_NODE) {
 929                              if ($currNode->lastChild != null) {
 930                                  $this->localNodeContainer[] =& $currNode->lastChild;
 931                              }
 932                          }
 933                      }
 934                  }
 935                  break;
 936  
 937              case 'text()':
 938                  $doProcess = true;
 939                  $targetNodeType = DOMIT_TEXT_NODE;
 940                  break;
 941  
 942              case 'comment()':
 943                  $doProcess = true;
 944                  $targetNodeType = DOMIT_COMMENT_NODE;
 945                  break;
 946  
 947              case 'processing-instruction()':
 948                  $doProcess = true;
 949                  $targetNodeType = DOMIT_PROCESSING_INSTRUCTION_NODE;
 950                  break;
 951          }
 952  
 953          if ($doProcess) {
 954              if (count($this->globalNodeContainer) != 0) {
 955                  foreach ($this->globalNodeContainer as $key =>$value) {
 956                      $currNode =& $this->globalNodeContainer[$key];
 957  
 958                      if ($currNode->nodeType == DOMIT_ELEMENT_NODE) {
 959                          $total = $currNode->childCount;
 960  
 961                          for ($j = 0; $j < $total; $j++) {
 962                              if ($currNode->childNodes[$j]->nodeType == $targetNodeType) {
 963                                  $this->localNodeContainer[] =& $currNode->childNodes[$j];
 964                              }
 965                          }
 966                      }
 967                  }
 968              }
 969          }
 970  
 971          $this->charContainer = '';
 972      } //selectNodesByFunction
 973  
 974      /**
 975      * Splits the supplied pattern into searchable segments
 976      * @param string The pattern
 977      */
 978  	function splitPattern($pattern) {
 979          //split multiple patterns if they exist (e.g. pattern1 | pattern2 | pattern3)
 980          $this->arPathSegments =& explode(DOMIT_XPATH_SEPARATOR_OR, $pattern);
 981  
 982          //split each pattern by relative path dividers (i.e., '//')
 983          $total = count($this->arPathSegments);
 984  
 985          for ($i = 0; $i < $total; $i++) {
 986              $this->arPathSegments[$i] =& explode(DOMIT_XPATH_SEPARATOR_RELATIVE, trim($this->arPathSegments[$i]));
 987  
 988              $currArray =& $this->arPathSegments[$i];
 989              $total2 = count($currArray);
 990  
 991              for ($j = 0; $j < $total2; $j++) {
 992                  $currArray[$j] =& explode(DOMIT_XPATH_SEPARATOR_ABSOLUTE, $currArray[$j]);
 993              }
 994          }
 995      } //splitPattern
 996  
 997      /**
 998      * Converts long XPath syntax into abbreviated XPath syntax
 999      * @param string The pattern
1000      * @return string The normalized pattern
1001      */
1002  	function normalize($pattern) {
1003          $pattern = strtr($pattern, $this->normalizationTable);
1004  
1005          while (strpos($pattern, '  ') !== false) {
1006              $pattern = str_replace('  ', ' ', $pattern);
1007          }
1008  
1009          $pattern = strtr($pattern, $this->normalizationTable2);
1010          $pattern = strtr($pattern, $this->normalizationTable3);
1011  
1012          return $pattern;
1013      } //normalize
1014  
1015      /**
1016      * Initializes the contextNode and searchType
1017      * @param array The current array of path segments
1018      * @return int The index of the first array item to begin the search at
1019      */
1020  	function initSearch(&$currArPathSegments) {
1021          $this->globalNodeContainer = array();
1022  
1023          if (is_null($currArPathSegments[0])) {
1024              if (count($currArPathSegments) == 1) {
1025                  //variable path
1026                  $this->searchType = DOMIT_XPATH_SEARCH_VARIABLE;
1027                  $this->globalNodeContainer[] =& $this->callingNode->ownerDocument;
1028              }
1029              else {
1030                  //absolute path
1031                  $this->searchType = DOMIT_XPATH_SEARCH_ABSOLUTE;
1032                  $this->globalNodeContainer[] =& $this->callingNode->ownerDocument;
1033              }
1034          }
1035          else {
1036              //relative path
1037              $this->searchType = DOMIT_XPATH_SEARCH_RELATIVE;
1038  
1039              if ($this->callingNode->uid != $this->callingNode->ownerDocument->uid) {
1040                  $this->globalNodeContainer[] =& $this->callingNode;
1041              }
1042              else {
1043                  $this->globalNodeContainer[] =& $this->callingNode->ownerDocument;
1044              }
1045          }
1046      } //initSearch
1047  } //DOMIT_XPath
1048  ?>


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