📄 xpath.class.php
字号:
* @param $message (string) Error message to be displayed. * @param $lineNumber (int) line number given by __LINE__ */ function _displayMessage($message, $lineNumber='-', $file='-') { // Display the error message. $err = '<b>XPath message from '.basename($file).':'.$lineNumber.'</b> '.$message."<br \>\n"; if ($this->properties['verboseLevel'] > 0) echo $err; } /** * Called to begin the debug run of a function. * * This method starts a <DIV><PRE> tag so that the entry to this function * is clear to the debugging user. Call _closeDebugFunction() at the * end of the function to create a clean box round the function call. * * @author Nigel Swinson <nigelswinson@users.sourceforge.net> * @author Sam Blum <bs_php@infeer.com> * @param $functionName (string) the name of the function we are beginning to debug * @param $bDebugFlag (bool) TRUE if we are to draw a call stack, FALSE otherwise * @return (array) the output from the microtime() function. * @see _closeDebugFunction() */ function _beginDebugFunction($functionName, $bDebugFlag) { if ($bDebugFlag) { $fileName = basename(__FILE__); static $color = array('green','blue','red','lime','fuchsia', 'aqua'); static $colIndex = -1; $colIndex++; echo '<div style="clear:both" align="left"> '; echo '<pre STYLE="border:solid thin '. $color[$colIndex % 6] . '; padding:5">'; echo '<a style="float:right;margin:5px" name="'.$this->iDebugNextLinkNumber.'Open" href="#'.$this->iDebugNextLinkNumber.'Close">Function Close '.$this->iDebugNextLinkNumber.'</a>'; echo "<STRONG>{$fileName} : {$functionName}</STRONG>"; echo '<hr style="clear:both">'; array_push($this->aDebugOpenLinks, $this->iDebugNextLinkNumber); $this->iDebugNextLinkNumber++; } if ($this->bClassProfiling) $this->_ProfBegin($FunctionName); return TRUE; } /** * Called to end the debug run of a function. * * This method ends a <DIV><PRE> block and reports the time since $aStartTime * is clear to the debugging user. * * @author Nigel Swinson <nigelswinson@users.sourceforge.net> * @param $functionName (string) the name of the function we are beginning to debug * @param $return_value (mixed) the return value from the function call that * we are debugging * @param $bDebugFlag (bool) TRUE if we are to draw a call stack, FALSE otherwise */ function _closeDebugFunction($functionName, $returnValue = "", $bDebugFlag) { if ($bDebugFlag) { echo "<hr>"; $iOpenLinkNumber = array_pop($this->aDebugOpenLinks); echo '<a style="float:right" name="'.$iOpenLinkNumber.'Close" href="#'.$iOpenLinkNumber.'Open">Function Open '.$iOpenLinkNumber.'</a>'; if (isSet($returnValue)) { if (is_array($returnValue)) echo "Return Value: ".print_r($returnValue)."\n"; else if (is_numeric($returnValue)) echo "Return Value: ".(string)$returnValue."\n"; else if (is_bool($returnValue)) echo "Return Value: ".($returnValue ? "TRUE" : "FALSE")."\n"; else echo "Return Value: \"".htmlspecialchars($returnValue)."\"\n"; } echo '<br style="clear:both">'; echo " \n</pre></div>"; } if ($this->bClassProfiling) $this->_ProfEnd($FunctionName); return TRUE; } /** * Profile begin call */ function _ProfBegin($sonFuncName) { static $entryTmpl = array ( 'start' => array(), 'recursiveCount' => 0, 'totTime' => 0, 'callCount' => 0 ); $now = explode(' ', microtime()); if (empty($this->callStack)) { $fatherFuncName = ''; } else { $fatherFuncName = $this->callStack[sizeOf($this->callStack)-1]; $fatherEntry = &$this->profile[$fatherFuncName]; } $this->callStack[] = $sonFuncName; if (!isSet($this->profile[$sonFuncName])) { $this->profile[$sonFuncName] = $entryTmpl; } $sonEntry = &$this->profile[$sonFuncName]; $sonEntry['callCount']++; // if we call the t's the same function let the time run, otherwise sum up if ($fatherFuncName == $sonFuncName) { $sonEntry['recursiveCount']++; } if (!empty($fatherFuncName)) { $last = $fatherEntry['start']; $fatherEntry['totTime'] += round( (($now[1] - $last[1]) + ($now[0] - $last[0]))*10000 ); $fatherEntry['start'] = 0; } $sonEntry['start'] = explode(' ', microtime()); } /** * Profile end call */ function _ProfEnd($sonFuncName) { $now = explode(' ', microtime()); array_pop($this->callStack); if (empty($this->callStack)) { $fatherFuncName = ''; } else { $fatherFuncName = $this->callStack[sizeOf($this->callStack)-1]; $fatherEntry = &$this->profile[$fatherFuncName]; } $sonEntry = &$this->profile[$sonFuncName]; if (empty($sonEntry)) { echo "ERROR in profEnd(): '$funcNam' not in list. Seams it was never started ;o)"; } $last = $sonEntry['start']; $sonEntry['totTime'] += round( (($now[1] - $last[1]) + ($now[0] - $last[0]))*10000 ); $sonEntry['start'] = 0; if (!empty($fatherEntry)) $fatherEntry['start'] = explode(' ', microtime()); } /** * Show profile gathered so far as HTML table */ function _ProfileToHtml() { $sortArr = array(); if (empty($this->profile)) return ''; reset($this->profile); while (list($funcName) = each($this->profile)) { $sortArrKey[] = $this->profile[$funcName]['totTime']; $sortArrVal[] = $funcName; } //echo '<pre>';var_dump($sortArrVal);echo '</pre>'; array_multisort ($sortArrKey, SORT_DESC, $sortArrVal ); //echo '<pre>';var_dump($sortArrVal);echo '</pre>'; $totTime = 0; $size = sizeOf($sortArrVal); for ($i=0; $i<$size; $i++) { $funcName = &$sortArrVal[$i]; $totTime += $this->profile[$funcName]['totTime']; } $out = '<table border="1">'; $out .='<tr align="center" bgcolor="#bcd6f1"><th>Function</th><th> % </th><th>Total [ms]</th><th># Call</th><th>[ms] per Call</th><th># Recursive</th></tr>'; for ($i=0; $i<$size; $i++) { $funcName = &$sortArrVal[$i]; $row = &$this->profile[$funcName]; $procent = round($row['totTime']*100/$totTime); if ($procent>20) $bgc = '#ff8080'; elseif ($procent>15) $bgc = '#ff9999'; elseif ($procent>10) $bgc = '#ffcccc'; elseif ($procent>5) $bgc = '#ffffcc'; else $bgc = '#66ff99'; $out .="<tr align='center' bgcolor='{$bgc}'>"; $out .='<td>'. $funcName .'</td><td>'. $procent .'% '.'</td><td>'. $row['totTime']/10 .'</td><td>'. $row['callCount'] .'</td><td>'. round($row['totTime']/10/$row['callCount'],2) .'</td><td>'. $row['recursiveCount'].'</td>'; $out .='</tr>'; } $out .= '</table> Total Time [' . $totTime/10 .'ms]' ; echo $out; return TRUE; } /** * Echo an XPath context for diagnostic purposes * * @param $context (array) An XPath context */ function _printContext($context) { echo "{$context['nodePath']}({$context['pos']}/{$context['size']})"; } /** * This is a debug helper function. It dumps the node-tree as HTML * * *QUICK AND DIRTY*. Needs some polishing. * * @param $node (array) A node * @param $indent (string) (optional, default=''). For internal recursive calls. */ function _treeDump($node, $indent = '') { $out = ''; // Get rid of recursion $parentName = empty($node['parentNode']) ? "SUPER ROOT" : $node['parentNode']['name']; unset($node['parentNode']); $node['parentNode'] = $parentName ; $out .= "NODE[{$node['name']}]\n"; foreach($node as $key => $val) { if ($key === 'childNodes') continue; if (is_Array($val)) { $out .= $indent . " [{$key}]\n" . arrayToStr($val, $indent . ' '); } else { $out .= $indent . " [{$key}] => '{$val}' \n"; } } if (!empty($node['childNodes'])) { $out .= $indent . " ['childNodes'] (Size = ".sizeOf($node['childNodes']).")\n"; foreach($node['childNodes'] as $key => $childNode) { $out .= $indent . " [$key] => " . $this->_treeDump($childNode, $indent . ' ') . "\n"; } } if (empty($indent)) { return "<pre>" . htmlspecialchars($out) . "</pre>"; } return $out; }} // END OF CLASS XPathBase/************************************************************************************************* ===============================================================================================* X P a t h E n g i n e - Class * ===============================================================================================************************************************************************************************/class XPathEngine extends XPathBase { // List of supported XPath axes. // What a stupid idea from W3C to take axes name containing a '-' (dash) // NOTE: We replace the '-' with '_' to avoid the conflict with the minus operator. // We will then do the same on the users Xpath querys // -sibling => _sibling // -or- => _or_ // // This array contains a list of all valid axes that can be evaluated in an // XPath query. var $axes = array ( 'ancestor', 'ancestor_or_self', 'attribute', 'child', 'descendant', 'descendant_or_self', 'following', 'following_sibling', 'namespace', 'parent', 'preceding', 'preceding_sibling', 'self' ); // List of supported XPath functions. // What a stupid idea from W3C to take function name containing a '-' (dash) // NOTE: We replace the '-' with '_' to avoid the conflict with the minus operator. // We will then do the same on the users Xpath querys // starts-with => starts_with // substring-before => substring_before // substring-after => substring_after // string-length => string_length // // This array contains a list of all valid functions that can be evaluated // in an XPath query. var $functions = array ( 'last', 'position', 'count', 'id', 'name', 'string', 'concat', 'starts_with', 'contains', 'substring_before', 'substring_after', 'substring', 'string_length', 'normalize_space', 'translate', 'boolean', 'not', 'true', 'false', 'lang', 'number', 'sum', 'floor', 'ceiling', 'round', 'x_lower', 'x_upper', 'generate_id' ); // List of supported XPath operators. // // This array contains a list of all valid operators that can be evaluated // in a predicate of an XPath query. The list is ordered by the // precedence of the operators (lowest precedence first). var $operators = array( ' or ', ' and ', '=', '!=', '<=', '<', '>=', '>', '+', '-', '*', ' div ', ' mod ', ' | '); // List of literals from the xPath string. var $axPathLiterals = array(); // The index and tree that is created during the analysis of an XML source. var $nodeIndex = array(); var $nodeRoot = array(); var $emptyNode = array( 'name' => '', // The tag name. E.g. In <FOO bar="aaa"/> it would be 'FOO' 'attributes' => array(), // The attributes of the tag E.g. In <FOO bar="aaa"/> it would be array('bar'=>'aaa') 'childNodes' => array(), // Array of pointers to child nodes. 'textParts' => array(), // Array of text parts between the cilderen E.g. <FOO>aa<A>bb<B/>cc</A>dd</FOO> -> array('aa','bb','cc','dd') 'parentNode' => NULL, // Pointer to parent node or NULL if this node is the 'super root' //-- *!* Following vars are set by the indexer and is for optimisation only *!* 'depth' => 0, // The tag depth (or tree level) starting with the root tag at 0. 'pos' => 0, // Is the zero-based position this node has in the parents 'childNodes'-list. 'contextPos' => 1, // Is the one-based position this node has by counting the siblings tags (tags with same name) 'xpath' => '' // Is the abs. XPath to this node. ); var $_indexIsDirty = FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -