[ Index ] |
|
Code source de Joomla 1.0.13 |
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 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Wed Nov 21 14:43:32 2007 | par Balluche grâce à PHPXref 0.7 |
![]() |