📄 xpathpredicate.cpp
字号:
predTokens.insert(tokens[i], iT + i);
}
}
++iT;
}
// check for '-' in node names versus operator
priv_parseCheckMinus(predTokens);
// remove all whitespace
priv_parseRemoveWhitespace(predTokens);
// concatinate operators & empty functions
priv_parseConcatOperators(predTokens);
// concatinate non-operator, non-paren tokens
priv_parseConcatNonOperators(predTokens);
// check for non-functions
priv_checkForNotFunctions(predTokens, *this);
// evaluate into XPathTokens
Array<XPathToken> results;
iT = 0;
while( iT < predTokens.getSize() ) {
String token = predTokens[iT];
if( priv_isOperator(token) ) {
results.append( XPathToken(token, XPathToken::OPERATOR) );
}
else if( token == "(" || token == ")" ) {
results.append( XPathToken(token, XPathToken::PAREN) );
}
else if( hasFunction(token) ) {
results.append( XPathToken(token, XPathToken::FUNCTION) );
}
else if( token.isValidDouble() ) {
if( token.isValidInt() ) {
results.append( XPathToken(token, XPathToken::NUMBER_INT) );
}
else {
results.append( XPathToken(token, XPathToken::NUMBER_DBL) );
}
}
else if( token == "true" || token == "false" ) {
results.append( XPathToken(token, XPathToken::BOOLEAN) );
}
else if( (token.beginsWith("\"") && token.endsWith("\"")) ||
(token.beginsWith("\'") && token.endsWith("\'")) ) {
results.append( XPathToken(token.stripFromLeft(1).stripFromRight(1), XPathToken::STRING) );
}
else {
results.append( XPathToken(token, XPathToken::NODESET) );
}
++iT;
}
return (results);
}
// ---------------------------------------------------------------------------------------------------------------------
bool XPathPredicate::hasFunction( String function )
{
for( int i = 0; i < m_functions.getSize(); ++i ) {
if( function == m_functions[i]->getName() ) {
return (true);
}
}
return (false);
}
// ---------------------------------------------------------------------------------------------------------------------
XPathFunction* XPathPredicate::getFunction( String function )
{
for( int i = 0; i < m_functions.getSize(); ++i ) {
if( function == m_functions[i]->getName() ) {
return (m_functions[i]);
}
}
return (0);
}
// ---------------------------------------------------------------------------------------------------------------------
const XPathFunction* XPathPredicate::getFunction( String function ) const
{
return ((XPathPredicate*)this)->getFunction(function);
}
// ---------------------------------------------------------------------------------------------------------------------
void XPathPredicate::addFunction( XPathFunction* function )
{
if( !hasFunction(function->getName()) ) {
m_functions.append(function);
}
}
// ---------------------------------------------------------------------------------------------------------------------
void XPathPredicate::removeFunction( String function )
{
for( int i = 0; i < m_functions.getSize(); ++i ) {
if( function == m_functions[i]->getName() ) {
m_functions.remove(i);
break;
}
}
}
// ---------------------------------------------------------------------------------------------------------------------
XPathToken XPathPredicate::evaluate( Array<XPathToken> predicate, Array<DomNode*> search, DomNode* context )
{
Array<XPathToken> wrkPredicate = predicate.copy();
while(true) {
int lastParen = -1;
for( int i = 0; i < wrkPredicate.getSize(); ++i ) {
String value = wrkPredicate[i].getValueString();
if( value == "(" ) {
lastParen = i;
}
else {
if( value == ")" ) {
if( lastParen <= 0 ) {
throw XPathException($("Invalid XPath expression given"));
}
int begIdx = lastParen + 1;
int endIdx = i - 1;
int begRmv = lastParen;
int endRmv = i;
bool func = false;
if( lastParen >= 1 ) {
if( wrkPredicate[lastParen - 1].getType() == XPathToken::FUNCTION ) {
begIdx -= 2;
endIdx += 1;
begRmv -= 1;
func = true;
}
}
XPathToken result = evaluateSection(wrkPredicate, search, context, begIdx, endIdx, func);
for( int i = endRmv; i >= begRmv; --i ) {
wrkPredicate.remove(i);
}
wrkPredicate.insert(result, begRmv);
break;
}
}
}
if( lastParen == -1 ) {
int wrkSize = wrkPredicate.getSize();
if( wrkSize == 1 ) {
return wrkPredicate[0];
}
return evaluateSection(wrkPredicate, search, context, 0, wrkPredicate.getSize()-1, false);
}
}
return XPathToken();
}
// ---------------------------------------------------------------------------------------------------------------------
XPathToken XPathPredicate::evaluateSection( Array<XPathToken> predicate, Array<DomNode*> search, DomNode* context, int begIdx, int endIdx, bool func )
{
if( func ) {
String functionName = predicate[begIdx].getValueString();
Array<XPathToken> parms;
if( predicate[begIdx+1].getValueString() != "(" && predicate[endIdx].getValueString() != ")" ) {
throw XPathException($("Invalid parameters to function given to XPathPredicate::evaluateSection"));
}
int lastBeg = begIdx + 2;
for( int i = begIdx + 2; i <= endIdx; ++i ) {
if( predicate[i].getValueString() == "," || i == endIdx ) {
if( i - lastBeg > 1 ) {
XPathToken result = evaluateSection(predicate, search, context, lastBeg, i-1, false);
parms.append(result);
}
else if( i - lastBeg != 0 ) {
parms.append(predicate[i-1]);
}
lastBeg = i + 1;
}
}
XPathFunction* function = getFunction(functionName);
if( function == 0 ) {
throw XPathException("Invalid XPath function specified: '" + functionName + "'");
}
int parmsAllowed = function->getParmCount();
if( parmsAllowed != -1 && parmsAllowed != parms.getSize() ) {
throw XPathException("Invalid number of arguments passed to XPath function '" + functionName + "'");
}
return function->execute(search, context, parms);
}
else {
if( ((endIdx - begIdx) + 1) % 2 == 0 ) {
throw XPathException($("Invalid operation specified in XPath expression"));
}
Array<XPathToken> wrkPredicate(endIdx - begIdx + 1);
for( int iC = begIdx; iC <= endIdx; ++iC ) {
wrkPredicate[iC - begIdx] = predicate[iC];
}
while(true) {
int maxIdx = -1;
int actIdx = -1;
for( int i = 0; i < wrkPredicate.getSize() - 1; i += 2 ) {
XPathToken& oper = wrkPredicate[i + 1];
if( oper.getType() != XPathToken::OPERATOR ) {
throw XPathException("Invalid XPath operator '" + oper.getValueString() + "'");
}
int opIdx = priv_findOperatorIdx(m_operators, oper.getValueString());
if( opIdx > maxIdx ) {
maxIdx = opIdx;
actIdx = i + 1;
}
}
if( actIdx == -1 ) {
throw XPathException($("Invalid operation specified in XPath expression"));
}
XPathToken& lparm = wrkPredicate[actIdx - 1];
XPathToken& oper = wrkPredicate[actIdx ];
XPathToken& rparm = wrkPredicate[actIdx + 1];
if( !lparm.isCompatibleWith(rparm.getType()) ) {
throw XPathException($("Parameters on the left and right side of an operation must be compatible"));
}
Array<XPathToken> parms(2);
parms[0] = lparm;
parms[1] = rparm;
XPathToken result = m_operators[maxIdx]->execute(search, context, parms);
if( wrkPredicate.getSize() == 3 ) {
return (result);
}
wrkPredicate.remove(actIdx + 1);
wrkPredicate.remove(actIdx );
wrkPredicate.remove(actIdx - 1);
wrkPredicate.insert(result, actIdx-1);
}
}
}
}}} // namespaces
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -