📄 gdata_condensed.js
字号:
// to. Strangely, the different value types are not specified in the// XPath syntax, but only in the semantics, so they don't show up as// nonterminals in the grammar. Yet, some expressions are required to// evaluate to particular types, and not every type can be coerced// into every other type. Although the types of XPath values are// similar to the types present in JavaScript, the type coercion rules// are a bit peculiar, so we explicitly model XPath types instead of// mapping them onto JavaScript types. (See XPath spec.)//// The four types are://// StringValue//// NumberValue//// BooleanValue//// NodeSetValue//// The common interface of the value classes consists of methods that// implement the XPath type coercion rules://// stringValue() -- returns the value as a JavaScript String,//// numberValue() -- returns the value as a JavaScript Number,//// booleanValue() -- returns the value as a JavaScript Boolean,//// nodeSetValue() -- returns the value as a JavaScript Array of DOM// Node objects.//function StringValue(value) { this.value = value; this.type = 'string';}StringValue.prototype.stringValue = function() { return this.value;}StringValue.prototype.booleanValue = function() { return this.value.length > 0;}StringValue.prototype.numberValue = function() { return this.value - 0;}StringValue.prototype.nodeSetValue = function() { throw this;}function BooleanValue(value) { this.value = value; this.type = 'boolean';}BooleanValue.prototype.stringValue = function() { return '' + this.value;}BooleanValue.prototype.booleanValue = function() { return this.value;}BooleanValue.prototype.numberValue = function() { return this.value ? 1 : 0;}BooleanValue.prototype.nodeSetValue = function() { throw this;}function NumberValue(value) { this.value = value; this.type = 'number';}NumberValue.prototype.stringValue = function() { return '' + this.value;}NumberValue.prototype.booleanValue = function() { return !!this.value;}NumberValue.prototype.numberValue = function() { return this.value - 0;}NumberValue.prototype.nodeSetValue = function() { throw this;}function NodeSetValue(value) { this.value = value; this.type = 'node-set';}NodeSetValue.prototype.stringValue = function() { if (this.value.length == 0) { return ''; } else { return UTIL_xmlValue(this.value[0]); }}NodeSetValue.prototype.booleanValue = function() { return this.value.length > 0;}NodeSetValue.prototype.numberValue = function() { return this.stringValue() - 0;}NodeSetValue.prototype.nodeSetValue = function() { return this.value;};// XPath expressions. They are used as nodes in the parse tree and// possess an evaluate() method to compute an XPath value given an XPath// context. Expressions are returned from the parser. Teh set of// expression classes closely mirrors the set of non terminal symbols// in the grammar. Every non trivial nonterminal symbol has a// corresponding expression class.//// The common expression interface consists of the following methods://// evaluate(context) -- evaluates the expression, returns a value.//// toString() -- returns the XPath text representation of the// expression (defined in xsltdebug.js).//// parseTree(indent) -- returns a parse tree representation of the// expression (defined in xsltdebug.js).function TokenExpr(m) { this.value = m;}TokenExpr.prototype.evaluate = function() { return new StringValue(this.value);};function LocationExpr() { this.absolute = false; this.steps = [];}LocationExpr.prototype.appendStep = function(s) { this.steps.push(s);}LocationExpr.prototype.prependStep = function(s) { var steps0 = this.steps; this.steps = [ s ]; for (var i = 0; i < steps0.length; ++i) { this.steps.push(steps0[i]); }};LocationExpr.prototype.evaluate = function(ctx) { var start; if (this.absolute) { start = ctx.root; } else { start = ctx.node; } var nodes = []; xPathStep(nodes, this.steps, 0, start, ctx); return new NodeSetValue(nodes);};function xPathStep(nodes, steps, step, input, ctx) { var s = steps[step]; var ctx2 = ctx.clone(input); var nodelist = s.evaluate(ctx2).nodeSetValue(); for (var i = 0; i < nodelist.length; ++i) { if (step == steps.length - 1) { nodes.push(nodelist[i]); } else { xPathStep(nodes, steps, step + 1, nodelist[i], ctx); } }}function StepExpr(axis, nodetest, predicate) { this.axis = axis; this.nodetest = nodetest; this.predicate = predicate || [];}StepExpr.prototype.appendPredicate = function(p) { this.predicate.push(p);}StepExpr.prototype.evaluate = function(ctx) { var input = ctx.node; var nodelist = []; // NOTE: When this was a switch() statement, it didn't work // in Safari/2.0. Not sure why though; it resulted in the JavaScript // console output "undefined" (without any line number or so). if (this.axis == xpathAxis.ANCESTOR_OR_SELF) { nodelist.push(input); for (var n = input.parentNode; n; n = input.parentNode) { nodelist.push(n); } } else if (this.axis == xpathAxis.ANCESTOR) { for (var n = input.parentNode; n; n = input.parentNode) { nodelist.push(n); } } else if (this.axis == xpathAxis.ATTRIBUTE) { UTIL_copyArray(nodelist, input.attributes); } else if (this.axis == xpathAxis.CHILD) { UTIL_copyArray(nodelist, input.childNodes); } else if (this.axis == xpathAxis.DESCENDANT_OR_SELF) { nodelist.push(input); xpathCollectDescendants(nodelist, input); } else if (this.axis == xpathAxis.DESCENDANT) { xpathCollectDescendants(nodelist, input); } else if (this.axis == xpathAxis.FOLLOWING) { for (var n = input.parentNode; n; n = n.parentNode) { for (var nn = n.nextSibling; nn; nn = nn.nextSibling) { nodelist.push(nn); xpathCollectDescendants(nodelist, nn); } } } else if (this.axis == xpathAxis.FOLLOWING_SIBLING) { for (var n = input.nextSibling; n; n = input.nextSibling) { nodelist.push(n); } } else if (this.axis == xpathAxis.NAMESPACE) { DBG_ALERT('not implemented: axis namespace'); } else if (this.axis == xpathAxis.PARENT) { if (input.parentNode) { nodelist.push(input.parentNode); } } else if (this.axis == xpathAxis.PRECEDING) { for (var n = input.parentNode; n; n = n.parentNode) { for (var nn = n.previousSibling; nn; nn = nn.previousSibling) { nodelist.push(nn); xpathCollectDescendantsReverse(nodelist, nn); } } } else if (this.axis == xpathAxis.PRECEDING_SIBLING) { for (var n = input.previousSibling; n; n = input.previousSibling) { nodelist.push(n); } } else if (this.axis == xpathAxis.SELF) { nodelist.push(input); } else { throw 'ERROR -- NO SUCH AXIS: ' + this.axis; } // process node test var nodelist0 = nodelist; nodelist = []; for (var i = 0; i < nodelist0.length; ++i) { var n = nodelist0[i]; if (this.nodetest.evaluate(ctx.clone(n, i, nodelist0)).booleanValue()) { nodelist.push(n); } } // process predicates for (var i = 0; i < this.predicate.length; ++i) { var nodelist0 = nodelist; nodelist = []; for (var ii = 0; ii < nodelist0.length; ++ii) { var n = nodelist0[ii]; if (this.predicate[i].evaluate(ctx.clone(n, ii, nodelist0)).booleanValue()) { nodelist.push(n); } } } return new NodeSetValue(nodelist);};function NodeTestAny() { this.value = new BooleanValue(true);}NodeTestAny.prototype.evaluate = function(ctx) { return this.value;};function NodeTestElement() {}NodeTestElement.prototype.evaluate = function(ctx) { return new BooleanValue(ctx.node.nodeType == DOM_ELEMENT_NODE);}function NodeTestText() {}NodeTestText.prototype.evaluate = function(ctx) { return new BooleanValue(ctx.node.nodeType == DOM_TEXT_NODE);}function NodeTestComment() {}NodeTestComment.prototype.evaluate = function(ctx) { return new BooleanValue(ctx.node.nodeType == DOM_COMMENT_NODE);}function NodeTestPI(target) { this.target = target;}NodeTestPI.prototype.evaluate = function(ctx) { return new BooleanValue(ctx.node.nodeType == DOM_PROCESSING_INSTRUCTION_NODE && (!this.target || ctx.node.nodeName == this.target));}function NodeTestNC(nsprefix) { this.regex = new RegExp("^" + nsprefix + ":"); this.nsprefix = nsprefix;}NodeTestNC.prototype.evaluate = function(ctx) { var n = ctx.node; return new BooleanValue(this.regex.match(n.nodeName));}function NodeTestName(name) { this.name = name;}NodeTestName.prototype.evaluate = function(ctx) { var n = ctx.node; return new BooleanValue(n.nodeName == this.name);}function PredicateExpr(expr) { this.expr = expr;}PredicateExpr.prototype.evaluate = function(ctx) { var v = this.expr.evaluate(ctx); if (v.type == 'number') { // NOTE: Internally, position is represented starting with // 0, however in XPath position starts with 1. See functions // position() and last(). return new BooleanValue(ctx.position == v.numberValue() - 1); } else { return new BooleanValue(v.booleanValue()); }};function FunctionCallExpr(name) { this.name = name; this.args = [];}FunctionCallExpr.prototype.appendArg = function(arg) { this.args.push(arg);};FunctionCallExpr.prototype.evaluate = function(ctx) { var fn = '' + this.name.value; var f = this.xpathfunctions[fn]; if (f) { return f.call(this, ctx); } else { LOG_DEBUG('XPath NO SUCH FUNCTION ' + fn); return new BooleanValue(false); }};FunctionCallExpr.prototype.xpathfunctions = { 'last': function(ctx) { assert(this.args.length == 0); // NOTE: XPath position starts at 1. return new NumberValue(ctx.nodelist.length); }, 'position': function(ctx) { assert(this.args.length == 0); // NOTE: XPath position starts at 1. return new NumberValue(ctx.position + 1); }, 'count': function(ctx) { assert(this.args.length == 1); var v = this.args[0].evaluate(ctx); return new NumberValue(v.nodeSetValue().length); }, 'id': function(ctx) { assert(this.args.length == 1); var e = this.args.evaluate(ctx); var ret = []; var ids; if (e.type == 'node-set') { ids = []; for (var i = 0; i < e.length; ++i) { var v = UTIL_xmlValue(e[i]).split(/\s+/); for (var ii = 0; ii < v.length; ++ii) { ids.push(v[ii]); } } } else { ids = e.split(/\s+/); } var d = ctx.node.ownerDocument; for (var i = 0; i < ids.length; ++i) { var n = d.getElementById(ids[i]); if (n) { ret.push(n); } } return new NodeSetValue(ret); }, 'local-name': function(ctx) { DBG_ALERT('not implmented yet: XPath function local-name()'); }, 'namespace-uri': function(ctx) { DBG_ALERT('not implmented yet: XPath function namespace-uri()'); }, 'name': function(ctx) { assert(this.args.length == 1 || this.args.length == 0); var n; if (this.args.length == 0) { n = [ ctx.node ]; } else { n = this.args[0].evaluate(ctx).nodeSetValue(); } if (n.length == 0) { return new StringValue(''); } else { return new StringValue(n[0].nodeName); } }, 'string': function(ctx) { assert(this.args.length == 1 || this.args.length == 0); if (this.args.length == 0) { return new StringValue(new NodeSetValue([ ctx.node ]).stringValue()); } else { return new StringValue(this.args[0].evaluate(ctx).stringValue()); } }, 'concat': function(ctx) { var ret = ''; for (var i = 0; i < this.args.length; ++i) { ret += this.args[i].evaluate(ctx).stringValue(); } return new StringValue(ret); }, 'starts-with': function(ctx) { assert(this.args.length == 2); var s0 = this.args[0].evaluate(ctx).stringValue(); var s1 = this.args[1].evaluate(ctx).stringValue(); return new BooleanValue(s0.indexOf(s1) =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -