[ Index ]
 

Code source de Joomla 1.0.13

Accédez au Source d'autres logiciels libres

title

Body

[fermer]

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


Généré le : Wed Nov 21 14:43:32 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics