⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xpathpredicate.cpp

📁 简单的xml解析类
💻 CPP
📖 第 1 页 / 共 2 页
字号:
					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 + -