xslt-processor 3.0.0 → 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/constants.d.ts +12 -12
- package/constants.js +16 -16
- package/dom/functions.d.ts +14 -14
- package/dom/functions.js +56 -57
- package/dom/functions.js.map +1 -1
- package/dom/index.d.ts +6 -6
- package/dom/index.js +22 -22
- package/dom/util.d.ts +7 -7
- package/dom/util.js +42 -43
- package/dom/util.js.map +1 -1
- package/dom/xdocument.d.ts +16 -16
- package/dom/xdocument.js +73 -74
- package/dom/xdocument.js.map +1 -1
- package/dom/xml-functions.d.ts +58 -58
- package/dom/xml-functions.js +369 -370
- package/dom/xml-functions.js.map +1 -1
- package/dom/xml-output-options.d.ts +6 -6
- package/dom/xml-output-options.js +2 -2
- package/dom/xml-parser.d.ts +47 -47
- package/dom/xml-parser.js +307 -307
- package/dom/xml-parser.js.map +1 -1
- package/dom/xmltoken.d.ts +12 -12
- package/dom/xmltoken.js +101 -101
- package/dom/xnode.d.ts +73 -73
- package/dom/xnode.js +450 -450
- package/dom/xnode.js.map +1 -1
- package/index.d.ts +4 -4
- package/index.js +12 -12
- package/package.json +11 -11
- package/test-without-jest.d.ts +1 -0
- package/test-without-jest.js +63 -0
- package/test-without-jest.js.map +1 -0
- package/umd/constants.d.ts +12 -12
- package/umd/dom/functions.d.ts +14 -14
- package/umd/dom/index.d.ts +6 -6
- package/umd/dom/util.d.ts +7 -7
- package/umd/dom/xdocument.d.ts +16 -16
- package/umd/dom/xml-functions.d.ts +58 -58
- package/umd/dom/xml-output-options.d.ts +6 -6
- package/umd/dom/xml-parser.d.ts +47 -47
- package/umd/dom/xmltoken.d.ts +12 -12
- package/umd/dom/xnode.d.ts +73 -73
- package/umd/index.d.ts +4 -4
- package/umd/test-without-jest.d.ts +1 -0
- package/umd/xpath/common-function.d.ts +8 -8
- package/umd/xpath/expr-context.d.ts +111 -111
- package/umd/xpath/expressions/binary-expr.d.ts +11 -11
- package/umd/xpath/expressions/expression.d.ts +4 -4
- package/umd/xpath/expressions/filter-expr.d.ts +9 -9
- package/umd/xpath/expressions/function-call-expr.d.ts +12 -12
- package/umd/xpath/expressions/index.d.ts +13 -13
- package/umd/xpath/expressions/literal-expr.d.ts +7 -7
- package/umd/xpath/expressions/location-expr.d.ts +15 -15
- package/umd/xpath/expressions/number-expr.d.ts +7 -7
- package/umd/xpath/expressions/path-expr.d.ts +9 -9
- package/umd/xpath/expressions/predicate-expr.d.ts +8 -8
- package/umd/xpath/expressions/step-expr.d.ts +25 -25
- package/umd/xpath/expressions/token-expr.d.ts +7 -7
- package/umd/xpath/expressions/unary-minus-expr.d.ts +8 -8
- package/umd/xpath/expressions/union-expr.d.ts +9 -9
- package/umd/xpath/expressions/variable-expr.d.ts +7 -7
- package/umd/xpath/functions/index.d.ts +2 -2
- package/umd/xpath/functions/internal-functions.d.ts +2 -2
- package/umd/xpath/functions/non-standard.d.ts +12 -12
- package/umd/xpath/functions/standard-20.d.ts +5 -5
- package/umd/xpath/functions/standard.d.ts +40 -40
- package/umd/xpath/grammar-rule-candidate.d.ts +8 -8
- package/umd/xpath/index.d.ts +3 -3
- package/umd/xpath/match-resolver.d.ts +55 -55
- package/umd/xpath/node-tests/index.d.ts +8 -8
- package/umd/xpath/node-tests/node-test-any.d.ts +6 -6
- package/umd/xpath/node-tests/node-test-comment.d.ts +6 -6
- package/umd/xpath/node-tests/node-test-element-or-attribute.d.ts +6 -6
- package/umd/xpath/node-tests/node-test-name.d.ts +10 -10
- package/umd/xpath/node-tests/node-test-nc.d.ts +9 -9
- package/umd/xpath/node-tests/node-test-pi.d.ts +8 -8
- package/umd/xpath/node-tests/node-test-text.d.ts +6 -6
- package/umd/xpath/node-tests/node-test.d.ts +5 -5
- package/umd/xpath/tokens.d.ts +62 -62
- package/umd/xpath/values/boolean-value.d.ts +11 -11
- package/umd/xpath/values/index.d.ts +5 -5
- package/umd/xpath/values/node-set-value.d.ts +11 -11
- package/umd/xpath/values/node-value.d.ts +7 -7
- package/umd/xpath/values/number-value.d.ts +11 -11
- package/umd/xpath/values/string-value.d.ts +11 -11
- package/umd/xpath/xpath-grammar-rules.d.ts +68 -68
- package/umd/xpath/xpath-token-rule.d.ts +7 -7
- package/umd/xpath/xpath.d.ts +174 -170
- package/umd/xpathdebug.d.ts +2 -2
- package/umd/xslt/index.d.ts +3 -3
- package/umd/xslt/xslt-decimal-format-settings.d.ts +28 -28
- package/umd/xslt/xslt-options.d.ts +7 -7
- package/umd/xslt/xslt-parameter.d.ts +5 -5
- package/umd/xslt/xslt.d.ts +207 -190
- package/umd/xslt-processor.js +1 -15
- package/umd/xslt-processor.js.map +1 -1
- package/xpath/common-function.d.ts +8 -8
- package/xpath/common-function.js +31 -32
- package/xpath/common-function.js.map +1 -1
- package/xpath/expr-context.d.ts +111 -111
- package/xpath/expr-context.js +189 -189
- package/xpath/expr-context.js.map +1 -1
- package/xpath/expressions/binary-expr.d.ts +11 -11
- package/xpath/expressions/binary-expr.js +165 -165
- package/xpath/expressions/binary-expr.js.map +1 -1
- package/xpath/expressions/expression.d.ts +4 -4
- package/xpath/expressions/expression.js +9 -9
- package/xpath/expressions/filter-expr.d.ts +9 -9
- package/xpath/expressions/filter-expr.js +52 -52
- package/xpath/expressions/filter-expr.js.map +1 -1
- package/xpath/expressions/function-call-expr.d.ts +12 -12
- package/xpath/expressions/function-call-expr.js +95 -95
- package/xpath/expressions/function-call-expr.js.map +1 -1
- package/xpath/expressions/index.d.ts +13 -13
- package/xpath/expressions/index.js +29 -29
- package/xpath/expressions/literal-expr.d.ts +7 -7
- package/xpath/expressions/literal-expr.js +33 -33
- package/xpath/expressions/literal-expr.js.map +1 -1
- package/xpath/expressions/location-expr.d.ts +15 -15
- package/xpath/expressions/location-expr.js +98 -98
- package/xpath/expressions/location-expr.js.map +1 -1
- package/xpath/expressions/number-expr.d.ts +7 -7
- package/xpath/expressions/number-expr.js +33 -33
- package/xpath/expressions/number-expr.js.map +1 -1
- package/xpath/expressions/path-expr.d.ts +9 -9
- package/xpath/expressions/path-expr.js +51 -51
- package/xpath/expressions/path-expr.js.map +1 -1
- package/xpath/expressions/predicate-expr.d.ts +8 -8
- package/xpath/expressions/predicate-expr.js +40 -40
- package/xpath/expressions/predicate-expr.js.map +1 -1
- package/xpath/expressions/step-expr.d.ts +25 -25
- package/xpath/expressions/step-expr.js +280 -280
- package/xpath/expressions/step-expr.js.map +1 -1
- package/xpath/expressions/token-expr.d.ts +7 -7
- package/xpath/expressions/token-expr.js +33 -33
- package/xpath/expressions/token-expr.js.map +1 -1
- package/xpath/expressions/unary-minus-expr.d.ts +8 -8
- package/xpath/expressions/unary-minus-expr.js +33 -33
- package/xpath/expressions/unary-minus-expr.js.map +1 -1
- package/xpath/expressions/union-expr.d.ts +9 -9
- package/xpath/expressions/union-expr.js +50 -50
- package/xpath/expressions/union-expr.js.map +1 -1
- package/xpath/expressions/variable-expr.d.ts +7 -7
- package/xpath/expressions/variable-expr.js +32 -32
- package/xpath/expressions/variable-expr.js.map +1 -1
- package/xpath/functions/index.d.ts +2 -2
- package/xpath/functions/index.js +18 -18
- package/xpath/functions/internal-functions.d.ts +2 -2
- package/xpath/functions/internal-functions.js +21 -22
- package/xpath/functions/internal-functions.js.map +1 -1
- package/xpath/functions/non-standard.d.ts +12 -12
- package/xpath/functions/non-standard.js +44 -45
- package/xpath/functions/non-standard.js.map +1 -1
- package/xpath/functions/standard-20.d.ts +5 -5
- package/xpath/functions/standard-20.js +25 -26
- package/xpath/functions/standard-20.js.map +1 -1
- package/xpath/functions/standard.d.ts +40 -40
- package/xpath/functions/standard.js +441 -442
- package/xpath/functions/standard.js.map +1 -1
- package/xpath/grammar-rule-candidate.d.ts +8 -8
- package/xpath/grammar-rule-candidate.js +2 -2
- package/xpath/index.d.ts +3 -3
- package/xpath/index.js +19 -19
- package/xpath/match-resolver.d.ts +55 -55
- package/xpath/match-resolver.js +136 -136
- package/xpath/match-resolver.js.map +1 -1
- package/xpath/node-tests/index.d.ts +8 -8
- package/xpath/node-tests/index.js +17 -17
- package/xpath/node-tests/node-test-any.d.ts +6 -6
- package/xpath/node-tests/node-test-any.js +14 -14
- package/xpath/node-tests/node-test-comment.d.ts +6 -6
- package/xpath/node-tests/node-test-comment.js +14 -14
- package/xpath/node-tests/node-test-element-or-attribute.d.ts +6 -6
- package/xpath/node-tests/node-test-element-or-attribute.js +15 -15
- package/xpath/node-tests/node-test-name.d.ts +10 -10
- package/xpath/node-tests/node-test-name.js +38 -38
- package/xpath/node-tests/node-test-name.js.map +1 -1
- package/xpath/node-tests/node-test-nc.d.ts +9 -9
- package/xpath/node-tests/node-test-nc.js +16 -16
- package/xpath/node-tests/node-test-pi.d.ts +8 -8
- package/xpath/node-tests/node-test-pi.js +16 -16
- package/xpath/node-tests/node-test-pi.js.map +1 -1
- package/xpath/node-tests/node-test-text.d.ts +6 -6
- package/xpath/node-tests/node-test-text.js +14 -14
- package/xpath/node-tests/node-test.d.ts +5 -5
- package/xpath/node-tests/node-test.js +2 -2
- package/xpath/tokens.d.ts +62 -62
- package/xpath/tokens.js +300 -300
- package/xpath/tokens.js.map +1 -1
- package/xpath/values/boolean-value.d.ts +11 -11
- package/xpath/values/boolean-value.js +23 -23
- package/xpath/values/index.d.ts +5 -5
- package/xpath/values/index.js +46 -46
- package/xpath/values/node-set-value.d.ts +11 -11
- package/xpath/values/node-set-value.js +27 -27
- package/xpath/values/node-set-value.js.map +1 -1
- package/xpath/values/node-value.d.ts +7 -7
- package/xpath/values/node-value.js +2 -2
- package/xpath/values/number-value.d.ts +11 -11
- package/xpath/values/number-value.js +23 -23
- package/xpath/values/string-value.d.ts +11 -11
- package/xpath/values/string-value.js +23 -23
- package/xpath/xpath-grammar-rules.d.ts +68 -68
- package/xpath/xpath-grammar-rules.js +74 -74
- package/xpath/xpath-token-rule.d.ts +7 -7
- package/xpath/xpath-token-rule.js +2 -2
- package/xpath/xpath.d.ts +174 -170
- package/xpath/xpath.js +911 -909
- package/xpath/xpath.js.map +1 -1
- package/xpathdebug.d.ts +2 -2
- package/xpathdebug.js +187 -187
- package/xpathdebug.js.map +1 -1
- package/xslt/index.d.ts +3 -3
- package/xslt/index.js +19 -19
- package/xslt/xslt-decimal-format-settings.d.ts +28 -28
- package/xslt/xslt-decimal-format-settings.js +2 -2
- package/xslt/xslt-options.d.ts +7 -7
- package/xslt/xslt-options.js +2 -2
- package/xslt/xslt-parameter.d.ts +5 -5
- package/xslt/xslt-parameter.js +2 -2
- package/xslt/xslt.d.ts +207 -190
- package/xslt/xslt.js +1135 -1079
- package/xslt/xslt.js.map +1 -1
package/xpath/xpath.js
CHANGED
|
@@ -1,910 +1,912 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// Copyright 2023-2024 Design Liquido
|
|
3
|
-
// Copyright 2018 Johannes Wilm
|
|
4
|
-
// Copyright 2005 Google Inc.
|
|
5
|
-
// All Rights Reserved
|
|
6
|
-
//
|
|
7
|
-
// An XPath parser and evaluator written in JavaScript. The
|
|
8
|
-
// implementation is complete except for functions handling
|
|
9
|
-
// namespaces.
|
|
10
|
-
//
|
|
11
|
-
// Reference: [XPATH] XPath Specification
|
|
12
|
-
// <http://www.w3.org/TR/1999/REC-xpath-19991116>.
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
// The API of the parser has several parts:
|
|
16
|
-
//
|
|
17
|
-
// 1. The parser function xpathParse() that takes a string and returns
|
|
18
|
-
// an expession object.
|
|
19
|
-
//
|
|
20
|
-
// 2. The expression object that has an evaluate() method to evaluate the
|
|
21
|
-
// XPath expression it represents. (It is actually a hierarchy of
|
|
22
|
-
// objects that resembles the parse tree, but an application will call
|
|
23
|
-
// evaluate() only on the top node of this hierarchy.)
|
|
24
|
-
//
|
|
25
|
-
// 3. The context object that is passed as an argument to the evaluate()
|
|
26
|
-
// method, which represents the DOM context in which the expression is
|
|
27
|
-
// evaluated.
|
|
28
|
-
//
|
|
29
|
-
// 4. The value object that is returned from evaluate() and represents
|
|
30
|
-
// values of the different types that are defined by XPath (number,
|
|
31
|
-
// string, boolean, and node-set), and allows to convert between them.
|
|
32
|
-
//
|
|
33
|
-
// These parts are near the top of the file, the functions and data
|
|
34
|
-
// that are used internally follow after them.
|
|
35
|
-
//
|
|
36
|
-
//
|
|
37
|
-
// Original author: Steffen Meschkat <mesch@google.com>
|
|
38
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.XPath = void 0;
|
|
40
|
-
var util_1 = require("../dom/util");
|
|
41
|
-
var common_function_1 = require("./common-function");
|
|
42
|
-
var expressions_1 = require("./expressions");
|
|
43
|
-
var tokens_1 = require("./tokens");
|
|
44
|
-
var xpath_grammar_rules_1 = require("./xpath-grammar-rules");
|
|
45
|
-
var node_tests_1 = require("./node-tests");
|
|
46
|
-
var constants_1 = require("../constants");
|
|
47
|
-
var XPath = /** @class */ (function () {
|
|
48
|
-
function XPath() {
|
|
49
|
-
// The productions of the grammar. Columns of the table:
|
|
50
|
-
//
|
|
51
|
-
// - target
|
|
52
|
-
// - pattern,
|
|
53
|
-
// - precedence,
|
|
54
|
-
// - semantic value factory
|
|
55
|
-
//
|
|
56
|
-
// The semantic value factory is a function that receives parse tree
|
|
57
|
-
// nodes from the stack frames of the matched symbols as arguments and
|
|
58
|
-
// returns an a node of the parse tree. The node is stored in the top
|
|
59
|
-
// stack frame along with the target object of the rule. The node in
|
|
60
|
-
// the parse tree is an expression object that has an evaluate() method
|
|
61
|
-
// and thus evaluates XPath expressions.
|
|
62
|
-
//
|
|
63
|
-
// The precedence is used to decide between reducing and shifting by
|
|
64
|
-
// comparing the
|
|
65
|
-
// reducing with the precedence of the look ahead token. Precedence of
|
|
66
|
-
// -1 means that the precedence of the tokens in the pattern is used
|
|
67
|
-
// instead. TODO: It shouldn't be necessary to explicitly assign
|
|
68
|
-
// precedences to rules.
|
|
69
|
-
// DGF As it stands, these precedences are purely empirical; we're
|
|
70
|
-
// not sure they can be made to be consistent at all.
|
|
71
|
-
this.xPathGrammarRules = [
|
|
72
|
-
[xpath_grammar_rules_1.XPathLocationPath, [xpath_grammar_rules_1.XPathRelativeLocationPath], 18, this.passExpr],
|
|
73
|
-
[xpath_grammar_rules_1.XPathLocationPath, [xpath_grammar_rules_1.XPathAbsoluteLocationPath], 18, this.passExpr],
|
|
74
|
-
[xpath_grammar_rules_1.XPathAbsoluteLocationPath, [tokens_1.TOK_SLASH, xpath_grammar_rules_1.XPathRelativeLocationPath], 18, this.makeLocationExpr1],
|
|
75
|
-
[xpath_grammar_rules_1.XPathAbsoluteLocationPath, [tokens_1.TOK_DSLASH, xpath_grammar_rules_1.XPathRelativeLocationPath], 18, this.makeLocationExpr2],
|
|
76
|
-
[xpath_grammar_rules_1.XPathAbsoluteLocationPath, [tokens_1.TOK_SLASH], 0, this.makeLocationExpr3],
|
|
77
|
-
[xpath_grammar_rules_1.XPathAbsoluteLocationPath, [tokens_1.TOK_DSLASH], 0, this.makeLocationExpr4],
|
|
78
|
-
[xpath_grammar_rules_1.XPathRelativeLocationPath, [xpath_grammar_rules_1.XPathStep], 31, this.makeLocationExpr5],
|
|
79
|
-
[xpath_grammar_rules_1.XPathRelativeLocationPath, [xpath_grammar_rules_1.XPathRelativeLocationPath, tokens_1.TOK_SLASH, xpath_grammar_rules_1.XPathStep], 31, this.makeLocationExpr6],
|
|
80
|
-
[xpath_grammar_rules_1.XPathRelativeLocationPath, [xpath_grammar_rules_1.XPathRelativeLocationPath, tokens_1.TOK_DSLASH, xpath_grammar_rules_1.XPathStep], 31, this.makeLocationExpr7],
|
|
81
|
-
[xpath_grammar_rules_1.XPathStep, [tokens_1.TOK_DOT], 33, this.makeStepExpr1],
|
|
82
|
-
[xpath_grammar_rules_1.XPathStep, [tokens_1.TOK_DDOT], 33, this.makeStepExpr2],
|
|
83
|
-
[xpath_grammar_rules_1.XPathStep, [tokens_1.TOK_AXISNAME, tokens_1.TOK_AXIS, xpath_grammar_rules_1.XPathNodeTest], 33, this.makeStepExpr3],
|
|
84
|
-
[xpath_grammar_rules_1.XPathStep, [tokens_1.TOK_AT, xpath_grammar_rules_1.XPathNodeTest], 33, this.makeStepExpr4],
|
|
85
|
-
[xpath_grammar_rules_1.XPathStep, [xpath_grammar_rules_1.XPathNodeTest], 33, this.makeStepExpr5],
|
|
86
|
-
[xpath_grammar_rules_1.XPathStep, [xpath_grammar_rules_1.XPathStep, xpath_grammar_rules_1.XPathPredicate], 33, this.makeStepExpr6],
|
|
87
|
-
[xpath_grammar_rules_1.XPathNodeTest, [tokens_1.TOK_ASTERISK], 33, this.makeNodeTestExpr1],
|
|
88
|
-
[xpath_grammar_rules_1.XPathNodeTest, [tokens_1.TOK_NCNAME, tokens_1.TOK_COLON, tokens_1.TOK_ASTERISK], 33, this.makeNodeTestExpr2],
|
|
89
|
-
[xpath_grammar_rules_1.XPathNodeTest, [tokens_1.TOK_QNAME], 33, this.makeNodeTestExpr3],
|
|
90
|
-
[xpath_grammar_rules_1.XPathNodeTest, [tokens_1.TOK_NODEO, tokens_1.TOK_PARENC], 33, this.makeNodeTestExpr4],
|
|
91
|
-
[xpath_grammar_rules_1.XPathNodeTest, [tokens_1.TOK_NODEO, xpath_grammar_rules_1.XPathLiteral, tokens_1.TOK_PARENC], 33, this.makeNodeTestExpr5],
|
|
92
|
-
[xpath_grammar_rules_1.XPathPredicate, [tokens_1.TOK_BRACKO, xpath_grammar_rules_1.XPathExpr, tokens_1.TOK_BRACKC], 33, this.makePredicateExpr],
|
|
93
|
-
[xpath_grammar_rules_1.XPathPrimaryExpr, [xpath_grammar_rules_1.XPathVariableReference], 33, this.passExpr],
|
|
94
|
-
[xpath_grammar_rules_1.XPathPrimaryExpr, [tokens_1.TOK_PARENO, xpath_grammar_rules_1.XPathExpr, tokens_1.TOK_PARENC], 33, this.makePrimaryExpr],
|
|
95
|
-
[xpath_grammar_rules_1.XPathPrimaryExpr, [xpath_grammar_rules_1.XPathLiteral], 30, this.passExpr],
|
|
96
|
-
[xpath_grammar_rules_1.XPathPrimaryExpr, [xpath_grammar_rules_1.XPathNumber], 30, this.passExpr],
|
|
97
|
-
[xpath_grammar_rules_1.XPathPrimaryExpr, [xpath_grammar_rules_1.XPathFunctionCall], 31, this.passExpr],
|
|
98
|
-
[xpath_grammar_rules_1.XPathFunctionCall, [tokens_1.TOK_QNAME, tokens_1.TOK_PARENO, tokens_1.TOK_PARENC], -1, this.makeFunctionCallExpr1],
|
|
99
|
-
[
|
|
100
|
-
xpath_grammar_rules_1.XPathFunctionCall,
|
|
101
|
-
[tokens_1.TOK_QNAME, tokens_1.TOK_PARENO, xpath_grammar_rules_1.XPathExpr, xpath_grammar_rules_1.XPathArgumentRemainder, tokens_1.
|
|
102
|
-
-1,
|
|
103
|
-
this.makeFunctionCallExpr2
|
|
104
|
-
],
|
|
105
|
-
[xpath_grammar_rules_1.XPathArgumentRemainder, [tokens_1.TOK_COMMA, xpath_grammar_rules_1.XPathExpr], -1, this.makeArgumentExpr],
|
|
106
|
-
[xpath_grammar_rules_1.XPathUnionExpr, [xpath_grammar_rules_1.XPathPathExpr], 20, this.passExpr],
|
|
107
|
-
[xpath_grammar_rules_1.XPathUnionExpr, [xpath_grammar_rules_1.XPathUnionExpr, tokens_1.TOK_PIPE, xpath_grammar_rules_1.XPathPathExpr], 20, this.makeUnionExpr],
|
|
108
|
-
[xpath_grammar_rules_1.XPathPathExpr, [xpath_grammar_rules_1.XPathLocationPath], 20, this.passExpr],
|
|
109
|
-
[xpath_grammar_rules_1.XPathPathExpr, [xpath_grammar_rules_1.XPathFilterExpr], 19, this.passExpr],
|
|
110
|
-
[xpath_grammar_rules_1.XPathPathExpr, [xpath_grammar_rules_1.XPathFilterExpr, tokens_1.TOK_SLASH, xpath_grammar_rules_1.XPathRelativeLocationPath], 19, this.makePathExpr1],
|
|
111
|
-
[xpath_grammar_rules_1.XPathPathExpr, [xpath_grammar_rules_1.XPathFilterExpr, tokens_1.TOK_DSLASH, xpath_grammar_rules_1.XPathRelativeLocationPath], 19, this.makePathExpr2],
|
|
112
|
-
[xpath_grammar_rules_1.XPathFilterExpr, [xpath_grammar_rules_1.XPathPrimaryExpr, xpath_grammar_rules_1.XPathPredicate, tokens_1.
|
|
113
|
-
[xpath_grammar_rules_1.XPathExpr, [xpath_grammar_rules_1.XPathPrimaryExpr], 16, this.passExpr],
|
|
114
|
-
[xpath_grammar_rules_1.XPathExpr, [xpath_grammar_rules_1.XPathUnionExpr], 16, this.passExpr],
|
|
115
|
-
[xpath_grammar_rules_1.XPathExpr, [tokens_1.TOK_MINUS, xpath_grammar_rules_1.XPathExpr], -1, this.makeUnaryMinusExpr],
|
|
116
|
-
[xpath_grammar_rules_1.XPathExpr, [xpath_grammar_rules_1.XPathExpr, tokens_1.TOK_OR, xpath_grammar_rules_1.XPathExpr], -1, this.makeBinaryExpr],
|
|
117
|
-
[xpath_grammar_rules_1.XPathExpr, [xpath_grammar_rules_1.XPathExpr, tokens_1.TOK_AND, xpath_grammar_rules_1.XPathExpr], -1, this.makeBinaryExpr],
|
|
118
|
-
[xpath_grammar_rules_1.XPathExpr, [xpath_grammar_rules_1.XPathExpr, tokens_1.TOK_EQ, xpath_grammar_rules_1.XPathExpr], -1, this.makeBinaryExpr],
|
|
119
|
-
[xpath_grammar_rules_1.XPathExpr, [xpath_grammar_rules_1.XPathExpr, tokens_1.TOK_NEQ, xpath_grammar_rules_1.XPathExpr], -1, this.makeBinaryExpr],
|
|
120
|
-
[xpath_grammar_rules_1.XPathExpr, [xpath_grammar_rules_1.XPathExpr, tokens_1.TOK_LT, xpath_grammar_rules_1.XPathExpr], -1, this.makeBinaryExpr],
|
|
121
|
-
[xpath_grammar_rules_1.XPathExpr, [xpath_grammar_rules_1.XPathExpr, tokens_1.TOK_LE, xpath_grammar_rules_1.XPathExpr], -1, this.makeBinaryExpr],
|
|
122
|
-
[xpath_grammar_rules_1.XPathExpr, [xpath_grammar_rules_1.XPathExpr, tokens_1.TOK_GT, xpath_grammar_rules_1.XPathExpr], -1, this.makeBinaryExpr],
|
|
123
|
-
[xpath_grammar_rules_1.XPathExpr, [xpath_grammar_rules_1.XPathExpr, tokens_1.TOK_GE, xpath_grammar_rules_1.XPathExpr], -1, this.makeBinaryExpr],
|
|
124
|
-
[xpath_grammar_rules_1.XPathExpr, [xpath_grammar_rules_1.XPathExpr, tokens_1.TOK_PLUS, xpath_grammar_rules_1.XPathExpr], -1, this.makeBinaryExpr, tokens_1.ASSOC_LEFT],
|
|
125
|
-
[xpath_grammar_rules_1.XPathExpr, [xpath_grammar_rules_1.XPathExpr, tokens_1.TOK_MINUS, xpath_grammar_rules_1.XPathExpr], -1, this.makeBinaryExpr, tokens_1.ASSOC_LEFT],
|
|
126
|
-
[xpath_grammar_rules_1.XPathExpr, [xpath_grammar_rules_1.XPathExpr, tokens_1.TOK_ASTERISK, xpath_grammar_rules_1.XPathExpr], -1, this.makeBinaryExpr, tokens_1.ASSOC_LEFT],
|
|
127
|
-
[xpath_grammar_rules_1.XPathExpr, [xpath_grammar_rules_1.XPathExpr, tokens_1.TOK_DIV, xpath_grammar_rules_1.XPathExpr], -1, this.makeBinaryExpr, tokens_1.ASSOC_LEFT],
|
|
128
|
-
[xpath_grammar_rules_1.XPathExpr, [xpath_grammar_rules_1.XPathExpr, tokens_1.TOK_MOD, xpath_grammar_rules_1.XPathExpr], -1, this.makeBinaryExpr, tokens_1.ASSOC_LEFT],
|
|
129
|
-
[xpath_grammar_rules_1.XPathLiteral, [tokens_1.TOK_LITERALQ], -1, this.makeLiteralExpr],
|
|
130
|
-
[xpath_grammar_rules_1.XPathLiteral, [tokens_1.TOK_LITERALQQ], -1, this.makeLiteralExpr],
|
|
131
|
-
[xpath_grammar_rules_1.XPathNumber, [tokens_1.TOK_NUMBER], -1, this.makeNumberExpr],
|
|
132
|
-
[xpath_grammar_rules_1.XPathVariableReference, [tokens_1.TOK_DOLLAR, tokens_1.TOK_QNAME], 200, this.makeVariableReference]
|
|
133
|
-
];
|
|
134
|
-
this.xPathParseCache = {};
|
|
135
|
-
this.xPathRules = [];
|
|
136
|
-
this.xPathLog = function () { };
|
|
137
|
-
this.lexerCount = 0;
|
|
138
|
-
this.parseCount = 0;
|
|
139
|
-
this.reduceCount = 0;
|
|
140
|
-
}
|
|
141
|
-
// Factory functions for semantic values (i.e. Expressions) of the
|
|
142
|
-
// productions in the grammar. When a production is matched to reduce
|
|
143
|
-
// the current parse state stack, the export function is called with the
|
|
144
|
-
// semantic values of the matched elements as arguments, and returns
|
|
145
|
-
// another semantic value. The semantic value is a node of the parse
|
|
146
|
-
// tree, an expression object with an evaluate() method that evaluates the
|
|
147
|
-
// expression in an actual context. These factory functions are used
|
|
148
|
-
// in the specification of the grammar rules, below.
|
|
149
|
-
XPath.prototype.makeTokenExpr = function (m) {
|
|
150
|
-
return new expressions_1.TokenExpr(m);
|
|
151
|
-
};
|
|
152
|
-
XPath.prototype.passExpr = function (e) {
|
|
153
|
-
return e;
|
|
154
|
-
};
|
|
155
|
-
XPath.prototype.makeLocationExpr1 = function (slash, rel) {
|
|
156
|
-
rel.absolute = true;
|
|
157
|
-
return rel;
|
|
158
|
-
};
|
|
159
|
-
XPath.prototype.makeLocationExpr2 = function (dslash, rel) {
|
|
160
|
-
rel.absolute = true;
|
|
161
|
-
rel.prependStep(this.makeAbbrevStep(dslash.value));
|
|
162
|
-
return rel;
|
|
163
|
-
};
|
|
164
|
-
XPath.prototype.makeLocationExpr3 = function () {
|
|
165
|
-
var ret = new expressions_1.LocationExpr(this);
|
|
166
|
-
ret.appendStep(this.makeAbbrevStep('.'));
|
|
167
|
-
ret.absolute = true;
|
|
168
|
-
return ret;
|
|
169
|
-
};
|
|
170
|
-
XPath.prototype.makeLocationExpr4 = function (dslash) {
|
|
171
|
-
var ret = new expressions_1.LocationExpr(this);
|
|
172
|
-
ret.absolute = true;
|
|
173
|
-
ret.appendStep(this.makeAbbrevStep(dslash.value));
|
|
174
|
-
return ret;
|
|
175
|
-
};
|
|
176
|
-
XPath.prototype.makeLocationExpr5 = function (step) {
|
|
177
|
-
var ret = new expressions_1.LocationExpr(this);
|
|
178
|
-
ret.appendStep(step);
|
|
179
|
-
return ret;
|
|
180
|
-
};
|
|
181
|
-
XPath.prototype.makeLocationExpr6 = function (rel, slash, step) {
|
|
182
|
-
rel.appendStep(step);
|
|
183
|
-
return rel;
|
|
184
|
-
};
|
|
185
|
-
XPath.prototype.makeLocationExpr7 = function (rel, dslash, step) {
|
|
186
|
-
rel.appendStep(this.makeAbbrevStep(dslash.value));
|
|
187
|
-
rel.appendStep(step);
|
|
188
|
-
return rel;
|
|
189
|
-
};
|
|
190
|
-
XPath.prototype.makeStepExpr1 = function (dot) {
|
|
191
|
-
return this.makeAbbrevStep(dot.value);
|
|
192
|
-
};
|
|
193
|
-
XPath.prototype.makeStepExpr2 = function (ddot) {
|
|
194
|
-
return this.makeAbbrevStep(ddot.value);
|
|
195
|
-
};
|
|
196
|
-
XPath.prototype.makeStepExpr3 = function (axisname, axis, nodeTest) {
|
|
197
|
-
return new expressions_1.StepExpr(axisname.value, nodeTest, this);
|
|
198
|
-
};
|
|
199
|
-
XPath.prototype.makeStepExpr4 = function (at, nodeTest) {
|
|
200
|
-
return new expressions_1.StepExpr('attribute', nodeTest, this);
|
|
201
|
-
};
|
|
202
|
-
XPath.prototype.makeStepExpr5 = function (nodeTest, axis) {
|
|
203
|
-
return new expressions_1.StepExpr(axis || 'child', nodeTest, this);
|
|
204
|
-
};
|
|
205
|
-
XPath.prototype.makeStepExpr6 = function (step, predicate) {
|
|
206
|
-
step.appendPredicate(predicate);
|
|
207
|
-
return step;
|
|
208
|
-
};
|
|
209
|
-
XPath.prototype.makeAbbrevStep = function (abbrev) {
|
|
210
|
-
switch (abbrev) {
|
|
211
|
-
case '//':
|
|
212
|
-
return new expressions_1.StepExpr('descendant-or-self', new node_tests_1.NodeTestAny(), this);
|
|
213
|
-
case '.':
|
|
214
|
-
return new expressions_1.StepExpr('self', new node_tests_1.NodeTestAny(), this);
|
|
215
|
-
case '..':
|
|
216
|
-
return new expressions_1.StepExpr('parent', new node_tests_1.NodeTestAny(), this);
|
|
217
|
-
}
|
|
218
|
-
};
|
|
219
|
-
XPath.prototype.makeNodeTestExpr1 = function () {
|
|
220
|
-
return new node_tests_1.NodeTestElementOrAttribute();
|
|
221
|
-
};
|
|
222
|
-
XPath.prototype.makeNodeTestExpr2 = function (ncname) {
|
|
223
|
-
return new node_tests_1.NodeTestNC(ncname.value);
|
|
224
|
-
};
|
|
225
|
-
XPath.prototype.makeNodeTestExpr3 = function (qname) {
|
|
226
|
-
return new node_tests_1.NodeTestName(qname.value);
|
|
227
|
-
};
|
|
228
|
-
XPath.prototype.makeNodeTestExpr4 = function (typeo) {
|
|
229
|
-
var type = typeo.value.replace(/\s*\($/, '');
|
|
230
|
-
switch (type) {
|
|
231
|
-
case 'node':
|
|
232
|
-
return new node_tests_1.NodeTestAny();
|
|
233
|
-
case 'text':
|
|
234
|
-
return new node_tests_1.NodeTestText();
|
|
235
|
-
case 'comment':
|
|
236
|
-
return new node_tests_1.NodeTestComment();
|
|
237
|
-
case 'processing-instruction':
|
|
238
|
-
return new node_tests_1.NodeTestPI('');
|
|
239
|
-
}
|
|
240
|
-
};
|
|
241
|
-
XPath.prototype.makeNodeTestExpr5 = function (typeo, target) {
|
|
242
|
-
var type = typeo.replace(/\s*\($/, '');
|
|
243
|
-
if (type != 'processing-instruction') {
|
|
244
|
-
throw type;
|
|
245
|
-
}
|
|
246
|
-
return new node_tests_1.NodeTestPI(target.value);
|
|
247
|
-
};
|
|
248
|
-
XPath.prototype.makePredicateExpr = function (pareno,
|
|
249
|
-
return new expressions_1.PredicateExpr(
|
|
250
|
-
};
|
|
251
|
-
XPath.prototype.makePrimaryExpr = function (pareno,
|
|
252
|
-
return
|
|
253
|
-
};
|
|
254
|
-
XPath.prototype.makeFunctionCallExpr1 = function (name) {
|
|
255
|
-
return new expressions_1.FunctionCallExpr(name);
|
|
256
|
-
};
|
|
257
|
-
XPath.prototype.makeFunctionCallExpr2 = function (name, pareno, arg1, args) {
|
|
258
|
-
var ret = new expressions_1.FunctionCallExpr(name);
|
|
259
|
-
ret.appendArg(arg1);
|
|
260
|
-
for (var i = 0; i < args.length; ++i) {
|
|
261
|
-
ret.appendArg(args[i]);
|
|
262
|
-
}
|
|
263
|
-
return ret;
|
|
264
|
-
};
|
|
265
|
-
XPath.prototype.makeArgumentExpr = function (comma,
|
|
266
|
-
return
|
|
267
|
-
};
|
|
268
|
-
XPath.prototype.makeUnionExpr = function (expr1, pipe, expr2) {
|
|
269
|
-
return new expressions_1.UnionExpr(expr1, expr2);
|
|
270
|
-
};
|
|
271
|
-
XPath.prototype.makePathExpr1 = function (filter, slash, rel) {
|
|
272
|
-
return new expressions_1.PathExpr(filter, rel);
|
|
273
|
-
};
|
|
274
|
-
XPath.prototype.makePathExpr2 = function (filter, dslash, rel) {
|
|
275
|
-
rel.prependStep(this.makeAbbrevStep(dslash.value));
|
|
276
|
-
return new expressions_1.PathExpr(filter, rel);
|
|
277
|
-
};
|
|
278
|
-
XPath.prototype.makeFilterExpr = function (expr, predicates) {
|
|
279
|
-
if (predicates.length > 0) {
|
|
280
|
-
return new expressions_1.FilterExpr(expr, predicates);
|
|
281
|
-
}
|
|
282
|
-
return expr;
|
|
283
|
-
};
|
|
284
|
-
XPath.prototype.makeUnaryMinusExpr = function (minus, expr) {
|
|
285
|
-
return new expressions_1.UnaryMinusExpr(expr);
|
|
286
|
-
};
|
|
287
|
-
XPath.prototype.makeBinaryExpr = function (expr1, op, expr2) {
|
|
288
|
-
return new expressions_1.BinaryExpr(expr1, op, expr2);
|
|
289
|
-
};
|
|
290
|
-
XPath.prototype.makeLiteralExpr = function (token) {
|
|
291
|
-
// remove quotes from the parsed value:
|
|
292
|
-
var value = token.value.substring(1, token.value.length - 1);
|
|
293
|
-
return new expressions_1.LiteralExpr(value);
|
|
294
|
-
};
|
|
295
|
-
XPath.prototype.makeNumberExpr = function (token) {
|
|
296
|
-
return new expressions_1.NumberExpr(token.value);
|
|
297
|
-
};
|
|
298
|
-
XPath.prototype.makeVariableReference = function (dollar, name) {
|
|
299
|
-
return new expressions_1.VariableExpr(name.value);
|
|
300
|
-
};
|
|
301
|
-
/**
|
|
302
|
-
* Used before parsing for optimization of common simple cases. See
|
|
303
|
-
* the begin of xPathParse() for which they are.
|
|
304
|
-
* @param expression The XPath expression.
|
|
305
|
-
* @param axis The axis, if required. Default is 'child'.
|
|
306
|
-
* @returns An `Expression` object.
|
|
307
|
-
*/
|
|
308
|
-
XPath.prototype.makeSimpleExpr = function (expression, axis) {
|
|
309
|
-
if (expression.charAt(0) == '$') {
|
|
310
|
-
return new expressions_1.VariableExpr(expression.substr(1));
|
|
311
|
-
}
|
|
312
|
-
if (expression.charAt(0) == '@') {
|
|
313
|
-
var a_1 = new node_tests_1.NodeTestName(expression.substr(1));
|
|
314
|
-
var b_1 = new expressions_1.StepExpr('attribute', a_1, this);
|
|
315
|
-
var c_1 = new expressions_1.LocationExpr(this);
|
|
316
|
-
c_1.appendStep(b_1);
|
|
317
|
-
return c_1;
|
|
318
|
-
}
|
|
319
|
-
if (expression.match(/^[0-9]+$/)) {
|
|
320
|
-
return new expressions_1.NumberExpr(expression);
|
|
321
|
-
}
|
|
322
|
-
var a = new node_tests_1.NodeTestName(expression);
|
|
323
|
-
var b = new expressions_1.StepExpr(axis || tokens_1.xPathAxis.CHILD, a, this);
|
|
324
|
-
var c = new expressions_1.LocationExpr(this);
|
|
325
|
-
c.appendStep(b);
|
|
326
|
-
return c;
|
|
327
|
-
};
|
|
328
|
-
XPath.prototype.makeSimpleExpr2 = function (expr) {
|
|
329
|
-
var steps = expr.split('/');
|
|
330
|
-
var c = new expressions_1.LocationExpr(this);
|
|
331
|
-
for (var i = 0; i < steps.length; ++i) {
|
|
332
|
-
var a = new node_tests_1.NodeTestName(steps[i]);
|
|
333
|
-
var b = new expressions_1.StepExpr(tokens_1.xPathAxis.CHILD, a, this);
|
|
334
|
-
c.appendStep(b);
|
|
335
|
-
}
|
|
336
|
-
return c;
|
|
337
|
-
};
|
|
338
|
-
XPath.prototype.stackToString = function (stack) {
|
|
339
|
-
var ret = '';
|
|
340
|
-
for (var i = 0; i < stack.length; ++i) {
|
|
341
|
-
if (ret) {
|
|
342
|
-
ret += '\n';
|
|
343
|
-
}
|
|
344
|
-
ret += stack[i].tag.label;
|
|
345
|
-
}
|
|
346
|
-
return ret;
|
|
347
|
-
};
|
|
348
|
-
XPath.prototype.xPathCacheLookup = function (expr) {
|
|
349
|
-
return this.xPathParseCache[expr];
|
|
350
|
-
};
|
|
351
|
-
XPath.prototype.xPathCollectDescendants = function (nodeList, node, opt_tagName) {
|
|
352
|
-
if (opt_tagName && node.getElementsByTagName) {
|
|
353
|
-
(0, common_function_1.copyArray)(nodeList, node.getElementsByTagName(opt_tagName));
|
|
354
|
-
return;
|
|
355
|
-
}
|
|
356
|
-
for (var n = node.firstChild; n; n = n.nextSibling) {
|
|
357
|
-
if (n.nodeType !== constants_1.DOM_ATTRIBUTE_NODE) {
|
|
358
|
-
nodeList.push(n);
|
|
359
|
-
}
|
|
360
|
-
this.xPathCollectDescendants(nodeList, n);
|
|
361
|
-
}
|
|
362
|
-
};
|
|
363
|
-
XPath.prototype.xPathCollectDescendantsReverse = function (nodeList, node) {
|
|
364
|
-
for (var n = node.lastChild; n; n = n.previousSibling) {
|
|
365
|
-
nodeList.push(n);
|
|
366
|
-
this.xPathCollectDescendantsReverse(nodeList, n);
|
|
367
|
-
}
|
|
368
|
-
};
|
|
369
|
-
/**
|
|
370
|
-
* Parses and then evaluates the given XPath expression in the given
|
|
371
|
-
* input context.
|
|
372
|
-
* @param select The xPath string.
|
|
373
|
-
* @param context The Expression Context.
|
|
374
|
-
* @returns A Node Value.
|
|
375
|
-
*/
|
|
376
|
-
XPath.prototype.xPathEval = function (select, context) {
|
|
377
|
-
var expression = this.xPathParse(select);
|
|
378
|
-
var response = expression.evaluate(context);
|
|
379
|
-
return response;
|
|
380
|
-
};
|
|
381
|
-
/**
|
|
382
|
-
* DGF - extract a tag name suitable for getElementsByTagName
|
|
383
|
-
*
|
|
384
|
-
* @param nodeTest the node test
|
|
385
|
-
* @param ignoreNonElementNodesForNTA if true, the node list returned when
|
|
386
|
-
* evaluating "node()" will not contain
|
|
387
|
-
* non-element nodes. This can boost
|
|
388
|
-
* performance. This is false by default.
|
|
389
|
-
*/
|
|
390
|
-
XPath.prototype.xPathExtractTagNameFromNodeTest = function (nodeTest, ignoreNonElementNodesForNTA) {
|
|
391
|
-
if (nodeTest instanceof node_tests_1.NodeTestName) {
|
|
392
|
-
return nodeTest.name;
|
|
393
|
-
}
|
|
394
|
-
if ((ignoreNonElementNodesForNTA && nodeTest instanceof node_tests_1.NodeTestAny) ||
|
|
395
|
-
nodeTest instanceof node_tests_1.NodeTestElementOrAttribute) {
|
|
396
|
-
return '*';
|
|
397
|
-
}
|
|
398
|
-
};
|
|
399
|
-
XPath.prototype.xPathMatchStack = function (stack, pattern) {
|
|
400
|
-
// NOTE(mesch): The stack matches for variable cardinality are
|
|
401
|
-
// greedy but don't do backtracking. This would be an issue only
|
|
402
|
-
// with rules of the form A* A, i.e. with an element with variable
|
|
403
|
-
// cardinality followed by the same element. Since that doesn't
|
|
404
|
-
// occur in the grammar at hand, all matches on the stack are
|
|
405
|
-
// unambiguous.
|
|
406
|
-
var
|
|
407
|
-
var
|
|
408
|
-
var p;
|
|
409
|
-
var s;
|
|
410
|
-
var match = [];
|
|
411
|
-
match.
|
|
412
|
-
var ds = 0;
|
|
413
|
-
for (p =
|
|
414
|
-
ds = 0;
|
|
415
|
-
var qmatch = [];
|
|
416
|
-
if (pattern[p] == tokens_1.
|
|
417
|
-
p -= 1;
|
|
418
|
-
match.push(qmatch);
|
|
419
|
-
while (s - ds >= 0 && stack[s - ds].tag == pattern[p]) {
|
|
420
|
-
qmatch.push(stack[s - ds]);
|
|
421
|
-
ds += 1;
|
|
422
|
-
match.
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
else if (pattern[p] == tokens_1.
|
|
426
|
-
p -= 1;
|
|
427
|
-
match.push(qmatch);
|
|
428
|
-
while (s - ds >= 0 && ds < 2 && stack[s - ds].tag == pattern[p]) {
|
|
429
|
-
qmatch.push(stack[s - ds]);
|
|
430
|
-
ds += 1;
|
|
431
|
-
match.
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
else if (pattern[p] == tokens_1.
|
|
435
|
-
p -= 1;
|
|
436
|
-
match.push(qmatch);
|
|
437
|
-
if (stack[s].tag == pattern[p]) {
|
|
438
|
-
while (s - ds >= 0 && stack[s - ds].tag == pattern[p]) {
|
|
439
|
-
qmatch.push(stack[s - ds]);
|
|
440
|
-
ds += 1;
|
|
441
|
-
match.
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
else {
|
|
445
|
-
return [];
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
else if (stack[s].tag == pattern[p]) {
|
|
449
|
-
match.push(stack[s]);
|
|
450
|
-
ds += 1;
|
|
451
|
-
match.
|
|
452
|
-
}
|
|
453
|
-
else {
|
|
454
|
-
return [];
|
|
455
|
-
}
|
|
456
|
-
(0, util_1.reverseInPlace)(qmatch);
|
|
457
|
-
qmatch.expr = (0, util_1.mapExpr)(qmatch, function (m) { return m.expr; });
|
|
458
|
-
}
|
|
459
|
-
(0, util_1.reverseInPlace)(match);
|
|
460
|
-
if (p === -1) {
|
|
461
|
-
return match;
|
|
462
|
-
}
|
|
463
|
-
return [];
|
|
464
|
-
};
|
|
465
|
-
/**
|
|
466
|
-
* Finds the best rule for the XPath expression provided.
|
|
467
|
-
* @param expression The XPath string expression.
|
|
468
|
-
* @param previous The previous matched XPath rule.
|
|
469
|
-
* @returns The found rule and the corresponding match.
|
|
470
|
-
*/
|
|
471
|
-
XPath.prototype.findXPathRuleForExpression = function (expression, previous) {
|
|
472
|
-
var rule = null;
|
|
473
|
-
var match = '';
|
|
474
|
-
for (var i = 0; i < tokens_1.xPathTokenRules.length; ++i) {
|
|
475
|
-
var result = tokens_1.xPathTokenRules[i].re.exec(expression);
|
|
476
|
-
this.lexerCount++;
|
|
477
|
-
if (result !== null && result.length > 0 && result[0].length > 0) {
|
|
478
|
-
rule = tokens_1.xPathTokenRules[i];
|
|
479
|
-
match = result[0];
|
|
480
|
-
break;
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
// Special case: allow operator keywords to be element and
|
|
484
|
-
// variable names.
|
|
485
|
-
// NOTE(mesch): The parser resolves conflicts by looking ahead,
|
|
486
|
-
// and this is the only case where we look back to
|
|
487
|
-
// disambiguate. So this is indeed something different, and
|
|
488
|
-
// looking back is usually done in the lexer (via states in the
|
|
489
|
-
// general case, called "start conditions" in flex(1)). Also, the
|
|
490
|
-
// conflict resolution in the parser is not as robust as it could
|
|
491
|
-
// be, so I'd like to keep as much off the parser as possible (all
|
|
492
|
-
// these precedence values should be computed from the grammar
|
|
493
|
-
// rules and possibly associativity declarations, as in bison(1),
|
|
494
|
-
// and not explicitly set.
|
|
495
|
-
if (rule &&
|
|
496
|
-
(rule == tokens_1.TOK_DIV || rule == tokens_1.TOK_MOD || rule == tokens_1.TOK_AND || rule == tokens_1.TOK_OR) &&
|
|
497
|
-
(!previous ||
|
|
498
|
-
previous.tag == tokens_1.TOK_AT ||
|
|
499
|
-
previous.tag == tokens_1.TOK_DSLASH ||
|
|
500
|
-
previous.tag == tokens_1.TOK_SLASH ||
|
|
501
|
-
previous.tag == tokens_1.TOK_AXIS ||
|
|
502
|
-
previous.tag == tokens_1.TOK_DOLLAR)) {
|
|
503
|
-
rule = tokens_1.TOK_QNAME;
|
|
504
|
-
}
|
|
505
|
-
return { rule: rule, match: match };
|
|
506
|
-
};
|
|
507
|
-
/**
|
|
508
|
-
* Initialization for `xPathParse`.
|
|
509
|
-
* @see xPathParse
|
|
510
|
-
*/
|
|
511
|
-
XPath.prototype.xPathParseInit = function () {
|
|
512
|
-
if (this.xPathRules.length) {
|
|
513
|
-
return;
|
|
514
|
-
}
|
|
515
|
-
var xPathNonTerminals = [
|
|
516
|
-
xpath_grammar_rules_1.XPathLocationPath,
|
|
517
|
-
xpath_grammar_rules_1.XPathRelativeLocationPath,
|
|
518
|
-
xpath_grammar_rules_1.XPathAbsoluteLocationPath,
|
|
519
|
-
xpath_grammar_rules_1.XPathStep,
|
|
520
|
-
xpath_grammar_rules_1.XPathNodeTest,
|
|
521
|
-
xpath_grammar_rules_1.XPathPredicate,
|
|
522
|
-
xpath_grammar_rules_1.XPathLiteral,
|
|
523
|
-
xpath_grammar_rules_1.XPathExpr,
|
|
524
|
-
xpath_grammar_rules_1.XPathPrimaryExpr,
|
|
525
|
-
xpath_grammar_rules_1.XPathVariableReference,
|
|
526
|
-
xpath_grammar_rules_1.XPathNumber,
|
|
527
|
-
xpath_grammar_rules_1.XPathFunctionCall,
|
|
528
|
-
xpath_grammar_rules_1.XPathArgumentRemainder,
|
|
529
|
-
xpath_grammar_rules_1.XPathPathExpr,
|
|
530
|
-
xpath_grammar_rules_1.XPathUnionExpr,
|
|
531
|
-
xpath_grammar_rules_1.XPathFilterExpr,
|
|
532
|
-
xpath_grammar_rules_1.XPathDigits
|
|
533
|
-
];
|
|
534
|
-
// Some simple optimizations for the xpath expression parser: sort
|
|
535
|
-
// grammar rules descending by length, so that the longest match is
|
|
536
|
-
// first found.
|
|
537
|
-
this.xPathGrammarRules.sort(function (a, b) {
|
|
538
|
-
var la = a[1].length;
|
|
539
|
-
var lb = b[1].length;
|
|
540
|
-
if (la < lb) {
|
|
541
|
-
return 1;
|
|
542
|
-
}
|
|
543
|
-
else if (la > lb) {
|
|
544
|
-
return -1;
|
|
545
|
-
}
|
|
546
|
-
return 0;
|
|
547
|
-
});
|
|
548
|
-
var k = 1;
|
|
549
|
-
for (var i = 0; i < xPathNonTerminals.length; ++i) {
|
|
550
|
-
xPathNonTerminals[i].key = k++;
|
|
551
|
-
}
|
|
552
|
-
for (var i = 0; i < tokens_1.xPathTokenRules.length; ++i) {
|
|
553
|
-
tokens_1.xPathTokenRules[i].key = k++;
|
|
554
|
-
}
|
|
555
|
-
this.xPathLog("XPath parse INIT: ".concat(k, " rules"));
|
|
556
|
-
// Another slight optimization: sort the rules into bins according
|
|
557
|
-
// to the last element (observing quantifiers), so we can restrict
|
|
558
|
-
// the match against the stack to the subest of rules that match the
|
|
559
|
-
// top of the stack.
|
|
560
|
-
//
|
|
561
|
-
// TODO(mesch): What we actually want is to compute states as in
|
|
562
|
-
// bison, so that we don't have to do any explicit and iterated
|
|
563
|
-
// match against the stack.
|
|
564
|
-
function push_(array, position, element) {
|
|
565
|
-
if (!array[position]) {
|
|
566
|
-
array[position] = [];
|
|
567
|
-
}
|
|
568
|
-
array[position].push(element);
|
|
569
|
-
}
|
|
570
|
-
for (var i = 0; i < this.xPathGrammarRules.length; ++i) {
|
|
571
|
-
var rule = this.xPathGrammarRules[i];
|
|
572
|
-
var pattern = rule[1];
|
|
573
|
-
for (var j = pattern.length - 1; j >= 0; --j) {
|
|
574
|
-
if (pattern[j] == tokens_1.
|
|
575
|
-
push_(this.xPathRules, pattern[j - 1].key, rule);
|
|
576
|
-
break;
|
|
577
|
-
}
|
|
578
|
-
else if (pattern[j] == tokens_1.
|
|
579
|
-
push_(this.xPathRules, pattern[j - 1].key, rule);
|
|
580
|
-
--j;
|
|
581
|
-
}
|
|
582
|
-
else {
|
|
583
|
-
push_(this.xPathRules, pattern[j].key, rule);
|
|
584
|
-
break;
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
this.xPathLog("XPath parse INIT: ".concat(this.xPathRules.length, " rule bins"));
|
|
589
|
-
var sum = 0;
|
|
590
|
-
(0, util_1.mapExec)(this.xPathRules, function (i) {
|
|
591
|
-
if (i) {
|
|
592
|
-
sum += i.length;
|
|
593
|
-
}
|
|
594
|
-
});
|
|
595
|
-
this.xPathLog("XPath parse INIT: ".concat(sum / this.xPathRules.length, " average bin size"));
|
|
596
|
-
};
|
|
597
|
-
/**
|
|
598
|
-
* The entry point for the parser.
|
|
599
|
-
* @param expression a string that contains an XPath expression.
|
|
600
|
-
* @param axis The XPath axis. Used when the match does not start with the parent.
|
|
601
|
-
* @returns an expression object that can be evaluated with an
|
|
602
|
-
* expression context.
|
|
603
|
-
*/
|
|
604
|
-
XPath.prototype.xPathParse = function (expression, axis) {
|
|
605
|
-
var originalExpression = "".concat(expression);
|
|
606
|
-
this.xPathLog("parse ".concat(expression));
|
|
607
|
-
this.xPathParseInit();
|
|
608
|
-
// TODO: Removing the cache for now.
|
|
609
|
-
// The cache became a real problem when having to deal with `self-and-siblings`
|
|
610
|
-
// axis.
|
|
611
|
-
/* const cached = this.xPathCacheLookup(expression);
|
|
612
|
-
if (cached && axis === undefined) {
|
|
613
|
-
this.xPathLog(' ... cached');
|
|
614
|
-
return cached;
|
|
615
|
-
} */
|
|
616
|
-
// Optimize for a few common cases: simple attribute node tests
|
|
617
|
-
// (@id), simple element node tests (page), variable references
|
|
618
|
-
// ($address), numbers (4), multi-step path expressions where each
|
|
619
|
-
// step is a plain element node test
|
|
620
|
-
// (page/overlay/locations/location).
|
|
621
|
-
if (expression.match(/^(\$|@)?\w+$/i)) {
|
|
622
|
-
var ret = this.makeSimpleExpr(expression, axis);
|
|
623
|
-
this.xPathParseCache[expression] = ret;
|
|
624
|
-
this.xPathLog(' ... simple');
|
|
625
|
-
return ret;
|
|
626
|
-
}
|
|
627
|
-
if (expression.match(/^\w+(\/\w+)*$/i)) {
|
|
628
|
-
var ret = this.makeSimpleExpr2(expression);
|
|
629
|
-
this.xPathParseCache[expression] = ret;
|
|
630
|
-
this.xPathLog(' ... simple 2');
|
|
631
|
-
return ret;
|
|
632
|
-
}
|
|
633
|
-
var cachekey = expression; // expression is modified during parse
|
|
634
|
-
var stack = [];
|
|
635
|
-
var ahead = null;
|
|
636
|
-
var previous = null;
|
|
637
|
-
var done = false;
|
|
638
|
-
var parseCount = 0;
|
|
639
|
-
this.lexerCount = 0;
|
|
640
|
-
var reduceCount = 0;
|
|
641
|
-
while (!done) {
|
|
642
|
-
parseCount++;
|
|
643
|
-
expression = expression.replace(/^\s*/, '');
|
|
644
|
-
previous = ahead;
|
|
645
|
-
ahead = null;
|
|
646
|
-
var _a = this.findXPathRuleForExpression(expression, previous), rule = _a.rule, match = _a.match;
|
|
647
|
-
if (rule) {
|
|
648
|
-
expression = expression.substr(match.length);
|
|
649
|
-
this.xPathLog("token: ".concat(match, " -- ").concat(rule.label));
|
|
650
|
-
ahead = {
|
|
651
|
-
tag: rule,
|
|
652
|
-
match: match,
|
|
653
|
-
prec: rule.prec ? rule.prec : 0,
|
|
654
|
-
expr: this.makeTokenExpr(match)
|
|
655
|
-
};
|
|
656
|
-
}
|
|
657
|
-
else {
|
|
658
|
-
this.xPathLog('DONE');
|
|
659
|
-
done = true;
|
|
660
|
-
}
|
|
661
|
-
while (this.xPathReduce(stack, ahead)) {
|
|
662
|
-
reduceCount++;
|
|
663
|
-
this.xPathLog("stack: ".concat(this.stackToString(stack)));
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
this.xPathLog("stack: ".concat(this.stackToString(stack)));
|
|
667
|
-
// DGF any valid XPath should "reduce" to a single Expr token
|
|
668
|
-
if (stack.length !== 1) {
|
|
669
|
-
throw "XPath parse error ".concat(cachekey, ":\n").concat(this.stackToString(stack));
|
|
670
|
-
}
|
|
671
|
-
var result = stack[0].expr;
|
|
672
|
-
// TODO: Remove this `if` after getting to rewrite `xPathReduce`.
|
|
673
|
-
if (axis !== undefined &&
|
|
674
|
-
!result.absolute &&
|
|
675
|
-
!originalExpression.startsWith('*') &&
|
|
676
|
-
result.steps &&
|
|
677
|
-
Array.isArray(result.steps)) {
|
|
678
|
-
result.steps[0].axis = axis;
|
|
679
|
-
}
|
|
680
|
-
this.xPathParseCache[cachekey] = result;
|
|
681
|
-
this.xPathLog("XPath parse: ".concat(parseCount, " / ").concat(this.lexerCount, " / ").concat(reduceCount));
|
|
682
|
-
return result;
|
|
683
|
-
};
|
|
684
|
-
XPath.prototype.findGrammarRuleCandidate = function (ruleset, stack) {
|
|
685
|
-
for (var i = 0; i < ruleset.length; ++i) {
|
|
686
|
-
var rule = ruleset[i];
|
|
687
|
-
var match = this.xPathMatchStack(stack, rule[1]);
|
|
688
|
-
if (match.length) {
|
|
689
|
-
var candidate = {
|
|
690
|
-
tag: rule[0],
|
|
691
|
-
rule: rule,
|
|
692
|
-
match: match,
|
|
693
|
-
prec: undefined
|
|
694
|
-
};
|
|
695
|
-
candidate.prec = this.xPathGrammarPrecedence(candidate);
|
|
696
|
-
return candidate;
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
return null;
|
|
700
|
-
};
|
|
701
|
-
/**
|
|
702
|
-
* DGF xPathReduce is where the magic happens in this parser.
|
|
703
|
-
* Check `src\xpath\xpath-grammar-rules.ts` to find the table of
|
|
704
|
-
* grammatical rules and precedence numbers, "The productions of the grammar".
|
|
705
|
-
*
|
|
706
|
-
* The idea here is that we want to take a stack of tokens and apply
|
|
707
|
-
* grammatical rules to them, "reducing" them to higher-level
|
|
708
|
-
* tokens. Ultimately, any valid XPath should reduce to exactly one
|
|
709
|
-
* "Expr" token.
|
|
710
|
-
|
|
711
|
-
* Reduce too early or too late and you'll have two tokens that can't reduce
|
|
712
|
-
* to single Expr. For example, you may hastily reduce a qname that
|
|
713
|
-
* should name a function, incorrectly treating it as a tag name.
|
|
714
|
-
* Or you may reduce too late, accidentally reducing the last part of the
|
|
715
|
-
* XPath into a top-level "Expr" that won't reduce with earlier parts of
|
|
716
|
-
* the XPath.
|
|
717
|
-
*
|
|
718
|
-
* A "candidate" is a grammatical rule candidate, with a given precedence
|
|
719
|
-
* number. "ahead" is the upcoming token, which also has a precedence
|
|
720
|
-
* number. If the token has a higher precedence number than
|
|
721
|
-
* the rule candidate, we'll "shift" the token onto the token stack,
|
|
722
|
-
* instead of immediately applying the rule candidate.
|
|
723
|
-
*
|
|
724
|
-
* Some tokens have left associativity, in which case we shift when they
|
|
725
|
-
* have LOWER precedence than the candidate.
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
candidate.
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
*
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
var
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
//
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
//
|
|
811
|
-
//
|
|
812
|
-
//
|
|
813
|
-
//
|
|
814
|
-
//
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
//
|
|
837
|
-
//
|
|
838
|
-
//
|
|
839
|
-
//
|
|
840
|
-
//
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
//
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
}
|
|
909
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright 2023-2024 Design Liquido
|
|
3
|
+
// Copyright 2018 Johannes Wilm
|
|
4
|
+
// Copyright 2005 Google Inc.
|
|
5
|
+
// All Rights Reserved
|
|
6
|
+
//
|
|
7
|
+
// An XPath parser and evaluator written in JavaScript. The
|
|
8
|
+
// implementation is complete except for functions handling
|
|
9
|
+
// namespaces.
|
|
10
|
+
//
|
|
11
|
+
// Reference: [XPATH] XPath Specification
|
|
12
|
+
// <http://www.w3.org/TR/1999/REC-xpath-19991116>.
|
|
13
|
+
//
|
|
14
|
+
//
|
|
15
|
+
// The API of the parser has several parts:
|
|
16
|
+
//
|
|
17
|
+
// 1. The parser function xpathParse() that takes a string and returns
|
|
18
|
+
// an expession object.
|
|
19
|
+
//
|
|
20
|
+
// 2. The expression object that has an evaluate() method to evaluate the
|
|
21
|
+
// XPath expression it represents. (It is actually a hierarchy of
|
|
22
|
+
// objects that resembles the parse tree, but an application will call
|
|
23
|
+
// evaluate() only on the top node of this hierarchy.)
|
|
24
|
+
//
|
|
25
|
+
// 3. The context object that is passed as an argument to the evaluate()
|
|
26
|
+
// method, which represents the DOM context in which the expression is
|
|
27
|
+
// evaluated.
|
|
28
|
+
//
|
|
29
|
+
// 4. The value object that is returned from evaluate() and represents
|
|
30
|
+
// values of the different types that are defined by XPath (number,
|
|
31
|
+
// string, boolean, and node-set), and allows to convert between them.
|
|
32
|
+
//
|
|
33
|
+
// These parts are near the top of the file, the functions and data
|
|
34
|
+
// that are used internally follow after them.
|
|
35
|
+
//
|
|
36
|
+
//
|
|
37
|
+
// Original author: Steffen Meschkat <mesch@google.com>
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.XPath = void 0;
|
|
40
|
+
var util_1 = require("../dom/util");
|
|
41
|
+
var common_function_1 = require("./common-function");
|
|
42
|
+
var expressions_1 = require("./expressions");
|
|
43
|
+
var tokens_1 = require("./tokens");
|
|
44
|
+
var xpath_grammar_rules_1 = require("./xpath-grammar-rules");
|
|
45
|
+
var node_tests_1 = require("./node-tests");
|
|
46
|
+
var constants_1 = require("../constants");
|
|
47
|
+
var XPath = /** @class */ (function () {
|
|
48
|
+
function XPath() {
|
|
49
|
+
// The productions of the grammar. Columns of the table:
|
|
50
|
+
//
|
|
51
|
+
// - target non-terminal,
|
|
52
|
+
// - pattern,
|
|
53
|
+
// - precedence,
|
|
54
|
+
// - semantic value factory
|
|
55
|
+
//
|
|
56
|
+
// The semantic value factory is a function that receives parse tree
|
|
57
|
+
// nodes from the stack frames of the matched symbols as arguments and
|
|
58
|
+
// returns an a node of the parse tree. The node is stored in the top
|
|
59
|
+
// stack frame along with the target object of the rule. The node in
|
|
60
|
+
// the parse tree is an expression object that has an evaluate() method
|
|
61
|
+
// and thus evaluates XPath expressions.
|
|
62
|
+
//
|
|
63
|
+
// The precedence is used to decide between reducing and shifting by
|
|
64
|
+
// comparing the precedence of the rule that is candidate for
|
|
65
|
+
// reducing with the precedence of the look ahead token. Precedence of
|
|
66
|
+
// -1 means that the precedence of the tokens in the pattern is used
|
|
67
|
+
// instead. TODO: It shouldn't be necessary to explicitly assign
|
|
68
|
+
// precedences to rules.
|
|
69
|
+
// DGF As it stands, these precedences are purely empirical; we're
|
|
70
|
+
// not sure if they can be made to be consistent at all.
|
|
71
|
+
this.xPathGrammarRules = [
|
|
72
|
+
[xpath_grammar_rules_1.XPathLocationPath, [xpath_grammar_rules_1.XPathRelativeLocationPath], 18, this.passExpr],
|
|
73
|
+
[xpath_grammar_rules_1.XPathLocationPath, [xpath_grammar_rules_1.XPathAbsoluteLocationPath], 18, this.passExpr],
|
|
74
|
+
[xpath_grammar_rules_1.XPathAbsoluteLocationPath, [tokens_1.TOK_SLASH, xpath_grammar_rules_1.XPathRelativeLocationPath], 18, this.makeLocationExpr1],
|
|
75
|
+
[xpath_grammar_rules_1.XPathAbsoluteLocationPath, [tokens_1.TOK_DSLASH, xpath_grammar_rules_1.XPathRelativeLocationPath], 18, this.makeLocationExpr2],
|
|
76
|
+
[xpath_grammar_rules_1.XPathAbsoluteLocationPath, [tokens_1.TOK_SLASH], 0, this.makeLocationExpr3],
|
|
77
|
+
[xpath_grammar_rules_1.XPathAbsoluteLocationPath, [tokens_1.TOK_DSLASH], 0, this.makeLocationExpr4],
|
|
78
|
+
[xpath_grammar_rules_1.XPathRelativeLocationPath, [xpath_grammar_rules_1.XPathStep], 31, this.makeLocationExpr5],
|
|
79
|
+
[xpath_grammar_rules_1.XPathRelativeLocationPath, [xpath_grammar_rules_1.XPathRelativeLocationPath, tokens_1.TOK_SLASH, xpath_grammar_rules_1.XPathStep], 31, this.makeLocationExpr6],
|
|
80
|
+
[xpath_grammar_rules_1.XPathRelativeLocationPath, [xpath_grammar_rules_1.XPathRelativeLocationPath, tokens_1.TOK_DSLASH, xpath_grammar_rules_1.XPathStep], 31, this.makeLocationExpr7],
|
|
81
|
+
[xpath_grammar_rules_1.XPathStep, [tokens_1.TOK_DOT], 33, this.makeStepExpr1],
|
|
82
|
+
[xpath_grammar_rules_1.XPathStep, [tokens_1.TOK_DDOT], 33, this.makeStepExpr2],
|
|
83
|
+
[xpath_grammar_rules_1.XPathStep, [tokens_1.TOK_AXISNAME, tokens_1.TOK_AXIS, xpath_grammar_rules_1.XPathNodeTest], 33, this.makeStepExpr3],
|
|
84
|
+
[xpath_grammar_rules_1.XPathStep, [tokens_1.TOK_AT, xpath_grammar_rules_1.XPathNodeTest], 33, this.makeStepExpr4],
|
|
85
|
+
[xpath_grammar_rules_1.XPathStep, [xpath_grammar_rules_1.XPathNodeTest], 33, this.makeStepExpr5],
|
|
86
|
+
[xpath_grammar_rules_1.XPathStep, [xpath_grammar_rules_1.XPathStep, xpath_grammar_rules_1.XPathPredicate], 33, this.makeStepExpr6],
|
|
87
|
+
[xpath_grammar_rules_1.XPathNodeTest, [tokens_1.TOK_ASTERISK], 33, this.makeNodeTestExpr1],
|
|
88
|
+
[xpath_grammar_rules_1.XPathNodeTest, [tokens_1.TOK_NCNAME, tokens_1.TOK_COLON, tokens_1.TOK_ASTERISK], 33, this.makeNodeTestExpr2],
|
|
89
|
+
[xpath_grammar_rules_1.XPathNodeTest, [tokens_1.TOK_QNAME], 33, this.makeNodeTestExpr3],
|
|
90
|
+
[xpath_grammar_rules_1.XPathNodeTest, [tokens_1.TOK_NODEO, tokens_1.TOK_PARENC], 33, this.makeNodeTestExpr4],
|
|
91
|
+
[xpath_grammar_rules_1.XPathNodeTest, [tokens_1.TOK_NODEO, xpath_grammar_rules_1.XPathLiteral, tokens_1.TOK_PARENC], 33, this.makeNodeTestExpr5],
|
|
92
|
+
[xpath_grammar_rules_1.XPathPredicate, [tokens_1.TOK_BRACKO, xpath_grammar_rules_1.XPathExpr, tokens_1.TOK_BRACKC], 33, this.makePredicateExpr],
|
|
93
|
+
[xpath_grammar_rules_1.XPathPrimaryExpr, [xpath_grammar_rules_1.XPathVariableReference], 33, this.passExpr],
|
|
94
|
+
[xpath_grammar_rules_1.XPathPrimaryExpr, [tokens_1.TOK_PARENO, xpath_grammar_rules_1.XPathExpr, tokens_1.TOK_PARENC], 33, this.makePrimaryExpr],
|
|
95
|
+
[xpath_grammar_rules_1.XPathPrimaryExpr, [xpath_grammar_rules_1.XPathLiteral], 30, this.passExpr],
|
|
96
|
+
[xpath_grammar_rules_1.XPathPrimaryExpr, [xpath_grammar_rules_1.XPathNumber], 30, this.passExpr],
|
|
97
|
+
[xpath_grammar_rules_1.XPathPrimaryExpr, [xpath_grammar_rules_1.XPathFunctionCall], 31, this.passExpr],
|
|
98
|
+
[xpath_grammar_rules_1.XPathFunctionCall, [tokens_1.TOK_QNAME, tokens_1.TOK_PARENO, tokens_1.TOK_PARENC], -1, this.makeFunctionCallExpr1],
|
|
99
|
+
[
|
|
100
|
+
xpath_grammar_rules_1.XPathFunctionCall,
|
|
101
|
+
[tokens_1.TOK_QNAME, tokens_1.TOK_PARENO, xpath_grammar_rules_1.XPathExpr, xpath_grammar_rules_1.XPathArgumentRemainder, tokens_1.Q_ZERO_OR_MULTIPLE, tokens_1.TOK_PARENC],
|
|
102
|
+
-1,
|
|
103
|
+
this.makeFunctionCallExpr2
|
|
104
|
+
],
|
|
105
|
+
[xpath_grammar_rules_1.XPathArgumentRemainder, [tokens_1.TOK_COMMA, xpath_grammar_rules_1.XPathExpr], -1, this.makeArgumentExpr],
|
|
106
|
+
[xpath_grammar_rules_1.XPathUnionExpr, [xpath_grammar_rules_1.XPathPathExpr], 20, this.passExpr],
|
|
107
|
+
[xpath_grammar_rules_1.XPathUnionExpr, [xpath_grammar_rules_1.XPathUnionExpr, tokens_1.TOK_PIPE, xpath_grammar_rules_1.XPathPathExpr], 20, this.makeUnionExpr],
|
|
108
|
+
[xpath_grammar_rules_1.XPathPathExpr, [xpath_grammar_rules_1.XPathLocationPath], 20, this.passExpr],
|
|
109
|
+
[xpath_grammar_rules_1.XPathPathExpr, [xpath_grammar_rules_1.XPathFilterExpr], 19, this.passExpr],
|
|
110
|
+
[xpath_grammar_rules_1.XPathPathExpr, [xpath_grammar_rules_1.XPathFilterExpr, tokens_1.TOK_SLASH, xpath_grammar_rules_1.XPathRelativeLocationPath], 19, this.makePathExpr1],
|
|
111
|
+
[xpath_grammar_rules_1.XPathPathExpr, [xpath_grammar_rules_1.XPathFilterExpr, tokens_1.TOK_DSLASH, xpath_grammar_rules_1.XPathRelativeLocationPath], 19, this.makePathExpr2],
|
|
112
|
+
[xpath_grammar_rules_1.XPathFilterExpr, [xpath_grammar_rules_1.XPathPrimaryExpr, xpath_grammar_rules_1.XPathPredicate, tokens_1.Q_ZERO_OR_MULTIPLE], 31, this.makeFilterExpr],
|
|
113
|
+
[xpath_grammar_rules_1.XPathExpr, [xpath_grammar_rules_1.XPathPrimaryExpr], 16, this.passExpr],
|
|
114
|
+
[xpath_grammar_rules_1.XPathExpr, [xpath_grammar_rules_1.XPathUnionExpr], 16, this.passExpr],
|
|
115
|
+
[xpath_grammar_rules_1.XPathExpr, [tokens_1.TOK_MINUS, xpath_grammar_rules_1.XPathExpr], -1, this.makeUnaryMinusExpr],
|
|
116
|
+
[xpath_grammar_rules_1.XPathExpr, [xpath_grammar_rules_1.XPathExpr, tokens_1.TOK_OR, xpath_grammar_rules_1.XPathExpr], -1, this.makeBinaryExpr],
|
|
117
|
+
[xpath_grammar_rules_1.XPathExpr, [xpath_grammar_rules_1.XPathExpr, tokens_1.TOK_AND, xpath_grammar_rules_1.XPathExpr], -1, this.makeBinaryExpr],
|
|
118
|
+
[xpath_grammar_rules_1.XPathExpr, [xpath_grammar_rules_1.XPathExpr, tokens_1.TOK_EQ, xpath_grammar_rules_1.XPathExpr], -1, this.makeBinaryExpr],
|
|
119
|
+
[xpath_grammar_rules_1.XPathExpr, [xpath_grammar_rules_1.XPathExpr, tokens_1.TOK_NEQ, xpath_grammar_rules_1.XPathExpr], -1, this.makeBinaryExpr],
|
|
120
|
+
[xpath_grammar_rules_1.XPathExpr, [xpath_grammar_rules_1.XPathExpr, tokens_1.TOK_LT, xpath_grammar_rules_1.XPathExpr], -1, this.makeBinaryExpr],
|
|
121
|
+
[xpath_grammar_rules_1.XPathExpr, [xpath_grammar_rules_1.XPathExpr, tokens_1.TOK_LE, xpath_grammar_rules_1.XPathExpr], -1, this.makeBinaryExpr],
|
|
122
|
+
[xpath_grammar_rules_1.XPathExpr, [xpath_grammar_rules_1.XPathExpr, tokens_1.TOK_GT, xpath_grammar_rules_1.XPathExpr], -1, this.makeBinaryExpr],
|
|
123
|
+
[xpath_grammar_rules_1.XPathExpr, [xpath_grammar_rules_1.XPathExpr, tokens_1.TOK_GE, xpath_grammar_rules_1.XPathExpr], -1, this.makeBinaryExpr],
|
|
124
|
+
[xpath_grammar_rules_1.XPathExpr, [xpath_grammar_rules_1.XPathExpr, tokens_1.TOK_PLUS, xpath_grammar_rules_1.XPathExpr], -1, this.makeBinaryExpr, tokens_1.ASSOC_LEFT],
|
|
125
|
+
[xpath_grammar_rules_1.XPathExpr, [xpath_grammar_rules_1.XPathExpr, tokens_1.TOK_MINUS, xpath_grammar_rules_1.XPathExpr], -1, this.makeBinaryExpr, tokens_1.ASSOC_LEFT],
|
|
126
|
+
[xpath_grammar_rules_1.XPathExpr, [xpath_grammar_rules_1.XPathExpr, tokens_1.TOK_ASTERISK, xpath_grammar_rules_1.XPathExpr], -1, this.makeBinaryExpr, tokens_1.ASSOC_LEFT],
|
|
127
|
+
[xpath_grammar_rules_1.XPathExpr, [xpath_grammar_rules_1.XPathExpr, tokens_1.TOK_DIV, xpath_grammar_rules_1.XPathExpr], -1, this.makeBinaryExpr, tokens_1.ASSOC_LEFT],
|
|
128
|
+
[xpath_grammar_rules_1.XPathExpr, [xpath_grammar_rules_1.XPathExpr, tokens_1.TOK_MOD, xpath_grammar_rules_1.XPathExpr], -1, this.makeBinaryExpr, tokens_1.ASSOC_LEFT],
|
|
129
|
+
[xpath_grammar_rules_1.XPathLiteral, [tokens_1.TOK_LITERALQ], -1, this.makeLiteralExpr],
|
|
130
|
+
[xpath_grammar_rules_1.XPathLiteral, [tokens_1.TOK_LITERALQQ], -1, this.makeLiteralExpr],
|
|
131
|
+
[xpath_grammar_rules_1.XPathNumber, [tokens_1.TOK_NUMBER], -1, this.makeNumberExpr],
|
|
132
|
+
[xpath_grammar_rules_1.XPathVariableReference, [tokens_1.TOK_DOLLAR, tokens_1.TOK_QNAME], 200, this.makeVariableReference]
|
|
133
|
+
];
|
|
134
|
+
this.xPathParseCache = {};
|
|
135
|
+
this.xPathRules = [];
|
|
136
|
+
this.xPathLog = function () { };
|
|
137
|
+
this.lexerCount = 0;
|
|
138
|
+
this.parseCount = 0;
|
|
139
|
+
this.reduceCount = 0;
|
|
140
|
+
}
|
|
141
|
+
// Factory functions for semantic values (i.e. Expressions) of the
|
|
142
|
+
// productions in the grammar. When a production is matched to reduce
|
|
143
|
+
// the current parse state stack, the export function is called with the
|
|
144
|
+
// semantic values of the matched elements as arguments, and returns
|
|
145
|
+
// another semantic value. The semantic value is a node of the parse
|
|
146
|
+
// tree, an expression object with an evaluate() method that evaluates the
|
|
147
|
+
// expression in an actual context. These factory functions are used
|
|
148
|
+
// in the specification of the grammar rules, below.
|
|
149
|
+
XPath.prototype.makeTokenExpr = function (m) {
|
|
150
|
+
return new expressions_1.TokenExpr(m);
|
|
151
|
+
};
|
|
152
|
+
XPath.prototype.passExpr = function (e) {
|
|
153
|
+
return e;
|
|
154
|
+
};
|
|
155
|
+
XPath.prototype.makeLocationExpr1 = function (slash, rel) {
|
|
156
|
+
rel.absolute = true;
|
|
157
|
+
return rel;
|
|
158
|
+
};
|
|
159
|
+
XPath.prototype.makeLocationExpr2 = function (dslash, rel) {
|
|
160
|
+
rel.absolute = true;
|
|
161
|
+
rel.prependStep(this.makeAbbrevStep(dslash.value));
|
|
162
|
+
return rel;
|
|
163
|
+
};
|
|
164
|
+
XPath.prototype.makeLocationExpr3 = function () {
|
|
165
|
+
var ret = new expressions_1.LocationExpr(this);
|
|
166
|
+
ret.appendStep(this.makeAbbrevStep('.'));
|
|
167
|
+
ret.absolute = true;
|
|
168
|
+
return ret;
|
|
169
|
+
};
|
|
170
|
+
XPath.prototype.makeLocationExpr4 = function (dslash) {
|
|
171
|
+
var ret = new expressions_1.LocationExpr(this);
|
|
172
|
+
ret.absolute = true;
|
|
173
|
+
ret.appendStep(this.makeAbbrevStep(dslash.value));
|
|
174
|
+
return ret;
|
|
175
|
+
};
|
|
176
|
+
XPath.prototype.makeLocationExpr5 = function (step) {
|
|
177
|
+
var ret = new expressions_1.LocationExpr(this);
|
|
178
|
+
ret.appendStep(step);
|
|
179
|
+
return ret;
|
|
180
|
+
};
|
|
181
|
+
XPath.prototype.makeLocationExpr6 = function (rel, slash, step) {
|
|
182
|
+
rel.appendStep(step);
|
|
183
|
+
return rel;
|
|
184
|
+
};
|
|
185
|
+
XPath.prototype.makeLocationExpr7 = function (rel, dslash, step) {
|
|
186
|
+
rel.appendStep(this.makeAbbrevStep(dslash.value));
|
|
187
|
+
rel.appendStep(step);
|
|
188
|
+
return rel;
|
|
189
|
+
};
|
|
190
|
+
XPath.prototype.makeStepExpr1 = function (dot) {
|
|
191
|
+
return this.makeAbbrevStep(dot.value);
|
|
192
|
+
};
|
|
193
|
+
XPath.prototype.makeStepExpr2 = function (ddot) {
|
|
194
|
+
return this.makeAbbrevStep(ddot.value);
|
|
195
|
+
};
|
|
196
|
+
XPath.prototype.makeStepExpr3 = function (axisname, axis, nodeTest) {
|
|
197
|
+
return new expressions_1.StepExpr(axisname.value, nodeTest, this);
|
|
198
|
+
};
|
|
199
|
+
XPath.prototype.makeStepExpr4 = function (at, nodeTest) {
|
|
200
|
+
return new expressions_1.StepExpr('attribute', nodeTest, this);
|
|
201
|
+
};
|
|
202
|
+
XPath.prototype.makeStepExpr5 = function (nodeTest, axis) {
|
|
203
|
+
return new expressions_1.StepExpr(axis || 'child', nodeTest, this);
|
|
204
|
+
};
|
|
205
|
+
XPath.prototype.makeStepExpr6 = function (step, predicate) {
|
|
206
|
+
step.appendPredicate(predicate);
|
|
207
|
+
return step;
|
|
208
|
+
};
|
|
209
|
+
XPath.prototype.makeAbbrevStep = function (abbrev) {
|
|
210
|
+
switch (abbrev) {
|
|
211
|
+
case '//':
|
|
212
|
+
return new expressions_1.StepExpr('descendant-or-self', new node_tests_1.NodeTestAny(), this);
|
|
213
|
+
case '.':
|
|
214
|
+
return new expressions_1.StepExpr('self', new node_tests_1.NodeTestAny(), this);
|
|
215
|
+
case '..':
|
|
216
|
+
return new expressions_1.StepExpr('parent', new node_tests_1.NodeTestAny(), this);
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
XPath.prototype.makeNodeTestExpr1 = function () {
|
|
220
|
+
return new node_tests_1.NodeTestElementOrAttribute();
|
|
221
|
+
};
|
|
222
|
+
XPath.prototype.makeNodeTestExpr2 = function (ncname) {
|
|
223
|
+
return new node_tests_1.NodeTestNC(ncname.value);
|
|
224
|
+
};
|
|
225
|
+
XPath.prototype.makeNodeTestExpr3 = function (qname) {
|
|
226
|
+
return new node_tests_1.NodeTestName(qname.value);
|
|
227
|
+
};
|
|
228
|
+
XPath.prototype.makeNodeTestExpr4 = function (typeo) {
|
|
229
|
+
var type = typeo.value.replace(/\s*\($/, '');
|
|
230
|
+
switch (type) {
|
|
231
|
+
case 'node':
|
|
232
|
+
return new node_tests_1.NodeTestAny();
|
|
233
|
+
case 'text':
|
|
234
|
+
return new node_tests_1.NodeTestText();
|
|
235
|
+
case 'comment':
|
|
236
|
+
return new node_tests_1.NodeTestComment();
|
|
237
|
+
case 'processing-instruction':
|
|
238
|
+
return new node_tests_1.NodeTestPI('');
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
XPath.prototype.makeNodeTestExpr5 = function (typeo, target) {
|
|
242
|
+
var type = typeo.replace(/\s*\($/, '');
|
|
243
|
+
if (type != 'processing-instruction') {
|
|
244
|
+
throw type;
|
|
245
|
+
}
|
|
246
|
+
return new node_tests_1.NodeTestPI(target.value);
|
|
247
|
+
};
|
|
248
|
+
XPath.prototype.makePredicateExpr = function (pareno, expression) {
|
|
249
|
+
return new expressions_1.PredicateExpr(expression);
|
|
250
|
+
};
|
|
251
|
+
XPath.prototype.makePrimaryExpr = function (pareno, expression) {
|
|
252
|
+
return expression;
|
|
253
|
+
};
|
|
254
|
+
XPath.prototype.makeFunctionCallExpr1 = function (name) {
|
|
255
|
+
return new expressions_1.FunctionCallExpr(name);
|
|
256
|
+
};
|
|
257
|
+
XPath.prototype.makeFunctionCallExpr2 = function (name, pareno, arg1, args) {
|
|
258
|
+
var ret = new expressions_1.FunctionCallExpr(name);
|
|
259
|
+
ret.appendArg(arg1);
|
|
260
|
+
for (var i = 0; i < args.length; ++i) {
|
|
261
|
+
ret.appendArg(args[i]);
|
|
262
|
+
}
|
|
263
|
+
return ret;
|
|
264
|
+
};
|
|
265
|
+
XPath.prototype.makeArgumentExpr = function (comma, expression) {
|
|
266
|
+
return expression;
|
|
267
|
+
};
|
|
268
|
+
XPath.prototype.makeUnionExpr = function (expr1, pipe, expr2) {
|
|
269
|
+
return new expressions_1.UnionExpr(expr1, expr2);
|
|
270
|
+
};
|
|
271
|
+
XPath.prototype.makePathExpr1 = function (filter, slash, rel) {
|
|
272
|
+
return new expressions_1.PathExpr(filter, rel);
|
|
273
|
+
};
|
|
274
|
+
XPath.prototype.makePathExpr2 = function (filter, dslash, rel) {
|
|
275
|
+
rel.prependStep(this.makeAbbrevStep(dslash.value));
|
|
276
|
+
return new expressions_1.PathExpr(filter, rel);
|
|
277
|
+
};
|
|
278
|
+
XPath.prototype.makeFilterExpr = function (expr, predicates) {
|
|
279
|
+
if (predicates.length > 0) {
|
|
280
|
+
return new expressions_1.FilterExpr(expr, predicates);
|
|
281
|
+
}
|
|
282
|
+
return expr;
|
|
283
|
+
};
|
|
284
|
+
XPath.prototype.makeUnaryMinusExpr = function (minus, expr) {
|
|
285
|
+
return new expressions_1.UnaryMinusExpr(expr);
|
|
286
|
+
};
|
|
287
|
+
XPath.prototype.makeBinaryExpr = function (expr1, op, expr2) {
|
|
288
|
+
return new expressions_1.BinaryExpr(expr1, op, expr2);
|
|
289
|
+
};
|
|
290
|
+
XPath.prototype.makeLiteralExpr = function (token) {
|
|
291
|
+
// remove quotes from the parsed value:
|
|
292
|
+
var value = token.value.substring(1, token.value.length - 1);
|
|
293
|
+
return new expressions_1.LiteralExpr(value);
|
|
294
|
+
};
|
|
295
|
+
XPath.prototype.makeNumberExpr = function (token) {
|
|
296
|
+
return new expressions_1.NumberExpr(token.value);
|
|
297
|
+
};
|
|
298
|
+
XPath.prototype.makeVariableReference = function (dollar, name) {
|
|
299
|
+
return new expressions_1.VariableExpr(name.value);
|
|
300
|
+
};
|
|
301
|
+
/**
|
|
302
|
+
* Used before parsing for optimization of common simple cases. See
|
|
303
|
+
* the begin of xPathParse() for which they are.
|
|
304
|
+
* @param expression The XPath expression.
|
|
305
|
+
* @param axis The axis, if required. Default is 'child'.
|
|
306
|
+
* @returns An `Expression` object.
|
|
307
|
+
*/
|
|
308
|
+
XPath.prototype.makeSimpleExpr = function (expression, axis) {
|
|
309
|
+
if (expression.charAt(0) == '$') {
|
|
310
|
+
return new expressions_1.VariableExpr(expression.substr(1));
|
|
311
|
+
}
|
|
312
|
+
if (expression.charAt(0) == '@') {
|
|
313
|
+
var a_1 = new node_tests_1.NodeTestName(expression.substr(1));
|
|
314
|
+
var b_1 = new expressions_1.StepExpr('attribute', a_1, this);
|
|
315
|
+
var c_1 = new expressions_1.LocationExpr(this);
|
|
316
|
+
c_1.appendStep(b_1);
|
|
317
|
+
return c_1;
|
|
318
|
+
}
|
|
319
|
+
if (expression.match(/^[0-9]+$/)) {
|
|
320
|
+
return new expressions_1.NumberExpr(expression);
|
|
321
|
+
}
|
|
322
|
+
var a = new node_tests_1.NodeTestName(expression);
|
|
323
|
+
var b = new expressions_1.StepExpr(axis || tokens_1.xPathAxis.CHILD, a, this);
|
|
324
|
+
var c = new expressions_1.LocationExpr(this);
|
|
325
|
+
c.appendStep(b);
|
|
326
|
+
return c;
|
|
327
|
+
};
|
|
328
|
+
XPath.prototype.makeSimpleExpr2 = function (expr) {
|
|
329
|
+
var steps = expr.split('/');
|
|
330
|
+
var c = new expressions_1.LocationExpr(this);
|
|
331
|
+
for (var i = 0; i < steps.length; ++i) {
|
|
332
|
+
var a = new node_tests_1.NodeTestName(steps[i]);
|
|
333
|
+
var b = new expressions_1.StepExpr(tokens_1.xPathAxis.CHILD, a, this);
|
|
334
|
+
c.appendStep(b);
|
|
335
|
+
}
|
|
336
|
+
return c;
|
|
337
|
+
};
|
|
338
|
+
XPath.prototype.stackToString = function (stack) {
|
|
339
|
+
var ret = '';
|
|
340
|
+
for (var i = 0; i < stack.length; ++i) {
|
|
341
|
+
if (ret) {
|
|
342
|
+
ret += '\n';
|
|
343
|
+
}
|
|
344
|
+
ret += stack[i].tag.label;
|
|
345
|
+
}
|
|
346
|
+
return ret;
|
|
347
|
+
};
|
|
348
|
+
XPath.prototype.xPathCacheLookup = function (expr) {
|
|
349
|
+
return this.xPathParseCache[expr];
|
|
350
|
+
};
|
|
351
|
+
XPath.prototype.xPathCollectDescendants = function (nodeList, node, opt_tagName) {
|
|
352
|
+
if (opt_tagName && node.getElementsByTagName) {
|
|
353
|
+
(0, common_function_1.copyArray)(nodeList, node.getElementsByTagName(opt_tagName));
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
for (var n = node.firstChild; n; n = n.nextSibling) {
|
|
357
|
+
if (n.nodeType !== constants_1.DOM_ATTRIBUTE_NODE) {
|
|
358
|
+
nodeList.push(n);
|
|
359
|
+
}
|
|
360
|
+
this.xPathCollectDescendants(nodeList, n);
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
XPath.prototype.xPathCollectDescendantsReverse = function (nodeList, node) {
|
|
364
|
+
for (var n = node.lastChild; n; n = n.previousSibling) {
|
|
365
|
+
nodeList.push(n);
|
|
366
|
+
this.xPathCollectDescendantsReverse(nodeList, n);
|
|
367
|
+
}
|
|
368
|
+
};
|
|
369
|
+
/**
|
|
370
|
+
* Parses and then evaluates the given XPath expression in the given
|
|
371
|
+
* input context.
|
|
372
|
+
* @param select The xPath string.
|
|
373
|
+
* @param context The Expression Context.
|
|
374
|
+
* @returns A Node Value.
|
|
375
|
+
*/
|
|
376
|
+
XPath.prototype.xPathEval = function (select, context) {
|
|
377
|
+
var expression = this.xPathParse(select);
|
|
378
|
+
var response = expression.evaluate(context);
|
|
379
|
+
return response;
|
|
380
|
+
};
|
|
381
|
+
/**
|
|
382
|
+
* DGF - extract a tag name suitable for getElementsByTagName
|
|
383
|
+
*
|
|
384
|
+
* @param nodeTest the node test
|
|
385
|
+
* @param ignoreNonElementNodesForNTA if true, the node list returned when
|
|
386
|
+
* evaluating "node()" will not contain
|
|
387
|
+
* non-element nodes. This can boost
|
|
388
|
+
* performance. This is false by default.
|
|
389
|
+
*/
|
|
390
|
+
XPath.prototype.xPathExtractTagNameFromNodeTest = function (nodeTest, ignoreNonElementNodesForNTA) {
|
|
391
|
+
if (nodeTest instanceof node_tests_1.NodeTestName) {
|
|
392
|
+
return nodeTest.name;
|
|
393
|
+
}
|
|
394
|
+
if ((ignoreNonElementNodesForNTA && nodeTest instanceof node_tests_1.NodeTestAny) ||
|
|
395
|
+
nodeTest instanceof node_tests_1.NodeTestElementOrAttribute) {
|
|
396
|
+
return '*';
|
|
397
|
+
}
|
|
398
|
+
};
|
|
399
|
+
XPath.prototype.xPathMatchStack = function (stack, pattern) {
|
|
400
|
+
// NOTE(mesch): The stack matches for variable cardinality are
|
|
401
|
+
// greedy but don't do backtracking. This would be an issue only
|
|
402
|
+
// with rules of the form A* A, i.e. with an element with variable
|
|
403
|
+
// cardinality followed by the same element. Since that doesn't
|
|
404
|
+
// occur in the grammar at hand, all matches on the stack are
|
|
405
|
+
// unambiguous.
|
|
406
|
+
var stackLength = stack.length;
|
|
407
|
+
var patternLength = pattern.length;
|
|
408
|
+
var p;
|
|
409
|
+
var s;
|
|
410
|
+
var match = [];
|
|
411
|
+
match.matchLength = 0;
|
|
412
|
+
var ds = 0;
|
|
413
|
+
for (p = patternLength - 1, s = stackLength - 1; p >= 0 && s >= 0; --p, s -= ds) {
|
|
414
|
+
ds = 0;
|
|
415
|
+
var qmatch = [];
|
|
416
|
+
if (pattern[p] == tokens_1.Q_ZERO_OR_MULTIPLE) {
|
|
417
|
+
p -= 1;
|
|
418
|
+
match.push(qmatch);
|
|
419
|
+
while (s - ds >= 0 && stack[s - ds].tag == pattern[p]) {
|
|
420
|
+
qmatch.push(stack[s - ds]);
|
|
421
|
+
ds += 1;
|
|
422
|
+
match.matchLength += 1;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
else if (pattern[p] == tokens_1.Q_ZERO_OR_ONE) {
|
|
426
|
+
p -= 1;
|
|
427
|
+
match.push(qmatch);
|
|
428
|
+
while (s - ds >= 0 && ds < 2 && stack[s - ds].tag == pattern[p]) {
|
|
429
|
+
qmatch.push(stack[s - ds]);
|
|
430
|
+
ds += 1;
|
|
431
|
+
match.matchLength += 1;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
else if (pattern[p] == tokens_1.Q_ONE_OR_MULTIPLE) {
|
|
435
|
+
p -= 1;
|
|
436
|
+
match.push(qmatch);
|
|
437
|
+
if (stack[s].tag == pattern[p]) {
|
|
438
|
+
while (s - ds >= 0 && stack[s - ds].tag == pattern[p]) {
|
|
439
|
+
qmatch.push(stack[s - ds]);
|
|
440
|
+
ds += 1;
|
|
441
|
+
match.matchLength += 1;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
else {
|
|
445
|
+
return [];
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
else if (stack[s].tag == pattern[p]) {
|
|
449
|
+
match.push(stack[s]);
|
|
450
|
+
ds += 1;
|
|
451
|
+
match.matchLength += 1;
|
|
452
|
+
}
|
|
453
|
+
else {
|
|
454
|
+
return [];
|
|
455
|
+
}
|
|
456
|
+
(0, util_1.reverseInPlace)(qmatch);
|
|
457
|
+
qmatch.expr = (0, util_1.mapExpr)(qmatch, function (m) { return m.expr; });
|
|
458
|
+
}
|
|
459
|
+
(0, util_1.reverseInPlace)(match);
|
|
460
|
+
if (p === -1) {
|
|
461
|
+
return match;
|
|
462
|
+
}
|
|
463
|
+
return [];
|
|
464
|
+
};
|
|
465
|
+
/**
|
|
466
|
+
* Finds the best rule for the XPath expression provided.
|
|
467
|
+
* @param expression The XPath string expression.
|
|
468
|
+
* @param previous The previous matched XPath rule.
|
|
469
|
+
* @returns The found rule and the corresponding match.
|
|
470
|
+
*/
|
|
471
|
+
XPath.prototype.findXPathRuleForExpression = function (expression, previous) {
|
|
472
|
+
var rule = null;
|
|
473
|
+
var match = '';
|
|
474
|
+
for (var i = 0; i < tokens_1.xPathTokenRules.length; ++i) {
|
|
475
|
+
var result = tokens_1.xPathTokenRules[i].re.exec(expression);
|
|
476
|
+
this.lexerCount++;
|
|
477
|
+
if (result !== null && result.length > 0 && result[0].length > 0) {
|
|
478
|
+
rule = tokens_1.xPathTokenRules[i];
|
|
479
|
+
match = result[0];
|
|
480
|
+
break;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
// Special case: allow operator keywords to be element and
|
|
484
|
+
// variable names.
|
|
485
|
+
// NOTE(mesch): The parser resolves conflicts by looking ahead,
|
|
486
|
+
// and this is the only case where we look back to
|
|
487
|
+
// disambiguate. So this is indeed something different, and
|
|
488
|
+
// looking back is usually done in the lexer (via states in the
|
|
489
|
+
// general case, called "start conditions" in flex(1)). Also, the
|
|
490
|
+
// conflict resolution in the parser is not as robust as it could
|
|
491
|
+
// be, so I'd like to keep as much off the parser as possible (all
|
|
492
|
+
// these precedence values should be computed from the grammar
|
|
493
|
+
// rules and possibly associativity declarations, as in bison(1),
|
|
494
|
+
// and not explicitly set.
|
|
495
|
+
if (rule &&
|
|
496
|
+
(rule == tokens_1.TOK_DIV || rule == tokens_1.TOK_MOD || rule == tokens_1.TOK_AND || rule == tokens_1.TOK_OR) &&
|
|
497
|
+
(!previous ||
|
|
498
|
+
previous.tag == tokens_1.TOK_AT ||
|
|
499
|
+
previous.tag == tokens_1.TOK_DSLASH ||
|
|
500
|
+
previous.tag == tokens_1.TOK_SLASH ||
|
|
501
|
+
previous.tag == tokens_1.TOK_AXIS ||
|
|
502
|
+
previous.tag == tokens_1.TOK_DOLLAR)) {
|
|
503
|
+
rule = tokens_1.TOK_QNAME;
|
|
504
|
+
}
|
|
505
|
+
return { rule: rule, match: match };
|
|
506
|
+
};
|
|
507
|
+
/**
|
|
508
|
+
* Initialization for `xPathParse`.
|
|
509
|
+
* @see xPathParse
|
|
510
|
+
*/
|
|
511
|
+
XPath.prototype.xPathParseInit = function () {
|
|
512
|
+
if (this.xPathRules.length) {
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
var xPathNonTerminals = [
|
|
516
|
+
xpath_grammar_rules_1.XPathLocationPath,
|
|
517
|
+
xpath_grammar_rules_1.XPathRelativeLocationPath,
|
|
518
|
+
xpath_grammar_rules_1.XPathAbsoluteLocationPath,
|
|
519
|
+
xpath_grammar_rules_1.XPathStep,
|
|
520
|
+
xpath_grammar_rules_1.XPathNodeTest,
|
|
521
|
+
xpath_grammar_rules_1.XPathPredicate,
|
|
522
|
+
xpath_grammar_rules_1.XPathLiteral,
|
|
523
|
+
xpath_grammar_rules_1.XPathExpr,
|
|
524
|
+
xpath_grammar_rules_1.XPathPrimaryExpr,
|
|
525
|
+
xpath_grammar_rules_1.XPathVariableReference,
|
|
526
|
+
xpath_grammar_rules_1.XPathNumber,
|
|
527
|
+
xpath_grammar_rules_1.XPathFunctionCall,
|
|
528
|
+
xpath_grammar_rules_1.XPathArgumentRemainder,
|
|
529
|
+
xpath_grammar_rules_1.XPathPathExpr,
|
|
530
|
+
xpath_grammar_rules_1.XPathUnionExpr,
|
|
531
|
+
xpath_grammar_rules_1.XPathFilterExpr,
|
|
532
|
+
xpath_grammar_rules_1.XPathDigits
|
|
533
|
+
];
|
|
534
|
+
// Some simple optimizations for the xpath expression parser: sort
|
|
535
|
+
// grammar rules descending by length, so that the longest match is
|
|
536
|
+
// first found.
|
|
537
|
+
this.xPathGrammarRules.sort(function (a, b) {
|
|
538
|
+
var la = a[1].length;
|
|
539
|
+
var lb = b[1].length;
|
|
540
|
+
if (la < lb) {
|
|
541
|
+
return 1;
|
|
542
|
+
}
|
|
543
|
+
else if (la > lb) {
|
|
544
|
+
return -1;
|
|
545
|
+
}
|
|
546
|
+
return 0;
|
|
547
|
+
});
|
|
548
|
+
var k = 1;
|
|
549
|
+
for (var i = 0; i < xPathNonTerminals.length; ++i) {
|
|
550
|
+
xPathNonTerminals[i].key = k++;
|
|
551
|
+
}
|
|
552
|
+
for (var i = 0; i < tokens_1.xPathTokenRules.length; ++i) {
|
|
553
|
+
tokens_1.xPathTokenRules[i].key = k++;
|
|
554
|
+
}
|
|
555
|
+
this.xPathLog("XPath parse INIT: ".concat(k, " rules"));
|
|
556
|
+
// Another slight optimization: sort the rules into bins according
|
|
557
|
+
// to the last element (observing quantifiers), so we can restrict
|
|
558
|
+
// the match against the stack to the subest of rules that match the
|
|
559
|
+
// top of the stack.
|
|
560
|
+
//
|
|
561
|
+
// TODO(mesch): What we actually want is to compute states as in
|
|
562
|
+
// bison, so that we don't have to do any explicit and iterated
|
|
563
|
+
// match against the stack.
|
|
564
|
+
function push_(array, position, element) {
|
|
565
|
+
if (!array[position]) {
|
|
566
|
+
array[position] = [];
|
|
567
|
+
}
|
|
568
|
+
array[position].push(element);
|
|
569
|
+
}
|
|
570
|
+
for (var i = 0; i < this.xPathGrammarRules.length; ++i) {
|
|
571
|
+
var rule = this.xPathGrammarRules[i];
|
|
572
|
+
var pattern = rule[1];
|
|
573
|
+
for (var j = pattern.length - 1; j >= 0; --j) {
|
|
574
|
+
if (pattern[j] == tokens_1.Q_ONE_OR_MULTIPLE) {
|
|
575
|
+
push_(this.xPathRules, pattern[j - 1].key, rule);
|
|
576
|
+
break;
|
|
577
|
+
}
|
|
578
|
+
else if (pattern[j] == tokens_1.Q_ZERO_OR_MULTIPLE || pattern[j] == tokens_1.Q_ZERO_OR_ONE) {
|
|
579
|
+
push_(this.xPathRules, pattern[j - 1].key, rule);
|
|
580
|
+
--j;
|
|
581
|
+
}
|
|
582
|
+
else {
|
|
583
|
+
push_(this.xPathRules, pattern[j].key, rule);
|
|
584
|
+
break;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
this.xPathLog("XPath parse INIT: ".concat(this.xPathRules.length, " rule bins"));
|
|
589
|
+
var sum = 0;
|
|
590
|
+
(0, util_1.mapExec)(this.xPathRules, function (i) {
|
|
591
|
+
if (i) {
|
|
592
|
+
sum += i.length;
|
|
593
|
+
}
|
|
594
|
+
});
|
|
595
|
+
this.xPathLog("XPath parse INIT: ".concat(sum / this.xPathRules.length, " average bin size"));
|
|
596
|
+
};
|
|
597
|
+
/**
|
|
598
|
+
* The entry point for the parser.
|
|
599
|
+
* @param expression a string that contains an XPath expression.
|
|
600
|
+
* @param axis The XPath axis. Used when the match does not start with the parent.
|
|
601
|
+
* @returns an expression object that can be evaluated with an
|
|
602
|
+
* expression context.
|
|
603
|
+
*/
|
|
604
|
+
XPath.prototype.xPathParse = function (expression, axis) {
|
|
605
|
+
var originalExpression = "".concat(expression);
|
|
606
|
+
this.xPathLog("parse ".concat(expression));
|
|
607
|
+
this.xPathParseInit();
|
|
608
|
+
// TODO: Removing the cache for now.
|
|
609
|
+
// The cache became a real problem when having to deal with `self-and-siblings`
|
|
610
|
+
// axis.
|
|
611
|
+
/* const cached = this.xPathCacheLookup(expression);
|
|
612
|
+
if (cached && axis === undefined) {
|
|
613
|
+
this.xPathLog(' ... cached');
|
|
614
|
+
return cached;
|
|
615
|
+
} */
|
|
616
|
+
// Optimize for a few common cases: simple attribute node tests
|
|
617
|
+
// (@id), simple element node tests (page), variable references
|
|
618
|
+
// ($address), numbers (4), multi-step path expressions where each
|
|
619
|
+
// step is a plain element node test
|
|
620
|
+
// (page/overlay/locations/location).
|
|
621
|
+
if (expression.match(/^(\$|@)?\w+$/i)) {
|
|
622
|
+
var ret = this.makeSimpleExpr(expression, axis);
|
|
623
|
+
this.xPathParseCache[expression] = ret;
|
|
624
|
+
this.xPathLog(' ... simple');
|
|
625
|
+
return ret;
|
|
626
|
+
}
|
|
627
|
+
if (expression.match(/^\w+(\/\w+)*$/i)) {
|
|
628
|
+
var ret = this.makeSimpleExpr2(expression);
|
|
629
|
+
this.xPathParseCache[expression] = ret;
|
|
630
|
+
this.xPathLog(' ... simple 2');
|
|
631
|
+
return ret;
|
|
632
|
+
}
|
|
633
|
+
var cachekey = expression; // expression is modified during parse
|
|
634
|
+
var stack = [];
|
|
635
|
+
var ahead = null;
|
|
636
|
+
var previous = null;
|
|
637
|
+
var done = false;
|
|
638
|
+
var parseCount = 0;
|
|
639
|
+
this.lexerCount = 0;
|
|
640
|
+
var reduceCount = 0;
|
|
641
|
+
while (!done) {
|
|
642
|
+
parseCount++;
|
|
643
|
+
expression = expression.replace(/^\s*/, '');
|
|
644
|
+
previous = ahead;
|
|
645
|
+
ahead = null;
|
|
646
|
+
var _a = this.findXPathRuleForExpression(expression, previous), rule = _a.rule, match = _a.match;
|
|
647
|
+
if (rule) {
|
|
648
|
+
expression = expression.substr(match.length);
|
|
649
|
+
this.xPathLog("token: ".concat(match, " -- ").concat(rule.label));
|
|
650
|
+
ahead = {
|
|
651
|
+
tag: rule,
|
|
652
|
+
match: match,
|
|
653
|
+
prec: rule.prec ? rule.prec : 0, // || 0 is removed by the compiler
|
|
654
|
+
expr: this.makeTokenExpr(match)
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
else {
|
|
658
|
+
this.xPathLog('DONE');
|
|
659
|
+
done = true;
|
|
660
|
+
}
|
|
661
|
+
while (this.xPathReduce(stack, ahead)) {
|
|
662
|
+
reduceCount++;
|
|
663
|
+
this.xPathLog("stack: ".concat(this.stackToString(stack)));
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
this.xPathLog("stack: ".concat(this.stackToString(stack)));
|
|
667
|
+
// DGF any valid XPath should "reduce" to a single Expr token
|
|
668
|
+
if (stack.length !== 1) {
|
|
669
|
+
throw "XPath parse error ".concat(cachekey, ":\n").concat(this.stackToString(stack));
|
|
670
|
+
}
|
|
671
|
+
var result = stack[0].expr;
|
|
672
|
+
// TODO: Remove this `if` after getting to rewrite `xPathReduce`.
|
|
673
|
+
if (axis !== undefined &&
|
|
674
|
+
!result.absolute &&
|
|
675
|
+
!originalExpression.startsWith('*') &&
|
|
676
|
+
result.steps &&
|
|
677
|
+
Array.isArray(result.steps)) {
|
|
678
|
+
result.steps[0].axis = axis;
|
|
679
|
+
}
|
|
680
|
+
this.xPathParseCache[cachekey] = result;
|
|
681
|
+
this.xPathLog("XPath parse: ".concat(parseCount, " / ").concat(this.lexerCount, " / ").concat(reduceCount));
|
|
682
|
+
return result;
|
|
683
|
+
};
|
|
684
|
+
XPath.prototype.findGrammarRuleCandidate = function (ruleset, stack) {
|
|
685
|
+
for (var i = 0; i < ruleset.length; ++i) {
|
|
686
|
+
var rule = ruleset[i];
|
|
687
|
+
var match = this.xPathMatchStack(stack, rule[1]);
|
|
688
|
+
if (match.length) {
|
|
689
|
+
var candidate = {
|
|
690
|
+
tag: rule[0],
|
|
691
|
+
rule: rule,
|
|
692
|
+
match: match,
|
|
693
|
+
prec: undefined
|
|
694
|
+
};
|
|
695
|
+
candidate.prec = this.xPathGrammarPrecedence(candidate);
|
|
696
|
+
return candidate;
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
return null;
|
|
700
|
+
};
|
|
701
|
+
/**
|
|
702
|
+
* DGF xPathReduce is where the magic happens in this parser.
|
|
703
|
+
* Check `src\xpath\xpath-grammar-rules.ts` to find the table of
|
|
704
|
+
* grammatical rules and precedence numbers, "The productions of the grammar".
|
|
705
|
+
*
|
|
706
|
+
* The idea here is that we want to take a stack of tokens and apply
|
|
707
|
+
* grammatical rules to them, "reducing" them to higher-level
|
|
708
|
+
* tokens. Ultimately, any valid XPath should reduce to exactly one
|
|
709
|
+
* "Expr" token.
|
|
710
|
+
*
|
|
711
|
+
* Reduce too early or too late, and you'll have two tokens that can't reduce
|
|
712
|
+
* to single Expr. For example, you may hastily reduce a qname that
|
|
713
|
+
* should name a function, incorrectly treating it as a tag name.
|
|
714
|
+
* Or you may reduce too late, accidentally reducing the last part of the
|
|
715
|
+
* XPath into a top-level "Expr" that won't reduce with earlier parts of
|
|
716
|
+
* the XPath.
|
|
717
|
+
*
|
|
718
|
+
* A "candidate" is a grammatical rule candidate, with a given precedence
|
|
719
|
+
* number. "ahead" is the upcoming token, which also has a precedence
|
|
720
|
+
* number. If the token has a higher precedence number than
|
|
721
|
+
* the rule candidate, we'll "shift" the token onto the token stack,
|
|
722
|
+
* instead of immediately applying the rule candidate.
|
|
723
|
+
*
|
|
724
|
+
* Some tokens have left associativity, in which case we shift when they
|
|
725
|
+
* have LOWER precedence than the candidate.
|
|
726
|
+
* @param stack The actual grammar rule stack.
|
|
727
|
+
* @param ahead The grammar rule ahead.
|
|
728
|
+
* @return `true` if a grammar rule candidate was applied. `false` otherwise.
|
|
729
|
+
* @private
|
|
730
|
+
*/
|
|
731
|
+
XPath.prototype.xPathReduce = function (stack, ahead) {
|
|
732
|
+
var candidate = null;
|
|
733
|
+
if (stack.length > 0) {
|
|
734
|
+
var top_1 = stack[stack.length - 1];
|
|
735
|
+
var ruleset = this.xPathRules[top_1.tag.key];
|
|
736
|
+
if (ruleset) {
|
|
737
|
+
candidate = this.findGrammarRuleCandidate(ruleset, stack);
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
if (candidate && (!ahead || candidate.prec > ahead.prec || (ahead.tag.left && candidate.prec >= ahead.prec))) {
|
|
741
|
+
for (var i = 0; i < candidate.match.matchLength; ++i) {
|
|
742
|
+
stack.pop();
|
|
743
|
+
}
|
|
744
|
+
this.xPathLog("reduce ".concat(candidate.tag.label, " ").concat(candidate.prec, " ahead ").concat(ahead ? ahead.tag.label + ' ' + ahead.prec + (ahead.tag.left ? ' left' : '') : ' none '));
|
|
745
|
+
var matchExpression = (0, util_1.mapExpr)(candidate.match, function (m) { return m.expr; });
|
|
746
|
+
this.xPathLog("going to apply ".concat(candidate.rule[3]));
|
|
747
|
+
candidate.expr = candidate.rule[3].apply(this, matchExpression);
|
|
748
|
+
stack.push(candidate);
|
|
749
|
+
return true;
|
|
750
|
+
}
|
|
751
|
+
else {
|
|
752
|
+
if (ahead) {
|
|
753
|
+
this.xPathLog("shift ".concat(ahead.tag.label, " ").concat(ahead.prec).concat(ahead.tag.left ? ' left' : '', " over ").concat(candidate ? candidate.tag.label + ' ' + candidate.prec : ' none'));
|
|
754
|
+
stack.push(ahead);
|
|
755
|
+
}
|
|
756
|
+
return false;
|
|
757
|
+
}
|
|
758
|
+
};
|
|
759
|
+
/**
|
|
760
|
+
* Utility function to sort a list of nodes. Used by xsltSort().
|
|
761
|
+
* @param context The Expression Context.
|
|
762
|
+
* @param sort TODO
|
|
763
|
+
*/
|
|
764
|
+
XPath.prototype.xPathSort = function (context, sort) {
|
|
765
|
+
if (sort.length === 0) {
|
|
766
|
+
return;
|
|
767
|
+
}
|
|
768
|
+
var sortList = [];
|
|
769
|
+
for (var i = 0; i < context.contextSize(); ++i) {
|
|
770
|
+
var node = context.nodeList[i];
|
|
771
|
+
var sortItem = {
|
|
772
|
+
node: node,
|
|
773
|
+
key: []
|
|
774
|
+
};
|
|
775
|
+
var clonedContext = context.clone([node], undefined, 0, undefined);
|
|
776
|
+
for (var _i = 0, sort_1 = sort; _i < sort_1.length; _i++) {
|
|
777
|
+
var s = sort_1[_i];
|
|
778
|
+
var value = s.expr.evaluate(clonedContext);
|
|
779
|
+
var evalue = void 0;
|
|
780
|
+
if (s.type === 'text') {
|
|
781
|
+
evalue = value.stringValue();
|
|
782
|
+
}
|
|
783
|
+
else if (s.type === 'number') {
|
|
784
|
+
evalue = value.numberValue();
|
|
785
|
+
}
|
|
786
|
+
sortItem.key.push({
|
|
787
|
+
value: evalue,
|
|
788
|
+
order: s.order
|
|
789
|
+
});
|
|
790
|
+
}
|
|
791
|
+
// Make the sort stable by adding a lowest priority sort by
|
|
792
|
+
// id. This is very convenient and furthermore required by the
|
|
793
|
+
// spec ([XSLT] - Section 10 Sorting).
|
|
794
|
+
sortItem.key.push({
|
|
795
|
+
value: i,
|
|
796
|
+
order: 'ascending'
|
|
797
|
+
});
|
|
798
|
+
sortList.push(sortItem);
|
|
799
|
+
}
|
|
800
|
+
sortList.sort(this.xPathSortByKey);
|
|
801
|
+
var nodes = [];
|
|
802
|
+
for (var i = 0; i < sortList.length; ++i) {
|
|
803
|
+
var node = sortList[i].node;
|
|
804
|
+
node.siblingPosition = i;
|
|
805
|
+
nodes.push(node);
|
|
806
|
+
}
|
|
807
|
+
context.nodeList = nodes;
|
|
808
|
+
context.setNode(0);
|
|
809
|
+
};
|
|
810
|
+
// Sorts by all order criteria defined. According to the JavaScript
|
|
811
|
+
// spec ([ECMA] Section 11.8.5), the compare operators compare strings
|
|
812
|
+
// as strings and numbers as numbers.
|
|
813
|
+
//
|
|
814
|
+
// NOTE: In browsers which do not follow the spec, this breaks only in
|
|
815
|
+
// the case that numbers should be sorted as strings, which is very
|
|
816
|
+
// uncommon.
|
|
817
|
+
XPath.prototype.xPathSortByKey = function (v1, v2) {
|
|
818
|
+
// NOTE: Sort key vectors of different length never occur in
|
|
819
|
+
// xsltSort.
|
|
820
|
+
for (var i = 0; i < v1.key.length; ++i) {
|
|
821
|
+
var o = v1.key[i].order == 'descending' ? -1 : 1;
|
|
822
|
+
if (v1.key[i].value > v2.key[i].value) {
|
|
823
|
+
return +1 * o;
|
|
824
|
+
}
|
|
825
|
+
if (v1.key[i].value < v2.key[i].value) {
|
|
826
|
+
return -1 * o;
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
return 0;
|
|
830
|
+
};
|
|
831
|
+
XPath.prototype.xPathStep = function (nodes, steps, step, input, context) {
|
|
832
|
+
var s = steps[step];
|
|
833
|
+
var ctx2 = context.clone([input], undefined, 0, undefined);
|
|
834
|
+
if (context.returnOnFirstMatch && !s.hasPositionalPredicate) {
|
|
835
|
+
var nodeList = s.evaluate(ctx2).nodeSetValue();
|
|
836
|
+
// the predicates were not processed in the last evaluate(), so that we can
|
|
837
|
+
// process them here with the returnOnFirstMatch optimization. We do a
|
|
838
|
+
// depth-first grab at any nodes that pass the predicate tests. There is no
|
|
839
|
+
// way to optimize when predicates contain positional selectors, including
|
|
840
|
+
// indexes or uses of the last() or position() functions, because they
|
|
841
|
+
// typically require the entire nodeList for context. Process without
|
|
842
|
+
// optimization if we encounter such selectors.
|
|
843
|
+
var nLength = nodeList.length;
|
|
844
|
+
var pLength = s.predicate.length;
|
|
845
|
+
nodeListLoop: for (var i = 0; i < nLength; ++i) {
|
|
846
|
+
for (var j = 0; j < pLength; ++j) {
|
|
847
|
+
if (!s.predicate[j].evaluate(context.clone(nodeList, undefined, i, undefined)).booleanValue()) {
|
|
848
|
+
continue nodeListLoop;
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
// n survived the predicate tests!
|
|
852
|
+
if (step == steps.length - 1) {
|
|
853
|
+
nodes.push(nodeList[i]);
|
|
854
|
+
}
|
|
855
|
+
else {
|
|
856
|
+
this.xPathStep(nodes, steps, step + 1, nodeList[i], context);
|
|
857
|
+
}
|
|
858
|
+
if (nodes.length > 0) {
|
|
859
|
+
break;
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
else {
|
|
864
|
+
// set returnOnFirstMatch to false for the cloned ExprContext, because
|
|
865
|
+
// behavior in StepExpr.prototype.evaluate is driven off its value. Note
|
|
866
|
+
// that the original context may still have true for this value.
|
|
867
|
+
ctx2.returnOnFirstMatch = false;
|
|
868
|
+
var nodeList = s.evaluate(ctx2).nodeSetValue();
|
|
869
|
+
for (var i = 0; i < nodeList.length; ++i) {
|
|
870
|
+
if (step == steps.length - 1) {
|
|
871
|
+
nodes.push(nodeList[i]);
|
|
872
|
+
}
|
|
873
|
+
else {
|
|
874
|
+
this.xPathStep(nodes, steps, step + 1, nodeList[i], context);
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
};
|
|
879
|
+
XPath.prototype.xPathGrammarPrecedence = function (frame) {
|
|
880
|
+
var ret = 0;
|
|
881
|
+
if (frame.rule) {
|
|
882
|
+
/* normal reduce */
|
|
883
|
+
if (frame.rule.length >= 3 && frame.rule[2] >= 0) {
|
|
884
|
+
ret = frame.rule[2];
|
|
885
|
+
}
|
|
886
|
+
else {
|
|
887
|
+
for (var i = 0; i < frame.rule[1].length; ++i) {
|
|
888
|
+
var p = this.xPathTokenPrecedence(frame.rule[1][i]);
|
|
889
|
+
ret = Math.max(ret, p);
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
else if (frame.tag) {
|
|
894
|
+
/* TOKEN match */
|
|
895
|
+
ret = this.xPathTokenPrecedence(frame.tag);
|
|
896
|
+
}
|
|
897
|
+
else if (frame.length) {
|
|
898
|
+
/* Q_ match */
|
|
899
|
+
for (var j = 0; j < frame.length; ++j) {
|
|
900
|
+
var p = this.xPathGrammarPrecedence(frame[j]);
|
|
901
|
+
ret = Math.max(ret, p);
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
return ret;
|
|
905
|
+
};
|
|
906
|
+
XPath.prototype.xPathTokenPrecedence = function (tag) {
|
|
907
|
+
return tag.prec || 2;
|
|
908
|
+
};
|
|
909
|
+
return XPath;
|
|
910
|
+
}());
|
|
911
|
+
exports.XPath = XPath;
|
|
910
912
|
//# sourceMappingURL=xpath.js.map
|