📄 xpathfunctions.cpp
字号:
} if (!node) node = evaluationContext().node.get(); return node->namespaceURI().string();}Value FunName::evaluate() const{ Node* node = 0; if (argCount() > 0) { Value a = arg(0)->evaluate(); if (!a.isNodeSet()) return ""; node = a.toNodeSet().firstNode(); if (!node) return ""; } if (!node) node = evaluationContext().node.get(); const AtomicString& prefix = node->prefix(); return prefix.isEmpty() ? node->localName().string() : prefix + ":" + node->localName();}Value FunCount::evaluate() const{ Value a = arg(0)->evaluate(); if (!a.isNodeSet()) return 0.0; return double(a.toNodeSet().size());}Value FunString::evaluate() const{ if (!argCount()) return Value(Expression::evaluationContext().node.get()).toString(); return arg(0)->evaluate().toString();}Value FunConcat::evaluate() const{ Vector<UChar, 1024> result; unsigned count = argCount(); for (unsigned i = 0; i < count; ++i) { String str(arg(i)->evaluate().toString()); result.append(str.characters(), str.length()); } return String(result.data(), result.size());}Value FunStartsWith::evaluate() const{ String s1 = arg(0)->evaluate().toString(); String s2 = arg(1)->evaluate().toString(); if (s2.isEmpty()) return true; return s1.startsWith(s2);}Value FunContains::evaluate() const{ String s1 = arg(0)->evaluate().toString(); String s2 = arg(1)->evaluate().toString(); if (s2.isEmpty()) return true; return s1.contains(s2) != 0;}Value FunSubstringBefore::evaluate() const{ String s1 = arg(0)->evaluate().toString(); String s2 = arg(1)->evaluate().toString(); if (s2.isEmpty()) return ""; int i = s1.find(s2); if (i == -1) return ""; return s1.left(i);}Value FunSubstringAfter::evaluate() const{ String s1 = arg(0)->evaluate().toString(); String s2 = arg(1)->evaluate().toString(); int i = s1.find(s2); if (i == -1) return ""; return s1.substring(i + s2.length());}Value FunSubstring::evaluate() const{ String s = arg(0)->evaluate().toString(); long pos = static_cast<long>(FunRound::round(arg(1)->evaluate().toNumber())); bool haveLength = argCount() == 3; long len = -1; if (haveLength) { double doubleLen = arg(2)->evaluate().toNumber(); if (isnan(doubleLen)) return ""; len = static_cast<long>(FunRound::round(doubleLen)); } if (pos > long(s.length())) return ""; if (haveLength && pos < 1) { len -= 1 - pos; pos = 1; if (len < 1) return ""; } return s.substring(pos - 1, len);}Value FunStringLength::evaluate() const{ if (!argCount()) return Value(Expression::evaluationContext().node.get()).toString().length(); return arg(0)->evaluate().toString().length();}Value FunNormalizeSpace::evaluate() const{ if (!argCount()) { String s = Value(Expression::evaluationContext().node.get()).toString(); return s.simplifyWhiteSpace(); } String s = arg(0)->evaluate().toString(); return s.simplifyWhiteSpace();}Value FunTranslate::evaluate() const{ String s1 = arg(0)->evaluate().toString(); String s2 = arg(1)->evaluate().toString(); String s3 = arg(2)->evaluate().toString(); String newString; // FIXME: Building a String a character at a time is quite slow. for (unsigned i1 = 0; i1 < s1.length(); ++i1) { UChar ch = s1[i1]; int i2 = s2.find(ch); if (i2 == -1) newString += String(&ch, 1); else if ((unsigned)i2 < s3.length()) { UChar c2 = s3[i2]; newString += String(&c2, 1); } } return newString;}Value FunBoolean::evaluate() const{ return arg(0)->evaluate().toBoolean();}Value FunNot::evaluate() const{ return !arg(0)->evaluate().toBoolean();}Value FunTrue::evaluate() const{ return true;}Value FunLang::evaluate() const{ String lang = arg(0)->evaluate().toString(); Attribute* languageAttribute = 0; Node* node = evaluationContext().node.get(); while (node) { NamedAttrMap* attrs = node->attributes(); if (attrs) languageAttribute = attrs->getAttributeItem(XMLNames::langAttr); if (languageAttribute) break; node = node->parentNode(); } if (!languageAttribute) return false; String langValue = languageAttribute->value(); while (true) { if (equalIgnoringCase(langValue, lang)) return true; // Remove suffixes one by one. int index = langValue.reverseFind('-'); if (index == -1) break; langValue = langValue.left(index); } return false;}Value FunFalse::evaluate() const{ return false;}Value FunNumber::evaluate() const{ if (!argCount()) return Value(Expression::evaluationContext().node.get()).toNumber(); return arg(0)->evaluate().toNumber();}Value FunSum::evaluate() const{ Value a = arg(0)->evaluate(); if (!a.isNodeSet()) return 0.0; double sum = 0.0; const NodeSet& nodes = a.toNodeSet(); // To be really compliant, we should sort the node-set, as floating point addition is not associative. // However, this is unlikely to ever become a practical issue, and sorting is slow. for (unsigned i = 0; i < nodes.size(); i++) sum += Value(stringValue(nodes[i])).toNumber(); return sum;}Value FunFloor::evaluate() const{ return floor(arg(0)->evaluate().toNumber());}Value FunCeiling::evaluate() const{ return ceil(arg(0)->evaluate().toNumber());}double FunRound::round(double val){ if (!isnan(val) && !isinf(val)) { if (signbit(val) && val >= -0.5) val *= 0; // negative zero else val = floor(val + 0.5); } return val;}Value FunRound::evaluate() const{ return round(arg(0)->evaluate().toNumber());}static void createFunctionMap(){ struct FunctionMapping { const char *name; FunctionRec function; }; static const FunctionMapping functions[] = { { "boolean", { &createFunBoolean, 1 } }, { "ceiling", { &createFunCeiling, 1 } }, { "concat", { &createFunConcat, Interval(2, Interval::Inf) } }, { "contains", { &createFunContains, 2 } }, { "count", { &createFunCount, 1 } }, { "false", { &createFunFalse, 0 } }, { "floor", { &createFunFloor, 1 } }, { "id", { &createFunId, 1 } }, { "lang", { &createFunLang, 1 } }, { "last", { &createFunLast, 0 } }, { "local-name", { &createFunLocalName, Interval(0, 1) } }, { "name", { &createFunName, Interval(0, 1) } }, { "namespace-uri", { &createFunNamespaceURI, Interval(0, 1) } }, { "normalize-space", { &createFunNormalizeSpace, Interval(0, 1) } }, { "not", { &createFunNot, 1 } }, { "number", { &createFunNumber, Interval(0, 1) } }, { "position", { &createFunPosition, 0 } }, { "round", { &createFunRound, 1 } }, { "starts-with", { &createFunStartsWith, 2 } }, { "string", { &createFunString, Interval(0, 1) } }, { "string-length", { &createFunStringLength, Interval(0, 1) } }, { "substring", { &createFunSubstring, Interval(2, 3) } }, { "substring-after", { &createFunSubstringAfter, 2 } }, { "substring-before", { &createFunSubstringBefore, 2 } }, { "sum", { &createFunSum, 1 } }, { "translate", { &createFunTranslate, 3 } }, { "true", { &createFunTrue, 0 } }, }; const unsigned int numFunctions = sizeof(functions) / sizeof(functions[0]); functionMap = new HashMap<String, FunctionRec>; for (unsigned i = 0; i < numFunctions; ++i) functionMap->set(functions[i].name, functions[i].function);}Function* createFunction(const String& name, const Vector<Expression*>& args){ if (!functionMap) createFunctionMap(); HashMap<String, FunctionRec>::iterator functionMapIter = functionMap->find(name); FunctionRec* functionRec = 0; if (functionMapIter == functionMap->end() || !(functionRec = &functionMapIter->second)->args.contains(args.size())) return 0; Function* function = functionRec->factoryFn(); function->setArguments(args); function->setName(name); return function;}}}#endif // ENABLE(XPATH)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -