📄 xpath.class.inc
字号:
* Looks for a string within another string -- BUT the search-string must be located *outside* of any brackets.
*
* This method looks for a string within another string. Brackets in the
* string the method is looking through will be respected, which means that
* only if the string the method is looking for is located outside of
* brackets, the search will be successful.
*
* @param $term (string) String in which the search shall take place.
* @param $expression (string) String that should be searched.
* @return (int) This method returns -1 if no string was found,
* otherwise the offset at which the string was found.
*/
function _searchString($term, $expression) {
$bracketCounter = 0; // Record where we are in the brackets.
$leng = strlen($term);
$exprLeng = strlen($expression);
for ($i=0; $i<$leng; $i++) {
$char = $term[$i];
if ($char=='(' || $char=='[') {
$bracketCounter++;
continue;
}
elseif ($char==')' || $char==']') {
$bracketCounter--;
}
if ($bracketCounter == 0) {
// Check whether we can find the expression at this index.
if (substr($term, $i, $exprLeng) == $expression) return $i;
}
}
// Nothing was found.
return (-1);
}
/**
* Split a string by a searator-string -- BUT the separator-string must be located *outside* of any brackets.
*
* Returns an array of strings, each of which is a substring of string formed
* by splitting it on boundaries formed by the string separator.
*
* @param $separator (string) String that should be searched.
* @param $term (string) String in which the search shall take place.
* @return (array) see above
*/
function _bracketExplode($separator, $term) {
// Note that it doesn't make sense for $separator to itself contain (,),[ or ],
// but as this is a private function we should be ok.
$resultArr = array();
$bracketCounter = 0; // Record where we are in the brackets.
do { // BEGIN try block
// Check if any separator is in the term
$sepLeng = strlen($separator);
if (strpos($term, $separator)===FALSE) { // no separator found so end now
$resultArr[] = $term;
break; // try-block
}
// Make a substitute separator out of 'unused chars'.
$substituteSep = str_repeat(chr(2), $sepLeng);
// Now determine the first bracket '(' or '['.
$tmp1 = strpos($term, '(');
$tmp2 = strpos($term, '[');
if ($tmp1===FALSE) {
$startAt = (int)$tmp2;
} elseif ($tmp2===FALSE) {
$startAt = (int)$tmp1;
} else {
$startAt = min($tmp1, $tmp2);
}
// Get prefix string part before the first bracket.
$preStr = substr($term, 0, $startAt);
// Substitute separator in prefix string.
$preStr = str_replace($separator, $substituteSep, $preStr);
// Now get the rest-string (postfix string)
$postStr = substr($term, $startAt);
// Go all the way through the rest-string.
$strLeng = strlen($postStr);
for ($i=0; $i < $strLeng; $i++) {
$char = $postStr[$i];
// Spot (,),[,] and modify our bracket counter. Note there is an
// assumption here that you don't have a string(with[mis)matched]brackets.
// This should be ok as the dodgy string will be detected elsewhere.
if ($char=='(' || $char=='[') {
$bracketCounter++;
continue;
}
elseif ($char==')' || $char==']') {
$bracketCounter--;
}
// If no brackets surround us check for separator
if ($bracketCounter == 0) {
// Check whether we can find the expression starting at this index.
if ((substr($postStr, $i, $sepLeng) == $separator)) {
// Substitute the found separator
for ($j=0; $j<$sepLeng; $j++) {
$postStr[$i+$j] = $substituteSep[$j];
}
}
}
}
// Now explod using the substitute separator as key.
$resultArr = explode($substituteSep, $preStr . $postStr);
} while (FALSE); // End try block
// Return the results that we found. May be a array with 1 entry.
return $resultArr;
}
/**
* Split a string at it's groups, ie bracketed expressions
*
* Returns an array of strings, when concatenated together would produce the original
* string. ie a(b)cde(f)(g) would map to:
* array ('a', '(b)', cde', '(f)', '(g)')
*
* @param $string (string) The string to process
* @param $open (string) The substring for the open of a group
* @param $close (string) The substring for the close of a group
* @return (array) The parsed string, see above
*/
function _getEndGroups($string, $open='[', $close=']') {
// Note that it doesn't make sense for $separator to itself contain (,),[ or ],
// but as this is a private function we should be ok.
$resultArr = array();
do { // BEGIN try block
// Check if we have both an open and a close tag
if (empty($open) and empty($close)) { // no separator found so end now
$resultArr[] = $string;
break; // try-block
}
if (empty($string)) {
$resultArr[] = $string;
break; // try-block
}
while (!empty($string)) {
// Now determine the first bracket '(' or '['.
$openPos = strpos($string, $open);
$closePos = strpos($string, $close);
if ($openPos===FALSE || $closePos===FALSE) {
// Oh, no more groups to be found then. Quit
$resultArr[] = $string;
break;
}
// Sanity check
if ($openPos > $closePos) {
// Malformed string, dump the rest and quit.
$resultArr[] = $string;
break;
}
// Get prefix string part before the first bracket.
$preStr = substr($string, 0, $openPos);
// This is the first string that will go in our output
if (!empty($preStr))
$resultArr[] = $preStr;
// Skip over what we've proceed, including the open char
$string = substr($string, $openPos + 1 - strlen($string));
// Find the next open char and adjust our close char
//echo "close: $closePos\nopen: $openPos\n\n";
$closePos -= $openPos + 1;
$openPos = strpos($string, $open);
//echo "close: $closePos\nopen: $openPos\n\n";
// While we have found nesting...
while ($openPos && $closePos && ($closePos > $openPos)) {
// Find another close pos after the one we are looking at
$closePos = strpos($string, $close, $closePos + 1);
// And skip our open
$openPos = strpos($string, $open, $openPos + 1);
}
//echo "close: $closePos\nopen: $openPos\n\n";
// If we now have a close pos, then it's the end of the group.
if ($closePos === FALSE) {
// We didn't... so bail dumping what was left
$resultArr[] = $open.$string;
break;
}
// We did, so we can extract the group
$resultArr[] = $open.substr($string, 0, $closePos + 1);
// Skip what we have processed
$string = substr($string, $closePos + 1);
}
} while (FALSE); // End try block
// Return the results that we found. May be a array with 1 entry.
return $resultArr;
}
/**
* Retrieves a substring before a delimiter.
*
* This method retrieves everything from a string before a given delimiter,
* not including the delimiter.
*
* @param $string (string) String, from which the substring should be extracted.
* @param $delimiter (string) String containing the delimiter to use.
* @return (string) Substring from the original string before the delimiter.
* @see _afterstr()
*/
function _prestr(&$string, $delimiter, $offset=0) {
// Return the substring.
$offset = ($offset<0) ? 0 : $offset;
$pos = strpos($string, $delimiter, $offset);
if ($pos===FALSE) return $string; else return substr($string, 0, $pos);
}
/**
* Retrieves a substring after a delimiter.
*
* This method retrieves everything from a string after a given delimiter,
* not including the delimiter.
*
* @param $string (string) String, from which the substring should be extracted.
* @param $delimiter (string) String containing the delimiter to use.
* @return (string) Substring from the original string after the delimiter.
* @see _prestr()
*/
function _afterstr($string, $delimiter, $offset=0) {
$offset = ($offset<0) ? 0 : $offset;
// Return the substring.
return substr($string, strpos($string, $delimiter, $offset) + strlen($delimiter));
}
//-----------------------------------------------------------------------------------------
// XPathBase ------ Debug Stuff ------
//-----------------------------------------------------------------------------------------
/**
* Alter the verbose (error) level reporting.
*
* Pass an int. >0 to turn on, 0 to turn off. The higher the number, the
* higher the level of verbosity. By default, the class has a verbose level
* of 1.
*
* @param $levelOfVerbosity (int) default is 1 = on
*/
function setVerbose($levelOfVerbosity = 1) {
$level = -1;
if ($levelOfVerbosity === TRUE) {
$level = 1;
} elseif ($levelOfVerbosity === FALSE) {
$level = 0;
} elseif (is_numeric($levelOfVerbosity)) {
$level = $levelOfVerbosity;
}
if ($level >= 0) $this->properties['verboseLevel'] = $levelOfVerbosity;
}
/**
* Returns the last occured error message.
*
* @access public
* @return string (may be empty if there was no error at all)
* @see _setLastError(), _lastError
*/
function getLastError() {
return $this->_lastError;
}
/**
* Creates a textual error message and sets it.
*
* example: 'XPath error in THIS_FILE_NAME:LINE. Message: YOUR_MESSAGE';
*
* I don't think the message should include any markup because not everyone wants to debug
* into the browser window.
*
* You should call _displayError() rather than _setLastError() if you would like the message,
* dependant on their verbose settings, echoed to the screen.
*
* @param $message (string) a textual error message default is ''
* @param $line (int) the line number where the error occured, use __LINE__
* @see getLastError()
*/
function _setLastError($message='', $line='-', $file='-') {
$this->_lastError = 'XPath error in ' . basename($file) . ':' . $line . '. Message: ' . $message;
}
/**
* Displays an error message.
*
* This method displays an error messages depending on the users verbose settings
* and sets the last error message.
*
* If also possibly stops the execution of the script.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -