| [ Index ] |
PHP Cross Reference of Joomla 1.5.26 DE |
[Summary view] [Print] [Text view]
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 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Wed Mar 28 15:54:07 2012 | Cross-referenced by PHPXref 0.7.1 |