/includes/domit/xml_domit_xpath.php
PHP | 1047 lines | 931 code | 51 blank | 65 comment | 70 complexity | 17226e93e2b740844ce1ccb71da5f728 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1
- <?php
- /**
- * @package domit-xmlparser
- * @subpackage domit-xmlparser-main
- * @copyright (C) 2004 John Heinstein. All rights reserved
- * @license http://www.gnu.org/copyleft/lesser.html LGPL License
- * @author John Heinstein <johnkarl@nbnet.nb.ca>
- * @link http://www.engageinteractive.com/domit/ DOMIT! Home Page
- * DOMIT! is Free Software
- **/
- if (!defined('DOMIT_INCLUDE_PATH')) {
- define('DOMIT_INCLUDE_PATH', (dirname(__FILE__) . "/"));
- }
- /** Separator for absolute path */
- define('DOMIT_XPATH_SEPARATOR_ABSOLUTE', '/');
- /** Separator for relative path */
- define('DOMIT_XPATH_SEPARATOR_RELATIVE', '//');
- /** OR separator for multiple patterns */
- define('DOMIT_XPATH_SEPARATOR_OR', '|');
- /** Constant for an absolute path search (starting at the document root) */
- define('DOMIT_XPATH_SEARCH_ABSOLUTE', 0);
- /** Constant for a relative path search (starting at the level of the calling node) */
- define('DOMIT_XPATH_SEARCH_RELATIVE', 1);
- /** Constant for a variable path search (finds all matches, regardless of place in the hierarchy) */
- define('DOMIT_XPATH_SEARCH_VARIABLE', 2);
- /**
- * DOMIT! XPath is an XPath parser.
- */
- class DOMIT_XPath {
- /** @var Object The node from which the search is called */
- var $callingNode;
- /** @var Object The node that is the current parent of the search */
- var $searchType;
- /** @var array An array containing a series of path segments for which to search */
- var $arPathSegments = array();
- /** @var Object A DOMIT_NodeList of matching nodes */
- var $nodeList;
- /** @var string A temporary string container */
- var $charContainer;
- /** @var string The current character of the current pattern segment being parsed */
- var $currChar;
- /** @var string The current pattern segment being parsed */
- var $currentSegment;
- /** @var array A temporary node container for caching node references at the pattern level*/
- var $globalNodeContainer;
- /** @var array A temporary node container for caching node references at the pattern segment level */
- var $localNodeContainer;
- /** @var array Normalization table for XPath syntax */
- var $normalizationTable = array('child::' => '', 'self::' => '.',
- 'attribute::' => '@', 'descendant::' => '*//',
- "\t" => ' ', "\x0B" => ' ');
- /** @var array A second-pass normalization table for XPath syntax */
- var $normalizationTable2 = array(' =' => '=', '= ' => '=', ' <' => '<',
- ' >' => '>', '< ' => '<', '> ' => '>',
- ' !' => '!', '( ' => '(',
- ' )' => ')', ' ]' => ']', '] ' => ']',
- ' [' => '[', '[ ' => '[', ' /' => '/',
- '/ ' => '/', '"' => "'");
- /** @var array A third-pass normalization table for XPath syntax */
- var $normalizationTable3 = array('position()=' => '',
- '/descendant-or-self::node()/' => "//", 'self::node()' => '.',
- 'parent::node()' => '..');
- /**
- * Constructor - creates an empty DOMIT_NodeList to store matching nodes
- */
- function DOMIT_XPath() {
- require_once(DOMIT_INCLUDE_PATH . 'xml_domit_nodemaps.php');
- $this->nodeList = new DOMIT_NodeList();
- } //DOMIT_XPath
- /**
- * Parses the supplied "path"-based pattern
- * @param Object The node from which the search is called
- * @param string The pattern
- * @return Object The NodeList containing matching nodes
- */
- function &parsePattern(&$node, $pattern, $nodeIndex = 0) {
- $this->callingNode =& $node;
- $pattern = $this->normalize(trim($pattern));
- $this->splitPattern($pattern);
- $total = count($this->arPathSegments);
- //whole pattern level
- for ($i = 0; $i < $total; $i++) {
- $outerArray =& $this->arPathSegments[$i];
- $this->initSearch($outerArray);
- $outerTotal = count($outerArray);
- $isInitialMatchAttempt = true;
- //variable path segment level
- for ($j = 0; $j < $outerTotal; $j++) {
- $innerArray =& $outerArray[$j];
- $innerTotal = count($innerArray);
- if (!$isInitialMatchAttempt) {
- $this->searchType = DOMIT_XPATH_SEARCH_VARIABLE;
- }
- //pattern segment level
- for ($k = 0; $k < $innerTotal; $k++) {
- $currentPattern = $innerArray[$k];
- if (($k == 0) && ($currentPattern == null)) {
- if ($innerTotal == 1) {
- $isInitialMatchAttempt = false;
- }
- //else just skip current step and don't alter searchType
- }
- else {
- if (!$isInitialMatchAttempt && ($k > 0)) {
- $this->searchType = DOMIT_XPATH_SEARCH_RELATIVE;
- }
- $this->currentSegment = $currentPattern;
- $this->processPatternSegment();
- $isInitialMatchAttempt = false;
- }
- }
- }
- }
- if ($nodeIndex > 0) {
- if ($nodeIndex <= count($this->globalNodeContainer)) {
- return $this->globalNodeContainer[($nodeIndex - 1)];
- }
- else {
- $null = null;
- return $null;
- }
- }
- if (count($this->globalNodeContainer) != 0) {
- foreach ($this->globalNodeContainer as $key =>$value) {
- $currNode =& $this->globalNodeContainer[$key];
- $this->nodeList->appendNode($currNode);
- }
- }
- return $this->nodeList;
- } //parsePattern
- /**
- * Generates a new globalNodeContainer of matches
- */
- function processPatternSegment() {
- $total = strlen($this->currentSegment);
- $this->charContainer = '';
- $this->localNodeContainer = array();
- for ($i = 0; $i < $total; $i++) {
- $this->currChar = $this->currentSegment{$i};
- switch ($this->currChar) {
- case '@':
- $this->selectAttribute(substr($this->currentSegment, ($this->currChar + 1)));
- $this->updateNodeContainers();
- return;
- //break;
- case '*':
- if ($i == ($total - 1)) {
- $this->selectNamedChild('*');
- }
- else {
- $this->charContainer .= $this->currChar;
- }
- break;
- case '.':
- $this->charContainer .= $this->currChar;
- if ($i == ($total - 1)) {
- if ($this->charContainer == '..') {
- $this->selectParent();
- }
- else {
- return;
- }
- }
- break;
- case ')':
- $this->charContainer .= $this->currChar;
- $this->selectNodesByFunction();
- break;
- case '[':
- $this->parsePredicate($this->charContainer,
- substr($this->currentSegment, ($i + 1)));
- return;
- //break;
- default:
- $this->charContainer .= $this->currChar;
- }
- }
- if ($this->charContainer != '') {
- $this->selectNamedChild($this->charContainer);
- }
- $this->updateNodeContainers();
- } //processPatternSegment
- /**
- * Replaces the global node container with the local node container
- */
- function updateNodeContainers() {
- $this->globalNodeContainer =& $this->localNodeContainer;
- unset($this->localNodeContainer);
- } //updateNodeContainers
- /**
- * Parses a predicate expression [...]
- * @param string The pattern segment containing the node expression
- * @param string The pattern segment containing the predicate expression
- */
- function parsePredicate($nodeName, $patternSegment) {
- $arPredicates =& explode('][', $patternSegment);
- $total = count($arPredicates);
- $lastIndex = $total - 1;
- $arPredicates[$lastIndex] = substr($arPredicates[$lastIndex],
- 0, (strlen($arPredicates[$lastIndex]) - 1));
- for ($i = 0; $i < $total; $i++) {
- $isRecursive = ($this->searchType == DOMIT_XPATH_SEARCH_VARIABLE) ? true : false;
- $currPredicate = $arPredicates[$i];
- if (is_numeric($currPredicate)) {
- if ($i == 0) {
- $this->filterByIndex($nodeName, intval($currPredicate), $isRecursive);
- }
- else {
- $this->refilterByIndex(intval($currPredicate));
- }
- }
- else {
- if ($i == 0) {
- $this->selectNamedChild($nodeName);
- $this->updateNodeContainers();
- }
- $phpExpression = $this->predicateToPHP($currPredicate);
- $this->filterByPHPExpression($phpExpression);
- }
- $this->updateNodeContainers();
- }
- $this->charContainer = '';
- } //parsePredicate
- /**
- * Converts the predicate into PHP evaluable code
- * @param string The predicate
- * @return string The converted PHP expression
- */
- function predicateToPHP($predicate) {
- $phpExpression = $predicate;
- $currChar = '';
- $charContainer = '';
- $totalChars = strlen($predicate);
- for ($i = 0; $i < $totalChars; $i++) {
- $currChar = substr($predicate, $i, 1);
- switch ($currChar) {
- case '(':
- case ')':
- case ' ':
- if ($charContainer != '') {
- $convertedPredicate = $this->expressionToPHP($charContainer);
- $phpExpression = str_replace($charContainer, $convertedPredicate, $phpExpression);
- $charContainer = '';
- }
- break;
- default:
- $charContainer .= $currChar;
- }
- }
- if ($charContainer != '') {
- $convertedPredicate = $this->expressionToPHP($charContainer);
- $phpExpression = str_replace($charContainer, $convertedPredicate, $phpExpression);
- }
- return $phpExpression;
- } //predicateToPHP
- /**
- * Converts the predicate expression into a PHP expression
- * @param string The predicate expression
- * @return string The converted PHP expression
- */
- function expressionToPHP($expression) {
- if ($expression == 'and') {
- $expression = '&&';
- }
- else if ($expression == 'or') {
- $expression = '||';
- }
- else if ($expression == 'not') {
- $expression = '!';
- }
- else {
- $expression = trim($expression);
- if (strpos($expression, '@') !== false) {
- if (strpos($expression, '>=') !== false) {
- $expression = str_replace('@', ('floatval($' . "contextNode->getAttribute('"), $expression);
- $expression = str_replace('>=', "')) >= floatval(", $expression);
- if (!is_numeric($expression)) $expression = str_replace('floatval', '', $expression);
- $expression .= ')';
- }
- else if (strpos($expression, '<=') !== false) {
- $expression = str_replace('@', ('floatval($' . "contextNode->getAttribute('"), $expression);
- $expression = str_replace('<=', "')) <= floatval(", $expression);
- if (!is_numeric($expression)) $expression = str_replace('floatval', '', $expression);
- $expression .= ')';
- }
- else if (strpos($expression, '!=') !== false) {
- $expression = str_replace('@', ('$' . "contextNode->getAttribute('"), $expression);
- $expression = str_replace('!=', "') != ", $expression);
- }
- else if (strpos($expression, '=') !== false) {
- $expression = str_replace('@', ('$' . "contextNode->getAttribute('"), $expression);
- $expression = str_replace('=', "') == ", $expression);
- }
- else if (strpos($expression, '>') !== false) {
- $expression = str_replace('>', "')) > floatval(", $expression); //reverse so > doesn't get replaced
- $expression = str_replace('@', ('floatval($' . "contextNode->getAttribute('"), $expression);
- if (!is_numeric($expression)) $expression = str_replace('floatval', '', $expression);
- $expression .= ')';
- }
- else if (strpos($expression, '<') !== false) {
- $expression = str_replace('@', ('floatval($' . "contextNode->getAttribute('"), $expression);
- $expression = str_replace('<', "')) < floatval(", $expression);
- if (!is_numeric($expression)) $expression = str_replace('floatval', '', $expression);
- $expression .= ')';
- }
- else {
- $expression = str_replace('@', ('$' . "contextNode->hasAttribute('"), $expression);
- $expression.= "')";
- }
- }
- else {
- if (strpos($expression, '>=') !== false) {
- $signPos = strpos($expression, '>=');
- $elementName = trim(substr($expression, 0, $signPos));
- $elementValue = trim(substr($expression, ($signPos + 2)));
- $expression = '$' . "this->hasNamedChildElementGreaterThanOrEqualToValue(" .
- '$' . "contextNode, '" . $elementName . "', " .
- $elementValue . ')';
- }
- else if (strpos($expression, '<=') !== false) {
- $signPos = strpos($expression, '>=');
- $elementName = trim(substr($expression, 0, $signPos));
- $elementValue = trim(substr($expression, ($signPos + 2)));
- $expression = '$' . "this->hasNamedChildElementLessThanOrEqualToValue(" .
- '$' . "contextNode, '" . $elementName . "', " .
- $elementValue . ')';
- }
- else if (strpos($expression, '!=') !== false) {
- $signPos = strpos($expression, '>=');
- $elementName = trim(substr($expression, 0, $signPos));
- $elementValue = trim(substr($expression, ($signPos + 2)));
- $expression = '$' . "this->hasNamedChildElementNotEqualToValue(" .
- '$' . "contextNode, '" . $elementName . "', " .
- $elementValue . ')';
- }
- else if (strpos($expression, '=') !== false) {
- $signPos = strpos($expression, '=');
- $elementName = trim(substr($expression, 0, $signPos));
- $elementValue = trim(substr($expression, ($signPos + 1)));
- $expression = '$' . "this->hasNamedChildElementEqualToValue(" .
- '$' . "contextNode, '" . $elementName . "', " .
- $elementValue . ')';
- }
- else if (strpos($expression, '>') !== false) {
- $signPos = strpos($expression, '=');
- $elementName = trim(substr($expression, 0, $signPos));
- $elementValue = trim(substr($expression, ($signPos + 1)));
- $expression = '$' . "this->hasNamedChildElementGreaterThanValue(" .
- '$' . "contextNode, '" . $elementName . "', " .
- $elementValue . ')';
- }
- else if (strpos($expression, '<') !== false) {
- $signPos = strpos($expression, '=');
- $elementName = trim(substr($expression, 0, $signPos));
- $elementValue = trim(substr($expression, ($signPos + 1)));
- $expression = '$' . "this->hasNamedChildElementLessThanValue(" .
- '$' . "contextNode, '" . $elementName . "', " .
- $elementValue . ')';
- }
- else {
- $expression = '$' . "this->hasNamedChildElement(" .
- '$' . "contextNode, '" . $expression . "')";
- }
- }
- }
- return $expression;
- } //expressionToPHP
- /**
- * Selects nodes that match the predicate expression
- * @param string The predicate expression, formatted as a PHP expression
- */
- function filterByPHPExpression($expression) {
- if (count($this->globalNodeContainer) != 0) {
- foreach ($this->globalNodeContainer as $key =>$value) {
- $contextNode =& $this->globalNodeContainer[$key];
- if ($contextNode->nodeType == DOMIT_ELEMENT_NODE) {
- $evaluatedExpression = 'if (' . $expression . ") $" .
- 'this->localNodeContainer[] =& $' . 'contextNode;';
- eval($evaluatedExpression);
- }
- }
- }
- } //filterByPHPExpression
- /**
- * Selects nodes with child elements that match the specified name
- * @param object The parent node of the child elements to match
- * @param string The tag name to match on
- * @return boolean True if a matching child element exists
- */
- function hasNamedChildElement(&$parentNode, $nodeName) {
- $total = $parentNode->childCount;
- for ($i = 0; $i < $total; $i++) {
- $currNode =& $parentNode->childNodes[$i];
- if (($currNode->nodeType == DOMIT_ELEMENT_NODE) && ($currNode->nodeName == $nodeName)) {
- return true;
- }
- }
- return false;
- } //hasNamedChildElement
- /**
- * Selects nodes with child elements that match the specified name and text value
- * @param object The parent node of the child elements to match
- * @param string The tag name to match on
- * @param string The text string to match on
- * @return boolean True if a matching child element exists
- */
- function hasNamedChildElementEqualToValue(&$parentNode, $nodeName, $nodeValue) {
- $total = $parentNode->childCount;
- for ($i = 0; $i < $total; $i++) {
- $currNode =& $parentNode->childNodes[$i];
- if (($currNode->nodeType == DOMIT_ELEMENT_NODE) &&
- ($currNode->nodeName == $nodeName) && ($currNode->getText() == $nodeValue)) {
- return true;
- }
- }
- return false;
- } //hasNamedChildElementEqualToValue
- /**
- * Selects nodes with child elements that are greater than or equal to the specified name and value
- * @param object The parent node of the child elements to match
- * @param string The tag name to match on
- * @param string The text string to match on
- * @return boolean True if a matching child element exists
- */
- function hasNamedChildElementGreaterThanOrEqualToValue(&$parentNode, $nodeName, $nodeValue) {
- $isNumeric = false;
- if (is_numeric($nodeValue)) {
- $isNumeric = true;
- $nodeValue = floatval($nodeValue);
- }
- $total = $parentNode->childCount;
- for ($i = 0; $i < $total; $i++) {
- $currNode =& $parentNode->childNodes[$i];
- if (($currNode->nodeType == DOMIT_ELEMENT_NODE) && ($currNode->nodeName == $nodeName)) {
- if ($isNumeric) {$compareVal = floatval($currNode->getText());}
- else {$compareVal = $currNode->getText();}
- if ($compareVal >= $nodeValue) return true;
- }
- }
- return false;
- } //hasNamedChildElementGreaterThanOrEqualToValue
- /**
- * Selects nodes with child elements that are less than or equal to the specified name and value
- * @param object The parent node of the child elements to match
- * @param string The tag name to match on
- * @param string The text string to match on
- * @return boolean True if a matching child element exists
- */
- function hasNamedChildElementLessThanOrEqualToValue(&$parentNode, $nodeName, $nodeValue) {
- $isNumeric = false;
- if (is_numeric($nodeValue)) {
- $isNumeric = true;
- $nodeValue = floatval($nodeValue);
- }
- $total = $parentNode->childCount;
- for ($i = 0; $i < $total; $i++) {
- $currNode =& $parentNode->childNodes[$i];
- if (($currNode->nodeType == DOMIT_ELEMENT_NODE) && ($currNode->nodeName == $nodeName)) {
- if ($isNumeric) {$compareVal = floatval($currNode->getText());}
- else {$compareVal = $currNode->getText();}
- if ($compareVal <= $nodeValue) return true;
- }
- }
- return false;
- } //hasNamedChildElementLessThanOrEqualToValue
- /**
- * Selects nodes with child elements that are not equal to the specified name and value
- * @param object The parent node of the child elements to match
- * @param string The tag name to match on
- * @param string The text string to match on
- * @return boolean True if a matching child element exists
- */
- function hasNamedChildElementNotEqualToValue(&$parentNode, $nodeName, $nodeValue) {
- $isNumeric = false;
- if (is_numeric($nodeValue)) {
- $isNumeric = true;
- $nodeValue = floatval($nodeValue);
- }
- $total = $parentNode->childCount;
- for ($i = 0; $i < $total; $i++) {
- $currNode =& $parentNode->childNodes[$i];
- if (($currNode->nodeType == DOMIT_ELEMENT_NODE) && ($currNode->nodeName == $nodeName)) {
- if ($isNumeric) {$compareVal = floatval($currNode->getText());}
- else {$compareVal = $currNode->getText();}
- if ($compareVal != $nodeValue) return true;
- }
- }
- return false;
- } //hasNamedChildElementNotEqualToValue
- /**
- * Selects nodes with child elements that are greater than the specified name and value
- * @param object The parent node of the child elements to match
- * @param string The tag name to match on
- * @param string The text string to match on
- * @return boolean True if a matching child element exists
- */
- function hasNamedChildElementGreaterThanValue(&$parentNode, $nodeName, $nodeValue) {
- $isNumeric = false;
- if (is_numeric($nodeValue)) {
- $isNumeric = true;
- $nodeValue = floatval($nodeValue);
- }
- $total = $parentNode->childCount;
- for ($i = 0; $i < $total; $i++) {
- $currNode =& $parentNode->childNodes[$i];
- if (($currNode->nodeType == DOMIT_ELEMENT_NODE) && ($currNode->nodeName == $nodeName)) {
- if ($isNumeric) {$compareVal = floatval($currNode->getText());}
- else {$compareVal = $currNode->getText();}
- if ($compareVal > $nodeValue) return true;
- }
- }
- return false;
- } //hasNamedChildElementGreaterThanValue
- /**
- * Selects nodes with child elements that are less than the specified name and value
- * @param object The parent node of the child elements to match
- * @param string The tag name to match on
- * @param string The text string to match on
- * @return boolean True if a matching child element exists
- */
- function hasNamedChildElementLessThanValue(&$parentNode, $nodeName, $nodeValue) {
- $isNumeric = false;
- if (is_numeric($nodeValue)) {
- $isNumeric = true;
- $nodeValue = floatval($nodeValue);
- }
- $total = $parentNode->childCount;
- for ($i = 0; $i < $total; $i++) {
- $currNode =& $parentNode->childNodes[$i];
- if (($currNode->nodeType == DOMIT_ELEMENT_NODE) && ($currNode->nodeName == $nodeName)) {
- if ($isNumeric) {$compareVal = floatval($currNode->getText());}
- else {$compareVal = $currNode->getText();}
- if ($compareVal < $nodeValue) return true;
- }
- }
- return false;
- } //hasNamedChildElementLessThanValue
- /**
- * Selects named elements of the specified index
- * @param string The pattern segment containing the node expression
- * @param int The index (base 1) of the matching node
- * @param boolean True if the selection is to be performed recursively
- */
- function refilterByIndex($index) {
- if ($index > 1) {
- if (count($this->globalNodeContainer) != 0) {
- $counter = 0;
- $lastParentID = null;
- foreach ($this->globalNodeContainer as $key =>$value) {
- $currNode =& $this->globalNodeContainer[$key];
- if (($lastParentID != null) && ($currNode->parentNode->uid != $lastParentID)) {
- $counter = 0;
- }
- $counter++;
- if (($counter == $index) && ($currNode->parentNode->uid == $lastParentID)) {
- $this->localNodeContainer[] =& $currNode;
- }
- $lastParentID = $currNode->parentNode->uid;
- }
- }
- }
- else {
- $this->localNodeContainer =& $this->globalNodeContainer;
- }
- } //refilterByIndex
- /**
- * Selects named elements of the specified index
- * @param string The pattern segment containing the node expression
- * @param int The index (base 1) of the matching node
- * @param boolean True if the selection is to be performed recursively
- */
- function filterByIndex($nodeName, $index, $deep) {
- if (count($this->globalNodeContainer) != 0) {
- foreach ($this->globalNodeContainer as $key =>$value) {
- $currNode =& $this->globalNodeContainer[$key];
- $this->_filterByIndex($currNode, $nodeName, $index, $deep);
- }
- }
- } //filterByIndex
- /**
- * Selects named elements of the specified index
- * @param object The context node
- * @param string The pattern segment containing the node expression
- * @param int The index (base 1) of the matching node
- * @param boolean True if the selection is to be performed recursively
- */
- function _filterByIndex(&$contextNode, $nodeName, $index, $deep) {
- if (($contextNode->nodeType == DOMIT_ELEMENT_NODE) ||
- ($contextNode->nodeType == DOMIT_DOCUMENT_NODE)) {
- $total = $contextNode->childCount;
- $nodeCounter = 0;
- for ($i = 0; $i < $total; $i++) {
- $currChildNode =& $contextNode->childNodes[$i];
- if ($currChildNode->nodeName == $nodeName) {
- $nodeCounter++;
- if ($nodeCounter == $index) {
- $this->localNodeContainer[] =& $currChildNode;
- }
- }
- if ($deep) {
- $this->_filterByIndex($currChildNode, $nodeName, $index, $deep);
- }
- }
- }
- } //_filterByIndex
- /**
- * Selects named elements with the specified named child
- * @param string The pattern segment containing the node expression
- * @param string The tag name of the matching child
- * @param boolean True if the selection is to be performed recursively
- */
- function filterByChildName($nodeName, $childName, $deep) {
- if (count($this->globalNodeContainer) != 0) {
- foreach ($this->globalNodeContainer as $key =>$value) {
- $currNode =& $this->globalNodeContainer[$key];
- $this->_filterByChildName($currNode, $nodeName, $childName, $deep);
- }
- }
- } //filterByChildName
- /**
- * Selects named elements with the specified named child
- * @param object The context node
- * @param string The pattern segment containing the node expression
- * @param string The tag name of the matching child
- * @param boolean True if the selection is to be performed recursively
- */
- function _filterByChildName(&$contextNode, $nodeName, $childName, $deep) {
- if (($contextNode->nodeType == DOMIT_ELEMENT_NODE) ||
- ($contextNode->nodeType == DOMIT_DOCUMENT_NODE)) {
- $total = $contextNode->childCount;
- for ($i = 0; $i < $total; $i++) {
- $currChildNode =& $contextNode->childNodes[$i];
- if (($currChildNode->nodeName == $nodeName) &&
- ($currChildNode->nodeType == DOMIT_ELEMENT_NODE)) {
- $total2 = $currChildNode->childCount;
- for ($j = 0; $j < $total2; $j++) {
- $currChildChildNode =& $currChildNode->childNodes[$j];
- if ($currChildChildNode->nodeName == $childName) {
- $this->localNodeContainer[] =& $currChildNode;
- }
- }
- }
- if ($deep) {
- $this->_filterByChildName($currChildNode, $nodeName, $childName, $deep);
- }
- }
- }
- } //_filterByChildName
- /**
- * Selects named attributes of the current context nodes
- * @param string The attribute name, or * to match all attributes
- */
- function selectAttribute($attrName) {
- if (count($this->globalNodeContainer) != 0) {
- foreach ($this->globalNodeContainer as $key =>$value) {
- $currNode =& $this->globalNodeContainer[$key];
- $isRecursive = ($this->searchType == DOMIT_XPATH_SEARCH_VARIABLE) ? true : false;
- $this->_selectAttribute($currNode, $attrName, $isRecursive);
- }
- }
- $this->charContainer = '';
- } //selectAttribute
- /**
- * Selects all attributes of the context nodes
- * @param object The context node
- * @param string The attribute name, or * to match all attributes
- * @param boolean True if the selection is to be performed recursively
- */
- function _selectAttribute(&$contextNode, $attrName, $deep) {
- if (($contextNode->nodeType == DOMIT_ELEMENT_NODE) ||
- ($contextNode->nodeType == DOMIT_DOCUMENT_NODE)) {
- $total = $contextNode->childCount;
- for ($i = 0; $i < $total; $i++) {
- $currNode =& $contextNode->childNodes[$i];
- if ($currNode->nodeType == DOMIT_ELEMENT_NODE) {
- if ($attrName == '*') {
- $total2 = $currNode->attributes->getLength();
- for ($j = 0; $j < $total2; $j++) {
- $this->localNodeContainer[] =& $currNode->attributes->item($j);
- }
- }
- else {
- if ($currNode->hasAttribute($attrName)) {
- $this->localNodeContainer[] =& $currNode->getAttributeNode($attrName);
- }
- }
- }
- if ($deep) {
- $this->_selectAttribute($currNode, $attrName, $deep);
- }
- }
- }
- } //_selectAttribute
- /**
- * Selects all child nodes of the current context nodes
- * @param string The element name
- */
- function selectNamedChild($tagName) {
- if (count($this->globalNodeContainer) != 0) {
- foreach ($this->globalNodeContainer as $key =>$value) {
- $currNode =& $this->globalNodeContainer[$key];
- $isRecursive = ($this->searchType == DOMIT_XPATH_SEARCH_VARIABLE) ? true : false;
- $this->_selectNamedChild($currNode, $tagName, $isRecursive);
- }
- }
- $this->charContainer = '';
- } //selectNamedChild
- /**
- * Selects all child nodes of the context node
- * @param object The context node
- * @param string The element name
- * @param boolean True if the selection is to be performed recursively
- */
- function _selectNamedChild(&$contextNode, $tagName, $deep = false) {
- if (($contextNode->nodeType == DOMIT_ELEMENT_NODE) ||
- ($contextNode->nodeType == DOMIT_DOCUMENT_NODE)) {
- $total = $contextNode->childCount;
- for ($i = 0; $i < $total; $i++) {
- $currChildNode =& $contextNode->childNodes[$i];
- if (($currChildNode->nodeType == DOMIT_ELEMENT_NODE) ||
- ($currChildNode->nodeType == DOMIT_DOCUMENT_NODE)) {
- if (($tagName == '*') || ($tagName == $currChildNode->nodeName)) {
- $this->localNodeContainer[] =& $currChildNode;
- }
- if ($deep) {
- $this->_selectNamedChild($currChildNode, $tagName, $deep);
- }
- }
- }
- }
- } //_selectNamedChild
- /**
- * Selects parent node of the current context nodes
- */
- function selectParent() {
- if (count($this->globalNodeContainer) != 0) {
- foreach ($this->globalNodeContainer as $key =>$value) {
- $currNode =& $this->globalNodeContainer[$key];
- $isRecursive = ($this->searchType == DOMIT_XPATH_SEARCH_VARIABLE) ? true : false;
- $this->_selectParent($currNode, $isRecursive);
- }
- }
- $this->charContainer = '';
- } //selectParent
- /**
- * Selects parent node of the current context nodes
- * @param object The context node
- * @param boolean True if the selection is to be performed recursively
- */
- function _selectParent(&$contextNode, $deep = false) {
- if ($contextNode->nodeType == DOMIT_ELEMENT_NODE) {
- if ($contextNode->parentNode != null) {
- $this->localNodeContainer[] =& $contextNode->parentNode;
- }
- }
- if ($deep) {
- if (($contextNode->nodeType == DOMIT_ELEMENT_NODE) ||
- ($contextNode->nodeType == DOMIT_DOCUMENT_NODE)) {
- $total = $contextNode->childCount;
- for ($i = 0; $i < $total; $i++) {
- $currNode =& $contextNode->childNodes[$i];
- if ($currNode->nodeType == DOMIT_ELEMENT_NODE) {
- $this->_selectParent($contextNode, $deep);
- }
- }
- }
- }
- } //_selectParent
- /**
- * Selects any nodes of the current context nodes which match the given function
- */
- function selectNodesByFunction() {
- $doProcess = false;
- $targetNodeType = -1;
- switch (strtolower(trim($this->charContainer))) {
- case 'last()':
- if (count($this->globalNodeContainer) != 0) {
- foreach ($this->globalNodeContainer as $key =>$value) {
- $currNode =& $this->globalNodeContainer[$key];
- if ($currNode->nodeType == DOMIT_ELEMENT_NODE) {
- if ($currNode->lastChild != null) {
- $this->localNodeContainer[] =& $currNode->lastChild;
- }
- }
- }
- }
- break;
- case 'text()':
- $doProcess = true;
- $targetNodeType = DOMIT_TEXT_NODE;
- break;
- case 'comment()':
- $doProcess = true;
- $targetNodeType = DOMIT_COMMENT_NODE;
- break;
- case 'processing-instruction()':
- $doProcess = true;
- $targetNodeType = DOMIT_PROCESSING_INSTRUCTION_NODE;
- break;
- }
- if ($doProcess) {
- if (count($this->globalNodeContainer) != 0) {
- foreach ($this->globalNodeContainer as $key =>$value) {
- $currNode =& $this->globalNodeContainer[$key];
- if ($currNode->nodeType == DOMIT_ELEMENT_NODE) {
- $total = $currNode->childCount;
- for ($j = 0; $j < $total; $j++) {
- if ($currNode->childNodes[$j]->nodeType == $targetNodeType) {
- $this->localNodeContainer[] =& $currNode->childNodes[$j];
- }
- }
- }
- }
- }
- }
- $this->charContainer = '';
- } //selectNodesByFunction
- /**
- * Splits the supplied pattern into searchable segments
- * @param string The pattern
- */
- function splitPattern($pattern) {
- //split multiple patterns if they exist (e.g. pattern1 | pattern2 | pattern3)
- $this->arPathSegments =& explode(DOMIT_XPATH_SEPARATOR_OR, $pattern);
- //split each pattern by relative path dividers (i.e., '//')
- $total = count($this->arPathSegments);
- for ($i = 0; $i < $total; $i++) {
- $this->arPathSegments[$i] =& explode(DOMIT_XPATH_SEPARATOR_RELATIVE, trim($this->arPathSegments[$i]));
- $currArray =& $this->arPathSegments[$i];
- $total2 = count($currArray);
- for ($j = 0; $j < $total2; $j++) {
- $currArray[$j] =& explode(DOMIT_XPATH_SEPARATOR_ABSOLUTE, $currArray[$j]);
- }
- }
- } //splitPattern
- /**
- * Converts long XPath syntax into abbreviated XPath syntax
- * @param string The pattern
- * @return string The normalized pattern
- */
- function normalize($pattern) {
- $pattern = strtr($pattern, $this->normalizationTable);
- while (strpos($pattern, ' ') !== false) {
- $pattern = str_replace(' ', ' ', $pattern);
- }
- $pattern = strtr($pattern, $this->normalizationTable2);
- $pattern = strtr($pattern, $this->normalizationTable3);
- return $pattern;
- } //normalize
- /**
- * Initializes the contextNode and searchType
- * @param array The current array of path segments
- * @return int The index of the first array item to begin the search at
- */
- function initSearch(&$currArPathSegments) {
- $this->globalNodeContainer = array();
- if (is_null($currArPathSegments[0])) {
- if (count($currArPathSegments) == 1) {
- //variable path
- $this->searchType = DOMIT_XPATH_SEARCH_VARIABLE;
- $this->globalNodeContainer[] =& $this->callingNode->ownerDocument;
- }
- else {
- //absolute path
- $this->searchType = DOMIT_XPATH_SEARCH_ABSOLUTE;
- $this->globalNodeContainer[] =& $this->callingNode->ownerDocument;
- }
- }
- else {
- //relative path
- $this->searchType = DOMIT_XPATH_SEARCH_RELATIVE;
- if ($this->callingNode->uid != $this->callingNode->ownerDocument->uid) {
- $this->globalNodeContainer[] =& $this->callingNode;
- }
- else {
- $this->globalNodeContainer[] =& $this->callingNode->ownerDocument;
- }
- }
- } //initSearch
- } //DOMIT_XPath
- ?>