?
Path : /home/admin/public_html/old/board/libraries/domit/ |
Current File : /home/admin/public_html/old/board/libraries/domit/xml_domit_xpath.php |
<?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}; $this->currChar = substr($this->currentSegment, $i, 1); 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 ?>