4 * An XPath 1.0 library for JavaScript.
6 * Cameron McCormack <cam (at) mcc.id.au>
8 * This work is licensed under the Creative Commons Attribution-ShareAlike
9 * License. To view a copy of this license, visit
11 * http://creativecommons.org/licenses/by-sa/2.0/
13 * or send a letter to Creative Commons, 559 Nathan Abbott Way, Stanford,
14 * California 94305, USA.
17 * Patch m1: January 13, 2006
18 * Forcing namespace resolution for default namespaces. In the current
19 * code the default namespace (no prefix) is the same as no namespace,
20 * but AFAICT this is incorrect. If a node has a namespaceURI then it
21 * should be used, and the expression should use the NamespaceResolver
22 * to match the node's namespaceURI.
24 * On a more positive note, I am using this library to test the correctness
25 * of my pure-JS DOM implementation for use in libjs environments. You can
26 * currently find that at
27 * http://open-ils.org/cgi-bin/viewcvs.cgi/ILS/Open-ILS/src/javascript/backend/libs/jsDOM.js
29 * Revision 19: November 29, 2005
30 * Nodesets now store their nodes in a height balanced tree, increasing
31 * performance for the common case of selecting nodes in document order,
32 * thanks to Sébastien Cramatte <contact (at) zeninteractif.com>.
33 * AVL tree code adapted from Raimund Neumann <rnova (at) gmx.net>.
35 * Revision 18: October 27, 2005
36 * DOM 3 XPath support. Caveats:
37 * - namespace prefixes aren't resolved in XPathEvaluator.createExpression,
38 * but in XPathExpression.evaluate.
39 * - XPathResult.invalidIteratorState is not implemented.
41 * Revision 17: October 25, 2005
42 * Some core XPath function fixes and a patch to avoid crashing certain
43 * versions of MSXML in PathExpr.prototype.getOwnerElement, thanks to
44 * Sébastien Cramatte <contact (at) zeninteractif.com>.
46 * Revision 16: September 22, 2005
47 * Workarounds for some IE 5.5 deficiencies.
48 * Fixed problem with prefix node tests on attribute nodes.
50 * Revision 15: May 21, 2005
51 * Fixed problem with QName node tests on elements with an xmlns="...".
53 * Revision 14: May 19, 2005
54 * Fixed QName node tests on attribute node regression.
56 * Revision 13: May 3, 2005
57 * Node tests are case insensitive now if working in an HTML DOM.
59 * Revision 12: April 26, 2005
60 * Updated licence. Slight code changes to enable use of Dean
61 * Edwards' script compression, http://dean.edwards.name/packer/ .
63 * Revision 11: April 23, 2005
64 * Fixed bug with 'and' and 'or' operators, fix thanks to
65 * Sandy McArthur <sandy (at) mcarthur.org>.
67 * Revision 10: April 15, 2005
68 * Added support for a virtual root node, supposedly helpful for
69 * implementing XForms. Fixed problem with QName node tests and
72 * Revision 9: March 17, 2005
73 * Namespace resolver tweaked so using the document node as the context
74 * for namespace lookups is equivalent to using the document element.
76 * Revision 8: February 13, 2005
77 * Handle implicit declaration of 'xmlns' namespace prefix.
78 * Fixed bug when comparing nodesets.
79 * Instance data can now be associated with a FunctionResolver, and
80 * workaround for MSXML not supporting 'localName' and 'getElementById',
81 * thanks to Grant Gongaware.
82 * Fix a few problems when the context node is the root node.
84 * Revision 7: February 11, 2005
85 * Default namespace resolver fix from Grant Gongaware
86 * <grant (at) gongaware.com>.
88 * Revision 6: February 10, 2005
89 * Fixed bug in 'number' function.
91 * Revision 5: February 9, 2005
92 * Fixed bug where text nodes not getting converted to string values.
94 * Revision 4: January 21, 2005
95 * Bug in 'name' function, fix thanks to Bill Edney.
96 * Fixed incorrect processing of namespace nodes.
97 * Fixed NamespaceResolver to resolve 'xml' namespace.
98 * Implemented union '|' operator.
100 * Revision 3: January 14, 2005
101 * Fixed bug with nodeset comparisons, bug lexing < and >.
103 * Revision 2: October 26, 2004
104 * QName node test namespace handling fixed. Few other bug fixes.
106 * Revision 1: August 13, 2004
107 * Bug fixes from William J. Edney <bedney (at) technicalpursuit.com>.
108 * Added minimal licence.
110 * Initial version: June 14, 2004
113 // XPathParser ///////////////////////////////////////////////////////////////
115 XPathParser.prototype = new Object();
116 XPathParser.prototype.constructor = XPathParser;
117 XPathParser.superclass = Object.prototype;
119 function XPathParser() {
123 XPathParser.prototype.init = function() {
124 this.reduceActions = [];
126 this.reduceActions[3] = function(rhs) {
127 return new OrOperation(rhs[0], rhs[2]);
129 this.reduceActions[5] = function(rhs) {
130 return new AndOperation(rhs[0], rhs[2]);
132 this.reduceActions[7] = function(rhs) {
133 return new EqualsOperation(rhs[0], rhs[2]);
135 this.reduceActions[8] = function(rhs) {
136 return new NotEqualOperation(rhs[0], rhs[2]);
138 this.reduceActions[10] = function(rhs) {
139 return new LessThanOperation(rhs[0], rhs[2]);
141 this.reduceActions[11] = function(rhs) {
142 return new GreaterThanOperation(rhs[0], rhs[2]);
144 this.reduceActions[12] = function(rhs) {
145 return new LessThanOrEqualOperation(rhs[0], rhs[2]);
147 this.reduceActions[13] = function(rhs) {
148 return new GreaterThanOrEqualOperation(rhs[0], rhs[2]);
150 this.reduceActions[15] = function(rhs) {
151 return new PlusOperation(rhs[0], rhs[2]);
153 this.reduceActions[16] = function(rhs) {
154 return new MinusOperation(rhs[0], rhs[2]);
156 this.reduceActions[18] = function(rhs) {
157 return new MultiplyOperation(rhs[0], rhs[2]);
159 this.reduceActions[19] = function(rhs) {
160 return new DivOperation(rhs[0], rhs[2]);
162 this.reduceActions[20] = function(rhs) {
163 return new ModOperation(rhs[0], rhs[2]);
165 this.reduceActions[22] = function(rhs) {
166 return new UnaryMinusOperation(rhs[1]);
168 this.reduceActions[24] = function(rhs) {
169 return new BarOperation(rhs[0], rhs[2]);
171 this.reduceActions[25] = function(rhs) {
172 return new PathExpr(undefined, undefined, rhs[0]);
174 this.reduceActions[27] = function(rhs) {
175 rhs[0].locationPath = rhs[2];
178 this.reduceActions[28] = function(rhs) {
179 rhs[0].locationPath = rhs[2];
180 rhs[0].locationPath.steps.unshift(new Step(Step.DESCENDANTORSELF, new NodeTest(NodeTest.NODE, undefined), []));
183 this.reduceActions[29] = function(rhs) {
184 return new PathExpr(rhs[0], [], undefined);
186 this.reduceActions[30] = function(rhs) {
187 if (Utilities.instance_of(rhs[0], PathExpr)) {
188 if (rhs[0].filterPredicates == undefined) {
189 rhs[0].filterPredicates = [];
191 rhs[0].filterPredicates.push(rhs[1]);
194 return new PathExpr(rhs[0], [rhs[1]], undefined);
197 this.reduceActions[32] = function(rhs) {
200 this.reduceActions[33] = function(rhs) {
201 return new XString(rhs[0]);
203 this.reduceActions[34] = function(rhs) {
204 return new XNumber(rhs[0]);
206 this.reduceActions[36] = function(rhs) {
207 return new FunctionCall(rhs[0], []);
209 this.reduceActions[37] = function(rhs) {
210 return new FunctionCall(rhs[0], rhs[2]);
212 this.reduceActions[38] = function(rhs) {
215 this.reduceActions[39] = function(rhs) {
216 rhs[2].unshift(rhs[0]);
219 this.reduceActions[43] = function(rhs) {
220 return new LocationPath(true, []);
222 this.reduceActions[44] = function(rhs) {
223 rhs[1].absolute = true;
226 this.reduceActions[46] = function(rhs) {
227 return new LocationPath(false, [ rhs[0] ]);
229 this.reduceActions[47] = function(rhs) {
230 rhs[0].steps.push(rhs[2]);
233 this.reduceActions[49] = function(rhs) {
234 return new Step(rhs[0], rhs[1], []);
236 this.reduceActions[50] = function(rhs) {
237 return new Step(Step.CHILD, rhs[0], []);
239 this.reduceActions[51] = function(rhs) {
240 return new Step(rhs[0], rhs[1], rhs[2]);
242 this.reduceActions[52] = function(rhs) {
243 return new Step(Step.CHILD, rhs[0], rhs[1]);
245 this.reduceActions[54] = function(rhs) {
248 this.reduceActions[55] = function(rhs) {
249 rhs[1].unshift(rhs[0]);
252 this.reduceActions[56] = function(rhs) {
253 if (rhs[0] == "ancestor") {
254 return Step.ANCESTOR;
255 } else if (rhs[0] == "ancestor-or-self") {
256 return Step.ANCESTORORSELF;
257 } else if (rhs[0] == "attribute") {
258 return Step.ATTRIBUTE;
259 } else if (rhs[0] == "child") {
261 } else if (rhs[0] == "descendant") {
262 return Step.DESCENDANT;
263 } else if (rhs[0] == "descendant-or-self") {
264 return Step.DESCENDANTORSELF;
265 } else if (rhs[0] == "following") {
266 return Step.FOLLOWING;
267 } else if (rhs[0] == "following-sibling") {
268 return Step.FOLLOWINGSIBLING;
269 } else if (rhs[0] == "namespace") {
270 return Step.NAMESPACE;
271 } else if (rhs[0] == "parent") {
273 } else if (rhs[0] == "preceding") {
274 return Step.PRECEDING;
275 } else if (rhs[0] == "preceding-sibling") {
276 return Step.PRECEDINGSIBLING;
277 } else if (rhs[0] == "self") {
282 this.reduceActions[57] = function(rhs) {
283 return Step.ATTRIBUTE;
285 this.reduceActions[59] = function(rhs) {
286 if (rhs[0] == "comment") {
287 return new NodeTest(NodeTest.COMMENT, undefined);
288 } else if (rhs[0] == "text") {
289 return new NodeTest(NodeTest.TEXT, undefined);
290 } else if (rhs[0] == "processing-instruction") {
291 return new NodeTest(NodeTest.PI, undefined);
292 } else if (rhs[0] == "node") {
293 return new NodeTest(NodeTest.NODE, undefined);
295 return new NodeTest(-1, undefined);
297 this.reduceActions[60] = function(rhs) {
298 return new NodeTest(NodeTest.PI, rhs[2]);
300 this.reduceActions[61] = function(rhs) {
303 this.reduceActions[63] = function(rhs) {
304 rhs[1].absolute = true;
305 rhs[1].steps.unshift(new Step(Step.DESCENDANTORSELF, new NodeTest(NodeTest.NODE, undefined), []));
308 this.reduceActions[64] = function(rhs) {
309 rhs[0].steps.push(new Step(Step.DESCENDANTORSELF, new NodeTest(NodeTest.NODE, undefined), []));
310 rhs[0].steps.push(rhs[2]);
313 this.reduceActions[65] = function(rhs) {
314 return new Step(Step.SELF, new NodeTest(NodeTest.NODE, undefined), []);
316 this.reduceActions[66] = function(rhs) {
317 return new Step(Step.PARENT, new NodeTest(NodeTest.NODE, undefined), []);
319 this.reduceActions[67] = function(rhs) {
320 return new VariableReference(rhs[1]);
322 this.reduceActions[68] = function(rhs) {
323 return new NodeTest(NodeTest.NAMETESTANY, undefined);
325 this.reduceActions[69] = function(rhs) {
326 var prefix = rhs[0].substring(0, rhs[0].indexOf(":"));
327 return new NodeTest(NodeTest.NAMETESTPREFIXANY, prefix);
329 this.reduceActions[70] = function(rhs) {
330 return new NodeTest(NodeTest.NAMETESTQNAME, rhs[0]);
334 XPathParser.actionTable = [
335 " s s sssssssss s ss s ss",
337 "r rrrrrrrrr rrrrrrr rr r ",
339 " s s sssssssss s ss s ss",
340 "rs rrrrrrrr s sssssrrrrrr rrs rs ",
341 " s s sssssssss s ss s ss",
344 "r rrrrrrrrr rrrrrrr rr rr ",
345 "r rrrrrrrrr rrrrrrr rr rr ",
346 "r rrrrrrrrr rrrrrrr rr rr ",
347 "r rrrrrrrrr rrrrrrr rr rr ",
348 "r rrrrrrrrr rrrrrrr rr rr ",
352 "r rrrrrrrrr rrrrrrr rr r ",
358 "r rrrrr rrrss rr r ",
359 "r rrrrrsss rrrrr rr r ",
360 "r rrrrrrrr rrrrr rr r ",
361 "r rrrrrrrr rrrrrs rr r ",
362 "r rrrrrrrr rrrrrr rr r ",
363 "r rrrrrrrr rrrrrr rr r ",
364 "r srrrrrrrr rrrrrrs rr sr ",
365 "r srrrrrrrr rrrrrrs rr r ",
366 "r rrrrrrrrr rrrrrrr rr rr ",
367 "r rrrrrrrrr rrrrrrr rr rr ",
368 "r rrrrrrrrr rrrrrrr rr rr ",
369 "r rrrrrrrr rrrrrr rr r ",
370 "r rrrrrrrr rrrrrr rr r ",
371 "r rrrrrrrrr rrrrrrr rr r ",
372 "r rrrrrrrrr rrrrrrr rr r ",
374 "r rrrrrrrrr rrrrrrr rr sr ",
375 "r rrrrrrrrr rrrrrrr rr r ",
376 "r rrrrrrrrr rrrrrrr rr rr ",
377 "r rrrrrrrrr rrrrrrr rr rr ",
379 "r srrrrrrrr rrrrrrs rr r ",
380 "r rrrrrrrr rrrrr rr r ",
384 " s s sssssssss s sss s ss",
385 "r srrrrrrrr rrrrrrs rr r ",
386 " s s sssssssss s ss s ss",
387 " s s sssssssss s ss s ss",
388 " s s sssssssss s ss s ss",
389 " s s sssssssss s ss s ss",
390 " s s sssssssss s ss s ss",
391 " s s sssssssss s ss s ss",
392 " s s sssssssss s ss s ss",
393 " s s sssssssss s ss s ss",
394 " s s sssssssss s ss s ss",
395 " s s sssssssss s ss s ss",
396 " s s sssssssss s ss s ss",
397 " s s sssssssss s ss s ss",
398 " s s sssssssss s ss s ss",
399 " s s sssssssss ss s ss",
400 " s s sssssssss s ss s ss",
403 "r rrrrrrrrr rrrrrrr rr rr ",
406 "r rrrrrrrrr rrrrrrr rr sr ",
407 "r rrrrrrrrr rrrrrrr rr sr ",
408 "r rrrrrrrrr rrrrrrr rr r ",
409 "r rrrrrrrrr rrrrrrr rr rr ",
411 "r rrrrrrrrr rrrrrrr rr rr ",
412 "r rrrrrrrrr rrrrrrr rr rr ",
420 "r rrrrr rrrss rr r ",
421 "r rrrrr rrrss rr r ",
422 "r rrrrr rrrss rr r ",
423 "r rrrrr rrrss rr r ",
424 "r rrrrrsss rrrrr rr r ",
425 "r rrrrrsss rrrrr rr r ",
426 "r rrrrrrrr rrrrr rr r ",
427 "r rrrrrrrr rrrrr rr r ",
428 "r rrrrrrrr rrrrr rr r ",
429 "r rrrrrrrr rrrrrr rr r ",
432 "r srrrrrrrr rrrrrrs rr r ",
433 "r srrrrrrrr rrrrrrs rr r ",
434 "r rrrrrrrrr rrrrrrr rr r ",
435 "r rrrrrrrrr rrrrrrr rr r ",
436 "r rrrrrrrrr rrrrrrr rr r ",
437 "r rrrrrrrrr rrrrrrr rr r ",
438 "r rrrrrrrrr rrrrrrr rr rr ",
439 "r rrrrrrrrr rrrrrrr rr rr ",
440 " s s sssssssss s ss s ss",
441 "r rrrrrrrrr rrrrrrr rr rr ",
445 XPathParser.actionTableNumber = [
446 " 1 0 /.-,+*)(' & %$ # \"!",
448 "a aaaaaaaaa aaaaaaa aa a ",
450 " 1 0 /.-,+*)(' & %$ # \"!",
451 "K1 KKKKKKKK . +*)('KKKKKK KK# K\" ",
452 " 1 0 /.-,+*)(' & %$ # \"!",
455 "e eeeeeeeee eeeeeee ee ee ",
456 "f fffffffff fffffff ff ff ",
457 "d ddddddddd ddddddd dd dd ",
458 "B BBBBBBBBB BBBBBBB BB BB ",
459 "A AAAAAAAAA AAAAAAA AA AA ",
463 "b bbbbbbbbb bbbbbbb bb b ",
469 ") ))))) )))\\[ )) ) ",
470 ". ....._^] ..... .. . ",
471 "1 11111111 11111 11 1 ",
472 "5 55555555 55555` 55 5 ",
473 "7 77777777 777777 77 7 ",
474 "9 99999999 999999 99 9 ",
475 ": c:::::::: ::::::b :: a: ",
476 "I fIIIIIIII IIIIIIe II I ",
477 "= ========= ======= == == ",
478 "? ????????? ??????? ?? ?? ",
479 "C CCCCCCCCC CCCCCCC CC CC ",
480 "J JJJJJJJJ JJJJJJ JJ J ",
481 "M MMMMMMMM MMMMMM MM M ",
482 "N NNNNNNNNN NNNNNNN NN N ",
483 "P PPPPPPPPP PPPPPPP PP P ",
485 "R RRRRRRRRR RRRRRRR RR aR ",
486 "U UUUUUUUUU UUUUUUU UU U ",
487 "Z ZZZZZZZZZ ZZZZZZZ ZZ ZZ ",
488 "c ccccccccc ccccccc cc cc ",
490 "L fLLLLLLLL LLLLLLe LL L ",
491 "6 66666666 66666 66 6 ",
495 " 1 0 /.-,+*)(' & %$m # \"!",
496 "_ f________ ______e __ _ ",
497 " 1 0 /.-,+*)(' & %$ # \"!",
498 " 1 0 /.-,+*)(' & %$ # \"!",
499 " 1 0 /.-,+*)(' & %$ # \"!",
500 " 1 0 /.-,+*)(' & %$ # \"!",
501 " 1 0 /.-,+*)(' & %$ # \"!",
502 " 1 0 /.-,+*)(' & %$ # \"!",
503 " 1 0 /.-,+*)(' & %$ # \"!",
504 " 1 0 /.-,+*)(' & %$ # \"!",
505 " 1 0 /.-,+*)(' & %$ # \"!",
506 " 1 0 /.-,+*)(' & %$ # \"!",
507 " 1 0 /.-,+*)(' & %$ # \"!",
508 " 1 0 /.-,+*)(' & %$ # \"!",
509 " 1 0 /.-,+*)(' & %$ # \"!",
510 " 1 0 /.-,+*)(' %$ # \"!",
511 " 1 0 /.-,+*)(' & %$ # \"!",
514 "> >>>>>>>>> >>>>>>> >> >> ",
517 "Q QQQQQQQQQ QQQQQQQ QQ aQ ",
518 "V VVVVVVVVV VVVVVVV VV aV ",
519 "T TTTTTTTTT TTTTTTT TT T ",
520 "@ @@@@@@@@@ @@@@@@@ @@ @@ ",
522 "[ [[[[[[[[[ [[[[[[[ [[ [[ ",
523 "D DDDDDDDDD DDDDDDD DD DD ",
531 "+ +++++ +++\\[ ++ + ",
532 "* ***** ***\\[ ** * ",
533 "- ----- ---\\[ -- - ",
534 ", ,,,,, ,,,\\[ ,, , ",
535 "0 00000_^] 00000 00 0 ",
536 "/ /////_^] ///// // / ",
537 "2 22222222 22222 22 2 ",
538 "3 33333333 33333 33 3 ",
539 "4 44444444 44444 44 4 ",
540 "8 88888888 888888 88 8 ",
543 "; f;;;;;;;; ;;;;;;e ;; ; ",
544 "< f<<<<<<<< <<<<<<e << < ",
545 "O OOOOOOOOO OOOOOOO OO O ",
546 "` ````````` ``````` `` ` ",
547 "S SSSSSSSSS SSSSSSS SS S ",
548 "W WWWWWWWWW WWWWWWW WW W ",
549 "\\ \\\\\\\\\\\\\\\\\\ \\\\\\\\\\\\\\ \\\\ \\\\ ",
550 "E EEEEEEEEE EEEEEEE EE EE ",
551 " 1 0 /.-,+*)(' & %$ # \"!",
552 "] ]]]]]]]]] ]]]]]]] ]] ]] ",
556 XPathParser.gotoTable = [
557 "3456789:;<=>?@ AB CDEFGH IJ ",
561 "L456789:;<=>?@ AB CDEFGH IJ ",
563 " N;<=>?@ AB CDEFGH IJ ",
606 "o456789:;<=>?@ ABpqCDEFGH IJ ",
608 " r6789:;<=>?@ AB CDEFGH IJ ",
609 " s789:;<=>?@ AB CDEFGH IJ ",
610 " t89:;<=>?@ AB CDEFGH IJ ",
611 " u89:;<=>?@ AB CDEFGH IJ ",
612 " v9:;<=>?@ AB CDEFGH IJ ",
613 " w9:;<=>?@ AB CDEFGH IJ ",
614 " x9:;<=>?@ AB CDEFGH IJ ",
615 " y9:;<=>?@ AB CDEFGH IJ ",
616 " z:;<=>?@ AB CDEFGH IJ ",
617 " {:;<=>?@ AB CDEFGH IJ ",
618 " |;<=>?@ AB CDEFGH IJ ",
619 " };<=>?@ AB CDEFGH IJ ",
620 " ~;<=>?@ AB CDEFGH IJ ",
621 " \x7f=>?@ AB CDEFGH IJ ",
622 "\x80456789:;<=>?@ AB CDEFGH IJ\x81",
662 "o456789:;<=>?@ AB\x8cqCDEFGH IJ ",
667 XPathParser.productions = [
692 [10, 3, 10, -27, 11],
695 [11, 3, 13, -28, 14],
700 [15, 3, -29, 2, -30],
704 [18, 3, -13, -29, -30],
705 [18, 4, -13, -29, 19, -30],
707 [19, 3, 20, -31, 19],
715 [14, 3, 14, -28, 23],
727 [26, 3, -20, -29, -30],
728 [26, 4, -21, -29, -15, -30],
729 [16, 3, -33, 30, -34],
741 XPathParser.DOUBLEDOT = 2;
742 XPathParser.DOUBLECOLON = 3;
743 XPathParser.DOUBLESLASH = 4;
744 XPathParser.NOTEQUAL = 5;
745 XPathParser.LESSTHANOREQUAL = 6;
746 XPathParser.GREATERTHANOREQUAL = 7;
749 XPathParser.MOD = 10;
750 XPathParser.DIV = 11;
751 XPathParser.MULTIPLYOPERATOR = 12;
752 XPathParser.FUNCTIONNAME = 13;
753 XPathParser.AXISNAME = 14;
754 XPathParser.LITERAL = 15;
755 XPathParser.NUMBER = 16;
756 XPathParser.ASTERISKNAMETEST = 17;
757 XPathParser.QNAME = 18;
758 XPathParser.NCNAMECOLONASTERISK = 19;
759 XPathParser.NODETYPE = 20;
760 XPathParser.PROCESSINGINSTRUCTIONWITHLITERAL = 21;
761 XPathParser.EQUALS = 22;
762 XPathParser.LESSTHAN = 23;
763 XPathParser.GREATERTHAN = 24;
764 XPathParser.PLUS = 25;
765 XPathParser.MINUS = 26;
766 XPathParser.BAR = 27;
767 XPathParser.SLASH = 28;
768 XPathParser.LEFTPARENTHESIS = 29;
769 XPathParser.RIGHTPARENTHESIS = 30;
770 XPathParser.COMMA = 31;
772 XPathParser.LEFTBRACKET = 33;
773 XPathParser.RIGHTBRACKET = 34;
774 XPathParser.DOT = 35;
775 XPathParser.DOLLAR = 36;
777 XPathParser.prototype.tokenize = function(s1) {
783 var c = s.charAt(pos++);
785 while (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
788 if (c == '\0' || pos >= s.length) {
793 types.push(XPathParser.LEFTPARENTHESIS);
799 types.push(XPathParser.RIGHTPARENTHESIS);
805 types.push(XPathParser.LEFTBRACKET);
811 types.push(XPathParser.RIGHTBRACKET);
817 types.push(XPathParser.AT);
823 types.push(XPathParser.COMMA);
829 types.push(XPathParser.BAR);
835 types.push(XPathParser.PLUS);
841 types.push(XPathParser.MINUS);
847 types.push(XPathParser.EQUALS);
853 types.push(XPathParser.DOLLAR);
862 types.push(XPathParser.DOUBLEDOT);
867 if (c >= '0' && c <= '9') {
868 var number = "." + c;
870 while (c >= '0' && c <= '9') {
874 types.push(XPathParser.NUMBER);
878 types.push(XPathParser.DOT);
883 if (c == '\'' || c == '"') {
886 while ((c = s.charAt(pos++)) != delimiter) {
889 types.push(XPathParser.LITERAL);
890 values.push(literal);
895 if (c >= '0' && c <= '9') {
898 while (c >= '0' && c <= '9') {
903 if (s.charAt(pos) >= '0' && s.charAt(pos) <= '9') {
905 number += s.charAt(pos++);
907 while (c >= '0' && c <= '9') {
913 types.push(XPathParser.NUMBER);
919 if (types.length > 0) {
920 var last = types[types.length - 1];
921 if (last != XPathParser.AT
922 && last != XPathParser.DOUBLECOLON
923 && last != XPathParser.LEFTPARENTHESIS
924 && last != XPathParser.LEFTBRACKET
925 && last != XPathParser.AND
926 && last != XPathParser.OR
927 && last != XPathParser.MOD
928 && last != XPathParser.DIV
929 && last != XPathParser.MULTIPLYOPERATOR
930 && last != XPathParser.SLASH
931 && last != XPathParser.DOUBLESLASH
932 && last != XPathParser.BAR
933 && last != XPathParser.PLUS
934 && last != XPathParser.MINUS
935 && last != XPathParser.EQUALS
936 && last != XPathParser.NOTEQUAL
937 && last != XPathParser.LESSTHAN
938 && last != XPathParser.LESSTHANOREQUAL
939 && last != XPathParser.GREATERTHAN
940 && last != XPathParser.GREATERTHANOREQUAL) {
941 types.push(XPathParser.MULTIPLYOPERATOR);
947 types.push(XPathParser.ASTERISKNAMETEST);
954 if (s.charAt(pos) == ':') {
955 types.push(XPathParser.DOUBLECOLON);
966 types.push(XPathParser.DOUBLESLASH);
971 types.push(XPathParser.SLASH);
977 if (s.charAt(pos) == '=') {
978 types.push(XPathParser.NOTEQUAL);
987 if (s.charAt(pos) == '=') {
988 types.push(XPathParser.LESSTHANOREQUAL);
994 types.push(XPathParser.LESSTHAN);
1001 if (s.charAt(pos) == '=') {
1002 types.push(XPathParser.GREATERTHANOREQUAL);
1005 c = s.charAt(pos++);
1008 types.push(XPathParser.GREATERTHAN);
1010 c = s.charAt(pos++);
1014 if (c == '_' || Utilities.isLetter(c.charCodeAt(0))) {
1016 c = s.charAt(pos++);
1017 while (Utilities.isNCNameChar(c.charCodeAt(0))) {
1019 c = s.charAt(pos++);
1021 if (types.length > 0) {
1022 var last = types[types.length - 1];
1023 if (last != XPathParser.AT
1024 && last != XPathParser.DOUBLECOLON
1025 && last != XPathParser.LEFTPARENTHESIS
1026 && last != XPathParser.LEFTBRACKET
1027 && last != XPathParser.AND
1028 && last != XPathParser.OR
1029 && last != XPathParser.MOD
1030 && last != XPathParser.DIV
1031 && last != XPathParser.MULTIPLYOPERATOR
1032 && last != XPathParser.SLASH
1033 && last != XPathParser.DOUBLESLASH
1034 && last != XPathParser.BAR
1035 && last != XPathParser.PLUS
1036 && last != XPathParser.MINUS
1037 && last != XPathParser.EQUALS
1038 && last != XPathParser.NOTEQUAL
1039 && last != XPathParser.LESSTHAN
1040 && last != XPathParser.LESSTHANOREQUAL
1041 && last != XPathParser.GREATERTHAN
1042 && last != XPathParser.GREATERTHANOREQUAL) {
1043 if (name == "and") {
1044 types.push(XPathParser.AND);
1049 types.push(XPathParser.OR);
1053 if (name == "mod") {
1054 types.push(XPathParser.MOD);
1058 if (name == "div") {
1059 types.push(XPathParser.DIV);
1066 if (s.charAt(pos) == '*') {
1067 types.push(XPathParser.NCNAMECOLONASTERISK);
1068 values.push(name + ":*");
1070 c = s.charAt(pos++);
1073 if (s.charAt(pos) == '_' || Utilities.isLetter(s.charCodeAt(pos))) {
1075 c = s.charAt(pos++);
1076 while (Utilities.isNCNameChar(c.charCodeAt(0))) {
1078 c = s.charAt(pos++);
1081 types.push(XPathParser.FUNCTIONNAME);
1085 types.push(XPathParser.QNAME);
1089 if (s.charAt(pos) == ':') {
1090 types.push(XPathParser.AXISNAME);
1096 if (name == "comment" || name == "text" || name == "node") {
1097 types.push(XPathParser.NODETYPE);
1101 if (name == "processing-instruction") {
1102 if (s.charAt(pos) == ')') {
1103 types.push(XPathParser.NODETYPE);
1105 types.push(XPathParser.PROCESSINGINSTRUCTIONWITHLITERAL);
1110 types.push(XPathParser.FUNCTIONNAME);
1114 types.push(XPathParser.QNAME);
1119 throw new Error("Unexpected character " + c);
1122 values.push("[EOF]");
1123 return [types, values];
1126 XPathParser.SHIFT = 's';
1127 XPathParser.REDUCE = 'r';
1128 XPathParser.ACCEPT = 'a';
1130 XPathParser.prototype.parse = function(s) {
1133 var res = this.tokenize(s);
1134 if (res == undefined) {
1142 var tokenValue = [];
1149 tokenValue.push("_S");
1151 a = types[tokenPos];
1152 t = values[tokenPos++];
1154 s = state[state.length - 1];
1155 switch (XPathParser.actionTable[s].charAt(a - 1)) {
1156 case XPathParser.SHIFT:
1159 state.push(XPathParser.actionTableNumber[s].charCodeAt(a - 1) - 32);
1160 a = types[tokenPos];
1161 t = values[tokenPos++];
1163 case XPathParser.REDUCE:
1164 var num = XPathParser.productions[XPathParser.actionTableNumber[s].charCodeAt(a - 1) - 32][1];
1166 for (var i = 0; i < num; i++) {
1168 rhs.unshift(tokenValue.pop());
1171 var s_ = state[state.length - 1];
1172 tokenType.push(XPathParser.productions[XPathParser.actionTableNumber[s].charCodeAt(a - 1) - 32][0]);
1173 if (this.reduceActions[XPathParser.actionTableNumber[s].charCodeAt(a - 1) - 32] == undefined) {
1174 tokenValue.push(rhs[0]);
1176 tokenValue.push(this.reduceActions[XPathParser.actionTableNumber[s].charCodeAt(a - 1) - 32](rhs));
1178 state.push(XPathParser.gotoTable[s_].charCodeAt(XPathParser.productions[XPathParser.actionTableNumber[s].charCodeAt(a - 1) - 32][0] - 2) - 33);
1180 case XPathParser.ACCEPT:
1181 return new XPath(tokenValue.pop());
1183 throw new Error("XPath parse error");
1188 // XPath /////////////////////////////////////////////////////////////////////
1190 XPath.prototype = new Object();
1191 XPath.prototype.constructor = XPath;
1192 XPath.superclass = Object.prototype;
1195 this.expression = e;
1198 XPath.prototype.toString = function() {
1199 return this.expression.toString();
1202 XPath.prototype.evaluate = function(c) {
1203 c.contextNode = c.expressionContextNode;
1205 c.contextPosition = 1;
1206 c.caseInsensitive = false;
1207 if (c.contextNode != null) {
1208 var doc = c.contextNode;
1209 if (doc.nodeType != 9 /*Node.DOCUMENT_NODE*/) {
1210 doc = doc.ownerDocument;
1213 c.caseInsensitive = doc.implementation.hasFeature("HTML", "2.0");
1215 c.caseInsensitive = true;
1218 return this.expression.evaluate(c);
1221 XPath.XML_NAMESPACE_URI = "http://www.w3.org/XML/1998/namespace";
1222 XPath.XMLNS_NAMESPACE_URI = "http://www.w3.org/2000/xmlns/";
1224 // Expression ////////////////////////////////////////////////////////////////
1226 Expression.prototype = new Object();
1227 Expression.prototype.constructor = Expression;
1228 Expression.superclass = Object.prototype;
1230 function Expression() {
1233 Expression.prototype.init = function() {
1236 Expression.prototype.toString = function() {
1237 return "<Expression>";
1240 Expression.prototype.evaluate = function(c) {
1241 throw new Error("Could not evaluate expression.");
1244 // UnaryOperation ////////////////////////////////////////////////////////////
1246 UnaryOperation.prototype = new Expression();
1247 UnaryOperation.prototype.constructor = UnaryOperation;
1248 UnaryOperation.superclass = Expression.prototype;
1250 function UnaryOperation(rhs) {
1251 if (arguments.length > 0) {
1256 UnaryOperation.prototype.init = function(rhs) {
1260 // UnaryMinusOperation ///////////////////////////////////////////////////////
1262 UnaryMinusOperation.prototype = new UnaryOperation();
1263 UnaryMinusOperation.prototype.constructor = UnaryMinusOperation;
1264 UnaryMinusOperation.superclass = UnaryOperation.prototype;
1266 function UnaryMinusOperation(rhs) {
1267 if (arguments.length > 0) {
1272 UnaryMinusOperation.prototype.init = function(rhs) {
1273 UnaryMinusOperation.superclass.init.call(this, rhs);
1276 UnaryMinusOperation.prototype.evaluate = function(c) {
1277 return this.rhs.evaluate(c).number().negate();
1280 UnaryMinusOperation.prototype.toString = function() {
1281 return "-" + this.rhs.toString();
1284 // BinaryOperation ///////////////////////////////////////////////////////////
1286 BinaryOperation.prototype = new Expression();
1287 BinaryOperation.prototype.constructor = BinaryOperation;
1288 BinaryOperation.superclass = Expression.prototype;
1290 function BinaryOperation(lhs, rhs) {
1291 if (arguments.length > 0) {
1292 this.init(lhs, rhs);
1296 BinaryOperation.prototype.init = function(lhs, rhs) {
1301 // OrOperation ///////////////////////////////////////////////////////////////
1303 OrOperation.prototype = new BinaryOperation();
1304 OrOperation.prototype.constructor = OrOperation;
1305 OrOperation.superclass = BinaryOperation.prototype;
1307 function OrOperation(lhs, rhs) {
1308 if (arguments.length > 0) {
1309 this.init(lhs, rhs);
1313 OrOperation.prototype.init = function(lhs, rhs) {
1314 OrOperation.superclass.init.call(this, lhs, rhs);
1317 OrOperation.prototype.toString = function() {
1318 return "(" + this.lhs.toString() + " or " + this.rhs.toString() + ")";
1321 OrOperation.prototype.evaluate = function(c) {
1322 var b = this.lhs.evaluate(c).bool();
1323 if (b.booleanValue()) {
1326 return this.rhs.evaluate(c).bool();
1329 // AndOperation //////////////////////////////////////////////////////////////
1331 AndOperation.prototype = new BinaryOperation();
1332 AndOperation.prototype.constructor = AndOperation;
1333 AndOperation.superclass = BinaryOperation.prototype;
1335 function AndOperation(lhs, rhs) {
1336 if (arguments.length > 0) {
1337 this.init(lhs, rhs);
1341 AndOperation.prototype.init = function(lhs, rhs) {
1342 AndOperation.superclass.init.call(this, lhs, rhs);
1345 AndOperation.prototype.toString = function() {
1346 return "(" + this.lhs.toString() + " and " + this.rhs.toString() + ")";
1349 AndOperation.prototype.evaluate = function(c) {
1350 var b = this.lhs.evaluate(c).bool();
1351 if (!b.booleanValue()) {
1354 return this.rhs.evaluate(c).bool();
1357 // EqualsOperation ///////////////////////////////////////////////////////////
1359 EqualsOperation.prototype = new BinaryOperation();
1360 EqualsOperation.prototype.constructor = EqualsOperation;
1361 EqualsOperation.superclass = BinaryOperation.prototype;
1363 function EqualsOperation(lhs, rhs) {
1364 if (arguments.length > 0) {
1365 this.init(lhs, rhs);
1369 EqualsOperation.prototype.init = function(lhs, rhs) {
1370 EqualsOperation.superclass.init.call(this, lhs, rhs);
1373 EqualsOperation.prototype.toString = function() {
1374 return "(" + this.lhs.toString() + " = " + this.rhs.toString() + ")";
1377 EqualsOperation.prototype.evaluate = function(c) {
1378 return this.lhs.evaluate(c).equals(this.rhs.evaluate(c));
1381 // NotEqualOperation /////////////////////////////////////////////////////////
1383 NotEqualOperation.prototype = new BinaryOperation();
1384 NotEqualOperation.prototype.constructor = NotEqualOperation;
1385 NotEqualOperation.superclass = BinaryOperation.prototype;
1387 function NotEqualOperation(lhs, rhs) {
1388 if (arguments.length > 0) {
1389 this.init(lhs, rhs);
1393 NotEqualOperation.prototype.init = function(lhs, rhs) {
1394 NotEqualOperation.superclass.init.call(this, lhs, rhs);
1397 NotEqualOperation.prototype.toString = function() {
1398 return "(" + this.lhs.toString() + " != " + this.rhs.toString() + ")";
1401 NotEqualOperation.prototype.evaluate = function(c) {
1402 return this.lhs.evaluate(c).notequal(this.rhs.evaluate(c));
1405 // LessThanOperation /////////////////////////////////////////////////////////
1407 LessThanOperation.prototype = new BinaryOperation();
1408 LessThanOperation.prototype.constructor = LessThanOperation;
1409 LessThanOperation.superclass = BinaryOperation.prototype;
1411 function LessThanOperation(lhs, rhs) {
1412 if (arguments.length > 0) {
1413 this.init(lhs, rhs);
1417 LessThanOperation.prototype.init = function(lhs, rhs) {
1418 LessThanOperation.superclass.init.call(this, lhs, rhs);
1421 LessThanOperation.prototype.evaluate = function(c) {
1422 return this.lhs.evaluate(c).lessthan(this.rhs.evaluate(c));
1425 LessThanOperation.prototype.toString = function() {
1426 return "(" + this.lhs.toString() + " < " + this.rhs.toString() + ")";
1429 // GreaterThanOperation //////////////////////////////////////////////////////
1431 GreaterThanOperation.prototype = new BinaryOperation();
1432 GreaterThanOperation.prototype.constructor = GreaterThanOperation;
1433 GreaterThanOperation.superclass = BinaryOperation.prototype;
1435 function GreaterThanOperation(lhs, rhs) {
1436 if (arguments.length > 0) {
1437 this.init(lhs, rhs);
1441 GreaterThanOperation.prototype.init = function(lhs, rhs) {
1442 GreaterThanOperation.superclass.init.call(this, lhs, rhs);
1445 GreaterThanOperation.prototype.evaluate = function(c) {
1446 return this.lhs.evaluate(c).greaterthan(this.rhs.evaluate(c));
1449 GreaterThanOperation.prototype.toString = function() {
1450 return "(" + this.lhs.toString() + " > " + this.rhs.toString() + ")";
1453 // LessThanOrEqualOperation //////////////////////////////////////////////////
1455 LessThanOrEqualOperation.prototype = new BinaryOperation();
1456 LessThanOrEqualOperation.prototype.constructor = LessThanOrEqualOperation;
1457 LessThanOrEqualOperation.superclass = BinaryOperation.prototype;
1459 function LessThanOrEqualOperation(lhs, rhs) {
1460 if (arguments.length > 0) {
1461 this.init(lhs, rhs);
1465 LessThanOrEqualOperation.prototype.init = function(lhs, rhs) {
1466 LessThanOrEqualOperation.superclass.init.call(this, lhs, rhs);
1469 LessThanOrEqualOperation.prototype.evaluate = function(c) {
1470 return this.lhs.evaluate(c).lessthanorequal(this.rhs.evaluate(c));
1473 LessThanOrEqualOperation.prototype.toString = function() {
1474 return "(" + this.lhs.toString() + " <= " + this.rhs.toString() + ")";
1477 // GreaterThanOrEqualOperation ///////////////////////////////////////////////
1479 GreaterThanOrEqualOperation.prototype = new BinaryOperation();
1480 GreaterThanOrEqualOperation.prototype.constructor = GreaterThanOrEqualOperation;
1481 GreaterThanOrEqualOperation.superclass = BinaryOperation.prototype;
1483 function GreaterThanOrEqualOperation(lhs, rhs) {
1484 if (arguments.length > 0) {
1485 this.init(lhs, rhs);
1489 GreaterThanOrEqualOperation.prototype.init = function(lhs, rhs) {
1490 GreaterThanOrEqualOperation.superclass.init.call(this, lhs, rhs);
1493 GreaterThanOrEqualOperation.prototype.evaluate = function(c) {
1494 return this.lhs.evaluate(c).greaterthanorequal(this.rhs.evaluate(c));
1497 GreaterThanOrEqualOperation.prototype.toString = function() {
1498 return "(" + this.lhs.toString() + " >= " + this.rhs.toString() + ")";
1501 // PlusOperation /////////////////////////////////////////////////////////////
1503 PlusOperation.prototype = new BinaryOperation();
1504 PlusOperation.prototype.constructor = PlusOperation;
1505 PlusOperation.superclass = BinaryOperation.prototype;
1507 function PlusOperation(lhs, rhs) {
1508 if (arguments.length > 0) {
1509 this.init(lhs, rhs);
1513 PlusOperation.prototype.init = function(lhs, rhs) {
1514 PlusOperation.superclass.init.call(this, lhs, rhs);
1517 PlusOperation.prototype.evaluate = function(c) {
1518 return this.lhs.evaluate(c).number().plus(this.rhs.evaluate(c).number());
1521 PlusOperation.prototype.toString = function() {
1522 return "(" + this.lhs.toString() + " + " + this.rhs.toString() + ")";
1525 // MinusOperation ////////////////////////////////////////////////////////////
1527 MinusOperation.prototype = new BinaryOperation();
1528 MinusOperation.prototype.constructor = MinusOperation;
1529 MinusOperation.superclass = BinaryOperation.prototype;
1531 function MinusOperation(lhs, rhs) {
1532 if (arguments.length > 0) {
1533 this.init(lhs, rhs);
1537 MinusOperation.prototype.init = function(lhs, rhs) {
1538 MinusOperation.superclass.init.call(this, lhs, rhs);
1541 MinusOperation.prototype.evaluate = function(c) {
1542 return this.lhs.evaluate(c).number().minus(this.rhs.evaluate(c).number());
1545 MinusOperation.prototype.toString = function() {
1546 return "(" + this.lhs.toString() + " - " + this.rhs.toString() + ")";
1549 // MultiplyOperation /////////////////////////////////////////////////////////
1551 MultiplyOperation.prototype = new BinaryOperation();
1552 MultiplyOperation.prototype.constructor = MultiplyOperation;
1553 MultiplyOperation.superclass = BinaryOperation.prototype;
1555 function MultiplyOperation(lhs, rhs) {
1556 if (arguments.length > 0) {
1557 this.init(lhs, rhs);
1561 MultiplyOperation.prototype.init = function(lhs, rhs) {
1562 MultiplyOperation.superclass.init.call(this, lhs, rhs);
1565 MultiplyOperation.prototype.evaluate = function(c) {
1566 return this.lhs.evaluate(c).number().multiply(this.rhs.evaluate(c).number());
1569 MultiplyOperation.prototype.toString = function() {
1570 return "(" + this.lhs.toString() + " * " + this.rhs.toString() + ")";
1573 // DivOperation //////////////////////////////////////////////////////////////
1575 DivOperation.prototype = new BinaryOperation();
1576 DivOperation.prototype.constructor = DivOperation;
1577 DivOperation.superclass = BinaryOperation.prototype;
1579 function DivOperation(lhs, rhs) {
1580 if (arguments.length > 0) {
1581 this.init(lhs, rhs);
1585 DivOperation.prototype.init = function(lhs, rhs) {
1586 DivOperation.superclass.init.call(this, lhs, rhs);
1589 DivOperation.prototype.evaluate = function(c) {
1590 return this.lhs.evaluate(c).number().div(this.rhs.evaluate(c).number());
1593 DivOperation.prototype.toString = function() {
1594 return "(" + this.lhs.toString() + " div " + this.rhs.toString() + ")";
1597 // ModOperation //////////////////////////////////////////////////////////////
1599 ModOperation.prototype = new BinaryOperation();
1600 ModOperation.prototype.constructor = ModOperation;
1601 ModOperation.superclass = BinaryOperation.prototype;
1603 function ModOperation(lhs, rhs) {
1604 if (arguments.length > 0) {
1605 this.init(lhs, rhs);
1609 ModOperation.prototype.init = function(lhs, rhs) {
1610 ModOperation.superclass.init.call(this, lhs, rhs);
1613 ModOperation.prototype.evaluate = function(c) {
1614 return this.lhs.evaluate(c).number().mod(this.rhs.evaluate(c).number());
1617 ModOperation.prototype.toString = function() {
1618 return "(" + this.lhs.toString() + " mod " + this.rhs.toString() + ")";
1621 // BarOperation //////////////////////////////////////////////////////////////
1623 BarOperation.prototype = new BinaryOperation();
1624 BarOperation.prototype.constructor = BarOperation;
1625 BarOperation.superclass = BinaryOperation.prototype;
1627 function BarOperation(lhs, rhs) {
1628 if (arguments.length > 0) {
1629 this.init(lhs, rhs);
1633 BarOperation.prototype.init = function(lhs, rhs) {
1634 BarOperation.superclass.init.call(this, lhs, rhs);
1637 BarOperation.prototype.evaluate = function(c) {
1638 return this.lhs.evaluate(c).nodeset().union(this.rhs.evaluate(c).nodeset());
1641 BarOperation.prototype.toString = function() {
1642 return this.lhs.toString() + " | " + this.rhs.toString();
1645 // PathExpr //////////////////////////////////////////////////////////////////
1647 PathExpr.prototype = new Expression();
1648 PathExpr.prototype.constructor = PathExpr;
1649 PathExpr.superclass = Expression.prototype;
1651 function PathExpr(filter, filterPreds, locpath) {
1652 if (arguments.length > 0) {
1653 this.init(filter, filterPreds, locpath);
1657 PathExpr.prototype.init = function(filter, filterPreds, locpath) {
1658 PathExpr.superclass.init.call(this);
1659 this.filter = filter;
1660 this.filterPredicates = filterPreds;
1661 this.locationPath = locpath;
1664 PathExpr.prototype.evaluate = function(c) {
1666 var xpc = new XPathContext();
1667 xpc.variableResolver = c.variableResolver;
1668 xpc.functionResolver = c.functionResolver;
1669 xpc.namespaceResolver = c.namespaceResolver;
1670 xpc.expressionContextNode = c.expressionContextNode;
1671 xpc.virtualRoot = c.virtualRoot;
1672 xpc.caseInsensitive = c.caseInsensitive;
1673 if (this.filter == null) {
1674 nodes = [ c.contextNode ];
1676 var ns = this.filter.evaluate(c);
1677 if (!Utilities.instance_of(ns, XNodeSet)) {
1678 if (this.filterPredicates != null && this.filterPredicates.length > 0 || this.locationPath != null) {
1679 throw new Error("Path expression filter must evaluate to a nodset if predicates or location path are used");
1683 nodes = ns.toArray();
1684 if (this.filterPredicates != null) {
1685 // apply each of the predicates in turn
1686 for (var j = 0; j < this.filterPredicates.length; j++) {
1687 var pred = this.filterPredicates[j];
1689 xpc.contextSize = nodes.length;
1690 for (xpc.contextPosition = 1; xpc.contextPosition <= xpc.contextSize; xpc.contextPosition++) {
1691 xpc.contextNode = nodes[xpc.contextPosition - 1];
1692 if (this.predicateMatches(pred, xpc)) {
1693 newNodes.push(xpc.contextNode);
1700 if (this.locationPath != null) {
1701 if (this.locationPath.absolute) {
1702 if (nodes[0].nodeType != 9 /*Node.DOCUMENT_NODE*/) {
1703 if (xpc.virtualRoot != null) {
1704 nodes = [ xpc.virtualRoot ];
1706 if (nodes[0].ownerDocument == null) {
1707 // IE 5.5 doesn't have ownerDocument?
1709 while (n.parentNode != null) {
1714 nodes = [ nodes[0].ownerDocument ];
1718 nodes = [ nodes[0] ];
1721 for (var i = 0; i < this.locationPath.steps.length; i++) {
1722 var step = this.locationPath.steps[i];
1724 for (var j = 0; j < nodes.length; j++) {
1725 xpc.contextNode = nodes[j];
1726 switch (step.axis) {
1728 // look at all the ancestor nodes
1729 if (xpc.contextNode === xpc.virtualRoot) {
1733 if (xpc.contextNode.nodeType == 2 /*Node.ATTRIBUTE_NODE*/) {
1734 m = this.getOwnerElement(xpc.contextNode);
1736 m = xpc.contextNode.parentNode;
1739 if (step.nodeTest.matches(m, xpc)) {
1742 if (m === xpc.virtualRoot) {
1749 case Step.ANCESTORORSELF:
1750 // look at all the ancestor nodes and the current node
1751 for (var m = xpc.contextNode; m != null; m = m.nodeType == 2 /*Node.ATTRIBUTE_NODE*/ ? this.getOwnerElement(m) : m.parentNode) {
1752 if (step.nodeTest.matches(m, xpc)) {
1755 if (m === xpc.virtualRoot) {
1761 case Step.ATTRIBUTE:
1762 // look at the attributes
1763 var nnm = xpc.contextNode.attributes;
1765 for (var k = 0; k < nnm.length; k++) {
1766 var m = nnm.item(k);
1767 if (step.nodeTest.matches(m, xpc)) {
1775 // look at all child elements
1776 for (var m = xpc.contextNode.firstChild; m != null; m = m.nextSibling) {
1777 if (step.nodeTest.matches(m, xpc)) {
1783 case Step.DESCENDANT:
1784 // look at all descendant nodes
1785 var st = [ xpc.contextNode.firstChild ];
1786 while (st.length > 0) {
1787 for (var m = st.pop(); m != null; ) {
1788 if (step.nodeTest.matches(m, xpc)) {
1791 if (m.firstChild != null) {
1792 st.push(m.nextSibling);
1801 case Step.DESCENDANTORSELF:
1803 if (step.nodeTest.matches(xpc.contextNode, xpc)) {
1804 newNodes.push(xpc.contextNode);
1806 // look at all descendant nodes
1807 var st = [ xpc.contextNode.firstChild ];
1808 while (st.length > 0) {
1809 for (var m = st.pop(); m != null; ) {
1810 if (step.nodeTest.matches(m, xpc)) {
1813 if (m.firstChild != null) {
1814 st.push(m.nextSibling);
1823 case Step.FOLLOWING:
1824 if (xpc.contextNode === xpc.virtualRoot) {
1828 if (xpc.contextNode.firstChild != null) {
1829 st.unshift(xpc.contextNode.firstChild);
1831 st.unshift(xpc.contextNode.nextSibling);
1833 for (var m = xpc.contextNode.parentNode; m != null && m.nodeType != 9 /*Node.DOCUMENT_NODE*/ && m !== xpc.virtualRoot; m = m.parentNode) {
1834 st.unshift(m.nextSibling);
1837 for (var m = st.pop(); m != null; ) {
1838 if (step.nodeTest.matches(m, xpc)) {
1841 if (m.firstChild != null) {
1842 st.push(m.nextSibling);
1848 } while (st.length > 0);
1851 case Step.FOLLOWINGSIBLING:
1852 if (xpc.contextNode === xpc.virtualRoot) {
1855 for (var m = xpc.contextNode.nextSibling; m != null; m = m.nextSibling) {
1856 if (step.nodeTest.matches(m, xpc)) {
1862 case Step.NAMESPACE:
1864 if (xpc.contextNode.nodeType == 1 /*Node.ELEMENT_NODE*/) {
1865 n["xml"] = XPath.XML_NAMESPACE_URI;
1866 n["xmlns"] = XPath.XMLNS_NAMESPACE_URI;
1867 for (var m = xpc.contextNode; m != null && m.nodeType == 1 /*Node.ELEMENT_NODE*/; m = m.parentNode) {
1868 for (var k = 0; k < m.attributes.length; k++) {
1869 var attr = m.attributes.item(k);
1870 var nm = String(attr.name);
1871 if (nm == "xmlns") {
1872 if (n[""] == undefined) {
1875 } else if (nm.length > 6 && nm.substring(0, 6) == "xmlns:") {
1876 var pre = nm.substring(6, nm.length);
1877 if (n[pre] == undefined) {
1878 n[pre] = attr.value;
1883 for (var pre in n) {
1884 var nsn = new NamespaceNode(pre, n[pre], xpc.contextNode);
1885 if (step.nodeTest.matches(nsn, xpc)) {
1894 if (xpc.contextNode !== xpc.virtualRoot) {
1895 if (xpc.contextNode.nodeType == 2 /*Node.ATTRIBUTE_NODE*/) {
1896 m = this.getOwnerElement(xpc.contextNode);
1898 m = xpc.contextNode.parentNode;
1901 if (m != null && step.nodeTest.matches(m, xpc)) {
1906 case Step.PRECEDING:
1908 if (xpc.virtualRoot != null) {
1909 st = [ xpc.virtualRoot ];
1911 st = xpc.contextNode.nodeType == 9 /*Node.DOCUMENT_NODE*/
1912 ? [ xpc.contextNode ]
1913 : [ xpc.contextNode.ownerDocument ];
1915 outer: while (st.length > 0) {
1916 for (var m = st.pop(); m != null; ) {
1917 if (m == xpc.contextNode) {
1920 if (step.nodeTest.matches(m, xpc)) {
1921 newNodes.unshift(m);
1923 if (m.firstChild != null) {
1924 st.push(m.nextSibling);
1933 case Step.PRECEDINGSIBLING:
1934 if (xpc.contextNode === xpc.virtualRoot) {
1937 for (var m = xpc.contextNode.previousSibling; m != null; m = m.previousSibling) {
1938 if (step.nodeTest.matches(m, xpc)) {
1945 if (step.nodeTest.matches(xpc.contextNode, xpc)) {
1946 newNodes.push(xpc.contextNode);
1954 // apply each of the predicates in turn
1955 for (var j = 0; j < step.predicates.length; j++) {
1956 var pred = step.predicates[j];
1958 xpc.contextSize = nodes.length;
1959 for (xpc.contextPosition = 1; xpc.contextPosition <= xpc.contextSize; xpc.contextPosition++) {
1960 xpc.contextNode = nodes[xpc.contextPosition - 1];
1961 if (this.predicateMatches(pred, xpc)) {
1962 newNodes.push(xpc.contextNode);
1970 var ns = new XNodeSet();
1975 PathExpr.prototype.predicateMatches = function(pred, c) {
1976 var res = pred.evaluate(c);
1977 if (Utilities.instance_of(res, XNumber)) {
1978 return c.contextPosition == res.numberValue();
1980 return res.booleanValue();
1983 PathExpr.prototype.toString = function() {
1984 if (this.filter != undefined) {
1985 var s = this.filter.toString();
1986 if (Utilities.instance_of(this.filter, XString)) {
1989 if (this.filterPredicates != undefined) {
1990 for (var i = 0; i < this.filterPredicates.length; i++) {
1991 s = s + "[" + this.filterPredicates[i].toString() + "]";
1994 if (this.locationPath != undefined) {
1995 if (!this.locationPath.absolute) {
1998 s += this.locationPath.toString();
2002 return this.locationPath.toString();
2005 PathExpr.prototype.getOwnerElement = function(n) {
2006 // DOM 2 has ownerElement
2007 if (n.ownerElement) {
2008 return n.ownerElement;
2010 // DOM 1 Internet Explorer can use selectSingleNode (ironically)
2012 if (n.selectSingleNode) {
2013 return n.selectSingleNode("..");
2017 // Other DOM 1 implementations must use this egregious search
2018 var doc = n.nodeType == 9 /*Node.DOCUMENT_NODE*/
2021 var elts = doc.getElementsByTagName("*");
2022 for (var i = 0; i < elts.length; i++) {
2023 var elt = elts.item(i);
2024 var nnm = elt.attributes;
2025 for (var j = 0; j < nnm.length; j++) {
2026 var an = nnm.item(j);
2035 // LocationPath //////////////////////////////////////////////////////////////
2037 LocationPath.prototype = new Object();
2038 LocationPath.prototype.constructor = LocationPath;
2039 LocationPath.superclass = Object.prototype;
2041 function LocationPath(abs, steps) {
2042 if (arguments.length > 0) {
2043 this.init(abs, steps);
2047 LocationPath.prototype.init = function(abs, steps) {
2048 this.absolute = abs;
2052 LocationPath.prototype.toString = function() {
2054 if (this.absolute) {
2059 for (var i = 0; i < this.steps.length; i++) {
2063 s += this.steps[i].toString();
2068 // Step //////////////////////////////////////////////////////////////////////
2070 Step.prototype = new Object();
2071 Step.prototype.constructor = Step;
2072 Step.superclass = Object.prototype;
2074 function Step(axis, nodetest, preds) {
2075 if (arguments.length > 0) {
2076 this.init(axis, nodetest, preds);
2080 Step.prototype.init = function(axis, nodetest, preds) {
2082 this.nodeTest = nodetest;
2083 this.predicates = preds;
2086 Step.prototype.toString = function() {
2088 switch (this.axis) {
2092 case Step.ANCESTORORSELF:
2093 s = "ancestor-or-self";
2095 case Step.ATTRIBUTE:
2101 case Step.DESCENDANT:
2104 case Step.DESCENDANTORSELF:
2105 s = "descendant-or-self";
2107 case Step.FOLLOWING:
2110 case Step.FOLLOWINGSIBLING:
2111 s = "following-sibling";
2113 case Step.NAMESPACE:
2119 case Step.PRECEDING:
2122 case Step.PRECEDINGSIBLING:
2123 s = "preceding-sibling";
2130 s += this.nodeTest.toString();
2131 for (var i = 0; i < this.predicates.length; i++) {
2132 s += "[" + this.predicates[i].toString() + "]";
2138 Step.ANCESTORORSELF = 1;
2141 Step.DESCENDANT = 4;
2142 Step.DESCENDANTORSELF = 5;
2144 Step.FOLLOWINGSIBLING = 7;
2147 Step.PRECEDING = 10;
2148 Step.PRECEDINGSIBLING = 11;
2151 // NodeTest //////////////////////////////////////////////////////////////////
2153 NodeTest.prototype = new Object();
2154 NodeTest.prototype.constructor = NodeTest;
2155 NodeTest.superclass = Object.prototype;
2157 function NodeTest(type, value) {
2158 if (arguments.length > 0) {
2159 this.init(type, value);
2163 NodeTest.prototype.init = function(type, value) {
2168 NodeTest.prototype.toString = function() {
2169 switch (this.type) {
2170 case NodeTest.NAMETESTANY:
2172 case NodeTest.NAMETESTPREFIXANY:
2173 return this.value + ":*";
2174 case NodeTest.NAMETESTRESOLVEDANY:
2175 return "{" + this.value + "}*";
2176 case NodeTest.NAMETESTQNAME:
2178 case NodeTest.NAMETESTRESOLVEDNAME:
2179 return "{" + this.namespaceURI + "}" + this.value;
2180 case NodeTest.COMMENT:
2185 if (this.value != undefined) {
2186 return "processing-instruction(\"" + this.value + "\")";
2188 return "processing-instruction()";
2192 return "<unknown nodetest type>";
2195 NodeTest.prototype.matches = function(n, xpc) {
2196 switch (this.type) {
2197 case NodeTest.NAMETESTANY:
2198 if (n.nodeType == 2 /*Node.ATTRIBUTE_NODE*/
2199 || n.nodeType == 1 /*Node.ELEMENT_NODE*/
2200 || n.nodeType == XPathNamespace.XPATH_NAMESPACE_NODE) {
2204 case NodeTest.NAMETESTPREFIXANY:
2205 if ((n.nodeType == 2 /*Node.ATTRIBUTE_NODE*/ || n.nodeType == 1 /*Node.ELEMENT_NODE*/)) {
2206 var ns = xpc.namespaceResolver.getNamespace(this.value, xpc.expressionContextNode);
2208 throw new Error("Cannot resolve QName " + this.value);
2213 case NodeTest.NAMETESTQNAME:
2214 if (n.nodeType == 2 /*Node.ATTRIBUTE_NODE*/
2215 || n.nodeType == 1 /*Node.ELEMENT_NODE*/
2216 || n.nodeType == XPathNamespace.XPATH_NAMESPACE_NODE) {
2217 var test = Utilities.resolveQName(this.value, xpc.namespaceResolver, xpc.expressionContextNode, false);
2218 if (test[0] == null) {
2219 throw new Error("Cannot resolve QName " + this.value);
2221 test[0] = String(test[0]);
2222 test[1] = String(test[1]);
2223 if (test[0] == "") {
2226 var node = Utilities.resolveQName(n.nodeName, xpc.namespaceResolver, n, n.nodeType == 1 /*Node.ELEMENT_NODE*/);
2227 node[0] = String(node[0]);
2228 node[1] = String(node[1]);
2229 if (node[0] == "") {
2230 if (n.namespaceURI) {
2231 node[0] = n.namespaceURI;
2236 if (xpc.caseInsensitive) {
2237 return test[0] == node[0] && String(test[1]).toLowerCase() == String(node[1]).toLowerCase();
2239 return test[0] == node[0] && test[1] == node[1];
2242 case NodeTest.COMMENT:
2243 return n.nodeType == 8 /*Node.COMMENT_NODE*/;
2245 return n.nodeType == 3 /*Node.TEXT_NODE*/ || n.nodeType == 4 /*Node.CDATA_SECTION_NODE*/;
2247 return n.nodeType == 7 /*Node.PROCESSING_INSTRUCTION_NODE*/
2248 && (this.value == null || n.nodeName == this.value);
2250 return n.nodeType == 9 /*Node.DOCUMENT_NODE*/
2251 || n.nodeType == 1 /*Node.ELEMENT_NODE*/
2252 || n.nodeType == 2 /*Node.ATTRIBUTE_NODE*/
2253 || n.nodeType == 3 /*Node.TEXT_NODE*/
2254 || n.nodeType == 4 /*Node.CDATA_SECTION_NODE*/
2255 || n.nodeType == 8 /*Node.COMMENT_NODE*/
2256 || n.nodeType == 7 /*Node.PROCESSING_INSTRUCTION_NODE*/;
2261 NodeTest.NAMETESTANY = 0;
2262 NodeTest.NAMETESTPREFIXANY = 1;
2263 NodeTest.NAMETESTQNAME = 2;
2264 NodeTest.COMMENT = 3;
2269 // VariableReference /////////////////////////////////////////////////////////
2271 VariableReference.prototype = new Expression();
2272 VariableReference.prototype.constructor = VariableReference;
2273 VariableReference.superclass = Expression.prototype;
2275 function VariableReference(v) {
2276 if (arguments.length > 0) {
2281 VariableReference.prototype.init = function(v) {
2285 VariableReference.prototype.toString = function() {
2286 return "$" + this.variable;
2289 VariableReference.prototype.evaluate = function(c) {
2290 return c.variableResolver.getVariable(this.variable, c);
2293 // FunctionCall //////////////////////////////////////////////////////////////
2295 FunctionCall.prototype = new Expression();
2296 FunctionCall.prototype.constructor = FunctionCall;
2297 FunctionCall.superclass = Expression.prototype;
2299 function FunctionCall(fn, args) {
2300 if (arguments.length > 0) {
2301 this.init(fn, args);
2305 FunctionCall.prototype.init = function(fn, args) {
2306 this.functionName = fn;
2307 this.arguments = args;
2310 FunctionCall.prototype.toString = function() {
2311 var s = this.functionName + "(";
2312 for (var i = 0; i < this.arguments.length; i++) {
2316 s += this.arguments[i].toString();
2321 FunctionCall.prototype.evaluate = function(c) {
2322 var f = c.functionResolver.getFunction(this.functionName, c);
2323 if (f == undefined) {
2324 throw new Error("Unknown function " + this.functionName);
2326 var a = [c].concat(this.arguments);
2327 return f.apply(c.functionResolver.thisArg, a);
2330 // XString ///////////////////////////////////////////////////////////////////
2332 XString.prototype = new Expression();
2333 XString.prototype.constructor = XString;
2334 XString.superclass = Expression.prototype;
2336 function XString(s) {
2337 if (arguments.length > 0) {
2342 XString.prototype.init = function(s) {
2346 XString.prototype.toString = function() {
2350 XString.prototype.evaluate = function(c) {
2354 XString.prototype.string = function() {
2358 XString.prototype.number = function() {
2359 return new XNumber(this.str);
2362 XString.prototype.bool = function() {
2363 return new XBoolean(this.str);
2366 XString.prototype.nodeset = function() {
2367 throw new Error("Cannot convert string to nodeset");
2370 XString.prototype.stringValue = function() {
2374 XString.prototype.numberValue = function() {
2375 return this.number().numberValue();
2378 XString.prototype.booleanValue = function() {
2379 return this.bool().booleanValue();
2382 XString.prototype.equals = function(r) {
2383 if (Utilities.instance_of(r, XBoolean)) {
2384 return this.bool().equals(r);
2386 if (Utilities.instance_of(r, XNumber)) {
2387 return this.number().equals(r);
2389 if (Utilities.instance_of(r, XNodeSet)) {
2390 return r.compareWithString(this, Operators.equals);
2392 return new XBoolean(this.str == r.str);
2395 XString.prototype.notequal = function(r) {
2396 if (Utilities.instance_of(r, XBoolean)) {
2397 return this.bool().notequal(r);
2399 if (Utilities.instance_of(r, XNumber)) {
2400 return this.number().notequal(r);
2402 if (Utilities.instance_of(r, XNodeSet)) {
2403 return r.compareWithString(this, Operators.notequal);
2405 return new XBoolean(this.str != r.str);
2408 XString.prototype.lessthan = function(r) {
2409 if (Utilities.instance_of(r, XNodeSet)) {
2410 return r.compareWithNumber(this.number(), Operators.greaterthanorequal);
2412 return this.number().lessthan(r.number());
2415 XString.prototype.greaterthan = function(r) {
2416 if (Utilities.instance_of(r, XNodeSet)) {
2417 return r.compareWithNumber(this.number(), Operators.lessthanorequal);
2419 return this.number().greaterthan(r.number());
2422 XString.prototype.lessthanorequal = function(r) {
2423 if (Utilities.instance_of(r, XNodeSet)) {
2424 return r.compareWithNumber(this.number(), Operators.greaterthan);
2426 return this.number().lessthanorequal(r.number());
2429 XString.prototype.greaterthanorequal = function(r) {
2430 if (Utilities.instance_of(r, XNodeSet)) {
2431 return r.compareWithNumber(this.number(), Operators.lessthan);
2433 return this.number().greaterthanorequal(r.number());
2436 // XNumber ///////////////////////////////////////////////////////////////////
2438 XNumber.prototype = new Expression();
2439 XNumber.prototype.constructor = XNumber;
2440 XNumber.superclass = Expression.prototype;
2442 function XNumber(n) {
2443 if (arguments.length > 0) {
2448 XNumber.prototype.init = function(n) {
2449 this.num = Number(n);
2452 XNumber.prototype.toString = function() {
2456 XNumber.prototype.evaluate = function(c) {
2460 XNumber.prototype.string = function() {
2461 return new XString(this.num);
2464 XNumber.prototype.number = function() {
2468 XNumber.prototype.bool = function() {
2469 return new XBoolean(this.num);
2472 XNumber.prototype.nodeset = function() {
2473 throw new Error("Cannot convert number to nodeset");
2476 XNumber.prototype.stringValue = function() {
2477 return this.string().stringValue();
2480 XNumber.prototype.numberValue = function() {
2484 XNumber.prototype.booleanValue = function() {
2485 return this.bool().booleanValue();
2488 XNumber.prototype.negate = function() {
2489 return new XNumber(-this.num);
2492 XNumber.prototype.equals = function(r) {
2493 if (Utilities.instance_of(r, XBoolean)) {
2494 return this.bool().equals(r);
2496 if (Utilities.instance_of(r, XString)) {
2497 return this.equals(r.number());
2499 if (Utilities.instance_of(r, XNodeSet)) {
2500 return r.compareWithNumber(this, Operators.equals);
2502 return new XBoolean(this.num == r.num);
2505 XNumber.prototype.notequal = function(r) {
2506 if (Utilities.instance_of(r, XBoolean)) {
2507 return this.bool().notequal(r);
2509 if (Utilities.instance_of(r, XString)) {
2510 return this.notequal(r.number());
2512 if (Utilities.instance_of(r, XNodeSet)) {
2513 return r.compareWithNumber(this, Operators.notequal);
2515 return new XBoolean(this.num != r.num);
2518 XNumber.prototype.lessthan = function(r) {
2519 if (Utilities.instance_of(r, XNodeSet)) {
2520 return r.compareWithNumber(this, Operators.greaterthanorequal);
2522 if (Utilities.instance_of(r, XBoolean) || Utilities.instance_of(r, XString)) {
2523 return this.lessthan(r.number());
2525 return new XBoolean(this.num < r.num);
2528 XNumber.prototype.greaterthan = function(r) {
2529 if (Utilities.instance_of(r, XNodeSet)) {
2530 return r.compareWithNumber(this, Operators.lessthanorequal);
2532 if (Utilities.instance_of(r, XBoolean) || Utilities.instance_of(r, XString)) {
2533 return this.greaterthan(r.number());
2535 return new XBoolean(this.num > r.num);
2538 XNumber.prototype.lessthanorequal = function(r) {
2539 if (Utilities.instance_of(r, XNodeSet)) {
2540 return r.compareWithNumber(this, Operators.greaterthan);
2542 if (Utilities.instance_of(r, XBoolean) || Utilities.instance_of(r, XString)) {
2543 return this.lessthanorequal(r.number());
2545 return new XBoolean(this.num <= r.num);
2548 XNumber.prototype.greaterthanorequal = function(r) {
2549 if (Utilities.instance_of(r, XNodeSet)) {
2550 return r.compareWithNumber(this, Operators.lessthan);
2552 if (Utilities.instance_of(r, XBoolean) || Utilities.instance_of(r, XString)) {
2553 return this.greaterthanorequal(r.number());
2555 return new XBoolean(this.num >= r.num);
2558 XNumber.prototype.plus = function(r) {
2559 return new XNumber(this.num + r.num);
2562 XNumber.prototype.minus = function(r) {
2563 return new XNumber(this.num - r.num);
2566 XNumber.prototype.multiply = function(r) {
2567 return new XNumber(this.num * r.num);
2570 XNumber.prototype.div = function(r) {
2571 return new XNumber(this.num / r.num);
2574 XNumber.prototype.mod = function(r) {
2575 return new XNumber(this.num % r.num);
2578 // XBoolean //////////////////////////////////////////////////////////////////
2580 XBoolean.prototype = new Expression();
2581 XBoolean.prototype.constructor = XBoolean;
2582 XBoolean.superclass = Expression.prototype;
2584 function XBoolean(b) {
2585 if (arguments.length > 0) {
2590 XBoolean.prototype.init = function(b) {
2591 this.b = Boolean(b);
2594 XBoolean.prototype.toString = function() {
2595 return this.b.toString();
2598 XBoolean.prototype.evaluate = function(c) {
2602 XBoolean.prototype.string = function() {
2603 return new XString(this.b);
2606 XBoolean.prototype.number = function() {
2607 return new XNumber(this.b);
2610 XBoolean.prototype.bool = function() {
2614 XBoolean.prototype.nodeset = function() {
2615 throw new Error("Cannot convert boolean to nodeset");
2618 XBoolean.prototype.stringValue = function() {
2619 return this.string().stringValue();
2622 XBoolean.prototype.numberValue = function() {
2623 return this.num().numberValue();
2626 XBoolean.prototype.booleanValue = function() {
2630 XBoolean.prototype.not = function() {
2631 return new XBoolean(!this.b);
2634 XBoolean.prototype.equals = function(r) {
2635 if (Utilities.instance_of(r, XString) || Utilities.instance_of(r, XNumber)) {
2636 return this.equals(r.bool());
2638 if (Utilities.instance_of(r, XNodeSet)) {
2639 return r.compareWithBoolean(this, Operators.equals);
2641 return new XBoolean(this.b == r.b);
2644 XBoolean.prototype.notequal = function(r) {
2645 if (Utilities.instance_of(r, XString) || Utilities.instance_of(r, XNumber)) {
2646 return this.notequal(r.bool());
2648 if (Utilities.instance_of(r, XNodeSet)) {
2649 return r.compareWithBoolean(this, Operators.notequal);
2651 return new XBoolean(this.b != r.b);
2654 XBoolean.prototype.lessthan = function(r) {
2655 if (Utilities.instance_of(r, XNodeSet)) {
2656 return r.compareWithNumber(this.number(), Operators.greaterthanorequal);
2658 return this.number().lessthan(r.number());
2661 XBoolean.prototype.greaterthan = function(r) {
2662 if (Utilities.instance_of(r, XNodeSet)) {
2663 return r.compareWithNumber(this.number(), Operators.lessthanorequal);
2665 return this.number().greaterthan(r.number());
2668 XBoolean.prototype.lessthanorequal = function(r) {
2669 if (Utilities.instance_of(r, XNodeSet)) {
2670 return r.compareWithNumber(this.number(), Operators.greaterthan);
2672 return this.number().lessthanorequal(r.number());
2675 XBoolean.prototype.greaterthanorequal = function(r) {
2676 if (Utilities.instance_of(r, XNodeSet)) {
2677 return r.compareWithNumber(this.number(), Operators.lessthan);
2679 return this.number().greaterthanorequal(r.number());
2682 // AVLTree ///////////////////////////////////////////////////////////////////
2684 AVLTree.prototype = new Object();
2685 AVLTree.prototype.constructor = AVLTree;
2686 AVLTree.superclass = Object.prototype;
2688 function AVLTree(n) {
2692 AVLTree.prototype.init = function(n) {
2699 AVLTree.prototype.balance = function() {
2700 var ldepth = this.left == null ? 0 : this.left.depth;
2701 var rdepth = this.right == null ? 0 : this.right.depth;
2703 if (ldepth > rdepth + 1) {
2704 // LR or LL rotation
2705 var lldepth = this.left.left == null ? 0 : this.left.left.depth;
2706 var lrdepth = this.left.right == null ? 0 : this.left.right.depth;
2708 if (lldepth < lrdepth) {
2709 // LR rotation consists of a RR rotation of the left child
2710 this.left.rotateRR();
2711 // plus a LL rotation of this node, which happens anyway
2714 } else if (ldepth + 1 < rdepth) {
2715 // RR or RL rorarion
2716 var rrdepth = this.right.right == null ? 0 : this.right.right.depth;
2717 var rldepth = this.right.left == null ? 0 : this.right.left.depth;
2719 if (rldepth > rrdepth) {
2720 // RR rotation consists of a LL rotation of the right child
2721 this.right.rotateLL();
2722 // plus a RR rotation of this node, which happens anyway
2728 AVLTree.prototype.rotateLL = function() {
2729 // the left side is too long => rotate from the left (_not_ leftwards)
2730 var nodeBefore = this.node;
2731 var rightBefore = this.right;
2732 this.node = this.left.node;
2733 this.right = this.left;
2734 this.left = this.left.left;
2735 this.right.left = this.right.right;
2736 this.right.right = rightBefore;
2737 this.right.node = nodeBefore;
2738 this.right.updateInNewLocation();
2739 this.updateInNewLocation();
2742 AVLTree.prototype.rotateRR = function() {
2743 // the right side is too long => rotate from the right (_not_ rightwards)
2744 var nodeBefore = this.node;
2745 var leftBefore = this.left;
2746 this.node = this.right.node;
2747 this.left = this.right;
2748 this.right = this.right.right;
2749 this.left.right = this.left.left;
2750 this.left.left = leftBefore;
2751 this.left.node = nodeBefore;
2752 this.left.updateInNewLocation();
2753 this.updateInNewLocation();
2756 AVLTree.prototype.updateInNewLocation = function() {
2757 this.getDepthFromChildren();
2760 AVLTree.prototype.getDepthFromChildren = function() {
2761 this.depth = this.node == null ? 0 : 1;
2762 if (this.left != null) {
2763 this.depth = this.left.depth + 1;
2765 if (this.right != null && this.depth <= this.right.depth) {
2766 this.depth = this.right.depth + 1;
2770 AVLTree.prototype.order = function(n1, n2) {
2776 for (var m1 = n1; m1 != null; m1 = m1.parentNode) {
2779 for (var m2 = n2; m2 != null; m2 = m2.parentNode) {
2790 } else if (d2 > d1) {
2799 while (n1.parentNode != n2.parentNode) {
2803 while (n1.previousSibling != null && n2.previousSibling != null) {
2804 n1 = n1.previousSibling;
2805 n2 = n2.previousSibling;
2807 if (n1.previousSibling == null) {
2813 AVLTree.prototype.add = function(n) {
2814 if (n === this.node) {
2818 var o = this.order(n, this.node);
2822 if (this.left == null) {
2823 this.left = new AVLTree(n);
2826 ret = this.left.add(n);
2831 } else if (o == 1) {
2832 if (this.right == null) {
2833 this.right = new AVLTree(n);
2836 ret = this.right.add(n);
2844 this.getDepthFromChildren();
2849 // XNodeSet //////////////////////////////////////////////////////////////////
2851 XNodeSet.prototype = new Expression();
2852 XNodeSet.prototype.constructor = XNodeSet;
2853 XNodeSet.superclass = Expression.prototype;
2855 function XNodeSet() {
2859 XNodeSet.prototype.init = function() {
2864 XNodeSet.prototype.toString = function() {
2865 var p = this.first();
2869 return this.stringForNode(p);
2872 XNodeSet.prototype.evaluate = function(c) {
2876 XNodeSet.prototype.string = function() {
2877 return new XString(this.toString());
2880 XNodeSet.prototype.stringValue = function() {
2881 return this.toString();
2884 XNodeSet.prototype.number = function() {
2885 return new XNumber(this.string());
2888 XNodeSet.prototype.numberValue = function() {
2889 return Number(this.string());
2892 XNodeSet.prototype.bool = function() {
2893 return new XBoolean(this.tree != null);
2896 XNodeSet.prototype.booleanValue = function() {
2897 return this.tree != null;
2900 XNodeSet.prototype.nodeset = function() {
2904 XNodeSet.prototype.stringForNode = function(n) {
2905 if (n.nodeType == 9 /*Node.DOCUMENT_NODE*/) {
2906 n = n.documentElement;
2908 if (n.nodeType == 1 /*Node.ELEMENT_NODE*/) {
2909 return this.stringForNodeRec(n);
2911 if (n.isNamespaceNode) {
2917 XNodeSet.prototype.stringForNodeRec = function(n) {
2919 for (var n2 = n.firstChild; n2 != null; n2 = n2.nextSibling) {
2920 if (n2.nodeType == 3 /*Node.TEXT_NODE*/) {
2922 } else if (n2.nodeType == 1 /*Node.ELEMENT_NODE*/) {
2923 s += this.stringForNodeRec(n2);
2929 XNodeSet.prototype.first = function() {
2934 while (p.left != null) {
2940 XNodeSet.prototype.add = function(n) {
2942 if (this.tree == null) {
2943 this.tree = new AVLTree(n);
2946 added = this.tree.add(n);
2953 XNodeSet.prototype.addArray = function(ns) {
2954 for (var i = 0; i < ns.length; i++) {
2959 XNodeSet.prototype.toArray = function() {
2961 this.toArrayRec(this.tree, a);
2965 XNodeSet.prototype.toArrayRec = function(t, a) {
2967 this.toArrayRec(t.left, a);
2969 this.toArrayRec(t.right, a);
2973 XNodeSet.prototype.compareWithString = function(r, o) {
2974 var a = this.toArray();
2975 for (var i = 0; i < a.length; i++) {
2977 var l = new XString(this.stringForNode(n));
2979 if (res.booleanValue()) {
2983 return new XBoolean(false);
2986 XNodeSet.prototype.compareWithNumber = function(r, o) {
2987 var a = this.toArray();
2988 for (var i = 0; i < a.length; i++) {
2990 var l = new XNumber(this.stringForNode(n));
2992 if (res.booleanValue()) {
2996 return new XBoolean(false);
2999 XNodeSet.prototype.compareWithBoolean = function(r, o) {
3000 return o(this.bool(), r);
3003 XNodeSet.prototype.compareWithNodeSet = function(r, o) {
3004 var a = this.toArray();
3005 for (var i = 0; i < a.length; i++) {
3007 var l = new XString(this.stringForNode(n));
3008 var b = r.toArray();
3009 for (var j = 0; j < b.length; j++) {
3011 var r = new XString(this.stringForNode(n2));
3013 if (res.booleanValue()) {
3018 return new XBoolean(false);
3021 XNodeSet.prototype.equals = function(r) {
3022 if (Utilities.instance_of(r, XString)) {
3023 return this.compareWithString(r, Operators.equals);
3025 if (Utilities.instance_of(r, XNumber)) {
3026 return this.compareWithNumber(r, Operators.equals);
3028 if (Utilities.instance_of(r, XBoolean)) {
3029 return this.compareWithBoolean(r, Operators.equals);
3031 return this.compareWithNodeSet(r, Operators.equals);
3034 XNodeSet.prototype.notequal = function(r) {
3035 if (Utilities.instance_of(r, XString)) {
3036 return this.compareWithString(r, Operators.notequal);
3038 if (Utilities.instance_of(r, XNumber)) {
3039 return this.compareWithNumber(r, Operators.notequal);
3041 if (Utilities.instance_of(r, XBoolean)) {
3042 return this.compareWithBoolean(r, Operators.notequal);
3044 return this.compareWithNodeSet(r, Operators.notequal);
3047 XNodeSet.prototype.lessthan = function(r) {
3048 if (Utilities.instance_of(r, XString)) {
3049 return this.compareWithNumber(r.number(), Operators.lessthan);
3051 if (Utilities.instance_of(r, XNumber)) {
3052 return this.compareWithNumber(r, Operators.lessthan);
3054 if (Utilities.instance_of(r, XBoolean)) {
3055 return this.compareWithBoolean(r, Operators.lessthan);
3057 return this.compareWithNodeSet(r, Operators.lessthan);
3060 XNodeSet.prototype.greaterthan = function(r) {
3061 if (Utilities.instance_of(r, XString)) {
3062 return this.compareWithNumber(r.number(), Operators.greaterthan);
3064 if (Utilities.instance_of(r, XNumber)) {
3065 return this.compareWithNumber(r, Operators.greaterthan);
3067 if (Utilities.instance_of(r, XBoolean)) {
3068 return this.compareWithBoolean(r, Operators.greaterthan);
3070 return this.compareWithNodeSet(r, Operators.greaterthan);
3073 XNodeSet.prototype.lessthanorequal = function(r) {
3074 if (Utilities.instance_of(r, XString)) {
3075 return this.compareWithNumber(r.number(), Operators.lessthanorequal);
3077 if (Utilities.instance_of(r, XNumber)) {
3078 return this.compareWithNumber(r, Operators.lessthanorequal);
3080 if (Utilities.instance_of(r, XBoolean)) {
3081 return this.compareWithBoolean(r, Operators.lessthanorequal);
3083 return this.compareWithNodeSet(r, Operators.lessthanorequal);
3086 XNodeSet.prototype.greaterthanorequal = function(r) {
3087 if (Utilities.instance_of(r, XString)) {
3088 return this.compareWithNumber(r.number(), Operators.greaterthanorequal);
3090 if (Utilities.instance_of(r, XNumber)) {
3091 return this.compareWithNumber(r, Operators.greaterthanorequal);
3093 if (Utilities.instance_of(r, XBoolean)) {
3094 return this.compareWithBoolean(r, Operators.greaterthanorequal);
3096 return this.compareWithNodeSet(r, Operators.greaterthanorequal);
3099 XNodeSet.prototype.union = function(r) {
3100 var ns = new XNodeSet();
3101 ns.tree = this.tree;
3102 ns.size = this.size;
3103 ns.addArray(r.toArray());
3107 // XPathNamespace ////////////////////////////////////////////////////////////
3109 XPathNamespace.prototype = new Object();
3110 XPathNamespace.prototype.constructor = XPathNamespace;
3111 XPathNamespace.superclass = Object.prototype;
3113 function XPathNamespace(pre, ns, p) {
3114 this.isXPathNamespace = true;
3115 this.ownerDocument = p.ownerDocument;
3116 this.nodeName = "#namespace";
3118 this.localName = pre;
3119 this.namespaceURI = ns;
3120 this.nodeValue = ns;
3121 this.ownerElement = p;
3122 this.nodeType = XPathNamespace.XPATH_NAMESPACE_NODE;
3125 XPathNamespace.prototype.toString = function() {
3126 return "{ \"" + this.prefix + "\", \"" + this.namespaceURI + "\" }";
3129 // Operators /////////////////////////////////////////////////////////////////
3131 var Operators = new Object();
3133 Operators.equals = function(l, r) {
3137 Operators.notequal = function(l, r) {
3138 return l.notequal(r);
3141 Operators.lessthan = function(l, r) {
3142 return l.lessthan(r);
3145 Operators.greaterthan = function(l, r) {
3146 return l.greaterthan(r);
3149 Operators.lessthanorequal = function(l, r) {
3150 return l.lessthanorequal(r);
3153 Operators.greaterthanorequal = function(l, r) {
3154 return l.greaterthanorequal(r);
3157 // XPathContext //////////////////////////////////////////////////////////////
3159 XPathContext.prototype = new Object();
3160 XPathContext.prototype.constructor = XPathContext;
3161 XPathContext.superclass = Object.prototype;
3163 function XPathContext(vr, nr, fr) {
3164 this.variableResolver = vr != null ? vr : new VariableResolver();
3165 this.namespaceResolver = nr != null ? nr : new NamespaceResolver();
3166 this.functionResolver = fr != null ? fr : new FunctionResolver();
3169 // VariableResolver //////////////////////////////////////////////////////////
3171 VariableResolver.prototype = new Object();
3172 VariableResolver.prototype.constructor = VariableResolver;
3173 VariableResolver.superclass = Object.prototype;
3175 function VariableResolver() {
3178 VariableResolver.prototype.getVariable = function(vn, c) {
3179 var parts = Utilities.splitQName(vn);
3180 if (parts[0] != null) {
3181 parts[0] = c.namespaceResolver.getNamespace(parts[0], c.expressionContextNode);
3182 if (parts[0] == null) {
3183 throw new Error("Cannot resolve QName " + fn);
3186 return this.getVariableWithName(parts[0], parts[1], c.expressionContextNode);
3189 VariableResolver.prototype.getVariableWithName = function(ns, ln, c) {
3193 // FunctionResolver //////////////////////////////////////////////////////////
3195 FunctionResolver.prototype = new Object();
3196 FunctionResolver.prototype.constructor = FunctionResolver;
3197 FunctionResolver.superclass = Object.prototype;
3199 function FunctionResolver(thisArg) {
3200 this.thisArg = thisArg != null ? thisArg : Functions;
3201 this.functions = new Object();
3202 this.addStandardFunctions();
3205 FunctionResolver.prototype.addStandardFunctions = function() {
3206 this.functions["{}last"] = Functions.last;
3207 this.functions["{}position"] = Functions.position;
3208 this.functions["{}count"] = Functions.count;
3209 this.functions["{}id"] = Functions.id;
3210 this.functions["{}local-name"] = Functions.localName;
3211 this.functions["{}namespace-uri"] = Functions.namespaceURI;
3212 this.functions["{}name"] = Functions.name;
3213 this.functions["{}string"] = Functions.string;
3214 this.functions["{}concat"] = Functions.concat;
3215 this.functions["{}starts-with"] = Functions.startsWith;
3216 this.functions["{}contains"] = Functions.contains;
3217 this.functions["{}substring-before"] = Functions.substringBefore;
3218 this.functions["{}substring-after"] = Functions.substringAfter;
3219 this.functions["{}substring"] = Functions.substring;
3220 this.functions["{}string-length"] = Functions.stringLength;
3221 this.functions["{}normalize-space"] = Functions.normalizeSpace;
3222 this.functions["{}translate"] = Functions.translate;
3223 this.functions["{}boolean"] = Functions.boolean_;
3224 this.functions["{}not"] = Functions.not;
3225 this.functions["{}true"] = Functions.true_;
3226 this.functions["{}false"] = Functions.false_;
3227 this.functions["{}lang"] = Functions.lang;
3228 this.functions["{}number"] = Functions.number;
3229 this.functions["{}sum"] = Functions.sum;
3230 this.functions["{}floor"] = Functions.floor;
3231 this.functions["{}ceiling"] = Functions.ceiling;
3232 this.functions["{}round"] = Functions.round;
3235 FunctionResolver.prototype.addFunction = function(ns, ln, f) {
3236 this.functions["{" + ns + "}" + ln] = f;
3239 FunctionResolver.prototype.getFunction = function(fn, c) {
3240 var parts = Utilities.resolveQName(fn, c.namespaceResolver, c.contextNode, false);
3241 if (parts[0] == null) {
3242 throw new Error("Cannot resolve QName " + fn);
3244 return this.getFunctionWithName(parts[0], parts[1], c.contextNode);
3247 FunctionResolver.prototype.getFunctionWithName = function(ns, ln, c) {
3248 return this.functions["{" + ns + "}" + ln];
3251 // NamespaceResolver /////////////////////////////////////////////////////////
3253 NamespaceResolver.prototype = new Object();
3254 NamespaceResolver.prototype.constructor = NamespaceResolver;
3255 NamespaceResolver.superclass = Object.prototype;
3257 function NamespaceResolver() {
3260 NamespaceResolver.prototype.getNamespace = function(prefix, n) {
3261 if (prefix == "xml") {
3262 return XPath.XML_NAMESPACE_URI;
3263 } else if (prefix == "xmlns") {
3264 return XPath.XMLNS_NAMESPACE_URI;
3266 if (n.nodeType == 9 /*Node.DOCUMENT_NODE*/) {
3267 n = n.documentElement;
3268 } else if (n.nodeType == 2 /*Node.ATTRIBUTE_NODE*/) {
3269 n = PathExpr.prototype.getOwnerElement(n);
3270 } else if (n.nodeType != 1 /*Node.ELEMENT_NODE*/) {
3273 while (n != null && n.nodeType == 1 /*Node.ELEMENT_NODE*/) {
3274 var nnm = n.attributes;
3275 for (var i = 0; i < nnm.length; i++) {
3276 var a = nnm.item(i);
3277 var aname = a.nodeName;
3278 if (aname == "xmlns" && prefix == ""
3279 || aname == "xmlns:" + prefix) {
3280 return String(a.nodeValue);
3288 // Functions /////////////////////////////////////////////////////////////////
3290 Functions = new Object();
3292 Functions.last = function() {
3293 var c = arguments[0];
3294 if (arguments.length != 1) {
3295 throw new Error("Function last expects ()");
3297 return new XNumber(c.contextSize);
3300 Functions.position = function() {
3301 var c = arguments[0];
3302 if (arguments.length != 1) {
3303 throw new Error("Function position expects ()");
3305 return new XNumber(c.contextPosition);
3308 Functions.count = function() {
3309 var c = arguments[0];
3311 if (arguments.length != 2 || !Utilities.instance_of(ns = arguments[1].evaluate(c), XNodeSet)) {
3312 throw new Error("Function count expects (node-set)");
3314 return new XNumber(ns.size);
3317 Functions.id = function() {
3318 var c = arguments[0];
3320 if (arguments.length != 2) {
3321 throw new Error("Function id expects (object)");
3323 id = arguments[1].evaluate(c);
3324 if (Utilities.instance_of(id, XNodeSet)) {
3325 id = id.toArray().join(" ");
3327 id = id.stringValue();
3329 var ids = id.split(/[\x0d\x0a\x09\x20]+/);
3331 var ns = new XNodeSet();
3332 var doc = c.contextNode.nodeType == 9 /*Node.DOCUMENT_NODE*/
3334 : c.contextNode.ownerDocument;
3335 for (var i = 0; i < ids.length; i++) {
3337 if (doc.getElementById) {
3338 n = doc.getElementById(ids[i]);
3340 n = Utilities.getElementById(doc, ids[i]);
3350 Functions.localName = function() {
3351 var c = arguments[0];
3353 if (arguments.length == 1) {
3355 } else if (arguments.length == 2) {
3356 n = arguments[1].evaluate(c).first();
3358 throw new Error("Function local-name expects (node-set?)");
3361 return new XString("");
3363 return new XString(n.localName ? n.localName : n.baseName);
3366 Functions.namespaceURI = function() {
3367 var c = arguments[0];
3369 if (arguments.length == 1) {
3371 } else if (arguments.length == 2) {
3372 n = arguments[1].evaluate(c).first();
3374 throw new Error("Function namespace-uri expects (node-set?)");
3377 return new XString("");
3379 return new XString(n.namespaceURI);
3382 Functions.name = function() {
3383 var c = arguments[0];
3385 if (arguments.length == 1) {
3387 } else if (arguments.length == 2) {
3388 n = arguments[1].evaluate(c).first();
3390 throw new Error("Function name expects (node-set?)");
3393 return new XString("");
3395 if (n.nodeType == 1 /*Node.ELEMENT_NODE*/ || n.nodeType == 2 /*Node.ATTRIBUTE_NODE*/) {
3396 return new XString(n.nodeName);
3397 } else if (n.localName == null) {
3398 return new XString("");
3400 return new XString(n.localName);
3404 Functions.string = function() {
3405 var c = arguments[0];
3406 if (arguments.length == 1) {
3407 return XNodeSet.prototype.stringForNode(c.contextNode);
3408 } else if (arguments.length == 2) {
3409 return arguments[1].evaluate(c).string();
3411 throw new Error("Function string expects (object?)");
3414 Functions.concat = function() {
3415 var c = arguments[0];
3416 if (arguments.length < 3) {
3417 throw new Error("Function concat expects (string, string, string*)");
3420 for (var i = 1; i < arguments.length; i++) {
3421 s += arguments[i].evaluate(c).stringValue();
3423 return new XString(s);
3426 Functions.startsWith = function() {
3427 var c = arguments[0];
3428 if (arguments.length != 3) {
3429 throw new Error("Function startsWith expects (string, string)");
3431 var s1 = arguments[1].evaluate(c).stringValue();
3432 var s2 = arguments[2].evaluate(c).stringValue();
3433 return new XBoolean(s1.substring(0, s2.length) == s2);
3436 Functions.contains = function() {
3437 var c = arguments[0];
3438 if (arguments.length != 3) {
3439 throw new Error("Function contains expects (string, string)");
3441 var s1 = arguments[1].evaluate(c).stringValue();
3442 var s2 = arguments[2].evaluate(c).stringValue();
3443 return new XBoolean(s1.indexOf(s2) != -1);
3446 Functions.substringBefore = function() {
3447 var c = arguments[0];
3448 if (arguments.length != 3) {
3449 throw new Error("Function substring-before expects (string, string)");
3451 var s1 = arguments[1].evaluate(c).stringValue();
3452 var s2 = arguments[2].evaluate(c).stringValue();
3453 return new XString(s1.substring(0, s1.indexOf(s2)));
3456 Functions.substringAfter = function() {
3457 var c = arguments[0];
3458 if (arguments.length != 3) {
3459 throw new Error("Function substring-after expects (string, string)");
3461 var s1 = arguments[1].evaluate(c).stringValue();
3462 var s2 = arguments[2].evaluate(c).stringValue();
3463 if (s2.length == 0) {
3464 return new XString(s1);
3466 var i = s1.indexOf(s2);
3468 return new XString("");
3470 return new XString(s1.substring(s1.indexOf(s2) + 1));
3473 Functions.substring = function() {
3474 var c = arguments[0];
3475 if (!(arguments.length == 3 || arguments.length == 4)) {
3476 throw new Error("Function substring expects (string, number, number?)");
3478 var s = arguments[1].evaluate(c).stringValue();
3479 var n1 = Math.round(arguments[2].evaluate(c).numberValue()) - 1;
3480 var n2 = arguments.length == 4 ? n1 + Math.round(arguments[3].evaluate(c).numberValue()) : undefined;
3481 return new XString(s.substring(n1, n2));
3484 Functions.stringLength = function() {
3485 var c = arguments[0];
3487 if (arguments.length == 1) {
3488 s = XNodeSet.prototype.stringForNode(c.contextNode);
3489 } else if (arguments.length == 2) {
3490 s = arguments[1].evaluate(c).stringValue();
3492 throw new Error("Function string-length expects (string?)");
3494 return new XNumber(s.length);
3497 Functions.normalizeSpace = function() {
3498 var c = arguments[0];
3500 if (arguments.length == 1) {
3501 s = XNodeSet.prototype.stringForNode(c.contextNode);
3502 } else if (arguments.length == 2) {
3503 s = arguments[1].evaluate(c).stringValue();
3505 throw new Error("Function normalize-space expects (string?)");
3508 var j = s.length - 1;
3509 while (Utilities.isSpace(s.charCodeAt(j))) {
3513 while (i <= j && Utilities.isSpace(s.charCodeAt(i))) {
3517 if (Utilities.isSpace(s.charCodeAt(i))) {
3519 while (i <= j && Utilities.isSpace(s.charCodeAt(i))) {
3527 return new XString(t);
3530 Functions.translate = function() {
3531 var c = arguments[0];
3532 if (arguments.length != 4) {
3533 throw new Error("Function translate expects (string, string, string)");
3535 var s1 = arguments[1].evaluate(c).stringValue();
3536 var s2 = arguments[2].evaluate(c).stringValue();
3537 var s3 = arguments[3].evaluate(c).stringValue();
3539 for (var i = 0; i < s2.length; i++) {
3540 var j = s2.charCodeAt(i);
3541 if (map[j] == undefined) {
3542 var k = i > s3.length ? "" : s3.charAt(i);
3547 for (var i = 0; i < s1.length; i++) {
3548 var c = s1.charCodeAt(i);
3550 if (r == undefined) {
3556 return new XString(t);
3559 Functions.boolean_ = function() {
3560 var c = arguments[0];
3561 if (arguments.length != 2) {
3562 throw new Error("Function boolean expects (object)");
3564 return arguments[1].evaluate(c).bool();
3567 Functions.not = function() {
3568 var c = arguments[0];
3569 if (arguments.length != 2) {
3570 throw new Error("Function not expects (object)");
3572 return arguments[1].evaluate(c).bool().not();
3575 Functions.true_ = function() {
3576 if (arguments.length != 1) {
3577 throw new Error("Function true expects ()");
3579 return new XBoolean(true);
3582 Functions.false_ = function() {
3583 if (arguments.length != 1) {
3584 throw new Error("Function false expects ()");
3586 return new XBoolean(false);
3589 Functions.lang = function() {
3590 var c = arguments[0];
3591 if (arguments.length != 2) {
3592 throw new Error("Function lang expects (string)");
3595 for (var n = c.contextNode; n != null && n.nodeType != 9 /*Node.DOCUMENT_NODE*/; n = n.parentNode) {
3596 var a = n.getAttributeNS(XPath.XML_NAMESPACE_URI, "lang");
3603 return new XBoolean(false);
3605 var s = arguments[1].evaluate(c).stringValue();
3606 return new XBoolean(lang.substring(0, s.length) == s
3607 && (lang.length == s.length || lang.charAt(s.length) == '-'));
3610 Functions.number = function() {
3611 var c = arguments[0];
3612 if (!(arguments.length == 1 || arguments.length == 2)) {
3613 throw new Error("Function number expects (object?)");
3615 if (arguments.length == 1) {
3616 return new XNumber(XNodeSet.prototype.stringForNode(c.contextNode));
3618 return arguments[1].evaluate(c).number();
3621 Functions.sum = function() {
3622 var c = arguments[0];
3624 if (arguments.length != 2 || !Utilities.instance_of((ns = arguments[1].evaluate(c)), XNodeSet)) {
3625 throw new Error("Function sum expects (node-set)");
3629 for (var i = 0; i < ns.length; i++) {
3630 n += new XNumber(XNodeSet.prototype.stringForNode(ns[i])).numberValue();
3632 return new XNumber(n);
3635 Functions.floor = function() {
3636 var c = arguments[0];
3637 if (arguments.length != 2) {
3638 throw new Error("Function floor expects (number)");
3640 return new XNumber(Math.floor(arguments[1].evaluate(c).numberValue()));
3643 Functions.ceiling = function() {
3644 var c = arguments[0];
3645 if (arguments.length != 2) {
3646 throw new Error("Function ceiling expects (number)");
3648 return new XNumber(Math.ceil(arguments[1].evaluate(c).numberValue()));
3651 Functions.round = function() {
3652 var c = arguments[0];
3653 if (arguments.length != 2) {
3654 throw new Error("Function round expects (number)");
3656 return new XNumber(Math.round(arguments[1].evaluate(c).numberValue()));
3659 // Utilities /////////////////////////////////////////////////////////////////
3661 Utilities = new Object();
3663 Utilities.splitQName = function(qn) {
3664 var i = qn.indexOf(":");
3666 return [ null, qn ];
3668 return [ qn.substring(0, i), qn.substring(i + 1) ];
3671 Utilities.resolveQName = function(qn, nr, n, useDefault) {
3672 var parts = Utilities.splitQName(qn);
3673 if (parts[0] != null) {
3674 parts[0] = nr.getNamespace(parts[0], n);
3677 parts[0] = nr.getNamespace("", n);
3678 if (parts[0] == null) {
3688 Utilities.isSpace = function(c) {
3689 return c == 0x9 || c == 0xd || c == 0xa || c == 0x20;
3692 Utilities.isLetter = function(c) {
3693 return c >= 0x0041 && c <= 0x005A ||
3694 c >= 0x0061 && c <= 0x007A ||
3695 c >= 0x00C0 && c <= 0x00D6 ||
3696 c >= 0x00D8 && c <= 0x00F6 ||
3697 c >= 0x00F8 && c <= 0x00FF ||
3698 c >= 0x0100 && c <= 0x0131 ||
3699 c >= 0x0134 && c <= 0x013E ||
3700 c >= 0x0141 && c <= 0x0148 ||
3701 c >= 0x014A && c <= 0x017E ||
3702 c >= 0x0180 && c <= 0x01C3 ||
3703 c >= 0x01CD && c <= 0x01F0 ||
3704 c >= 0x01F4 && c <= 0x01F5 ||
3705 c >= 0x01FA && c <= 0x0217 ||
3706 c >= 0x0250 && c <= 0x02A8 ||
3707 c >= 0x02BB && c <= 0x02C1 ||
3709 c >= 0x0388 && c <= 0x038A ||
3711 c >= 0x038E && c <= 0x03A1 ||
3712 c >= 0x03A3 && c <= 0x03CE ||
3713 c >= 0x03D0 && c <= 0x03D6 ||
3718 c >= 0x03E2 && c <= 0x03F3 ||
3719 c >= 0x0401 && c <= 0x040C ||
3720 c >= 0x040E && c <= 0x044F ||
3721 c >= 0x0451 && c <= 0x045C ||
3722 c >= 0x045E && c <= 0x0481 ||
3723 c >= 0x0490 && c <= 0x04C4 ||
3724 c >= 0x04C7 && c <= 0x04C8 ||
3725 c >= 0x04CB && c <= 0x04CC ||
3726 c >= 0x04D0 && c <= 0x04EB ||
3727 c >= 0x04EE && c <= 0x04F5 ||
3728 c >= 0x04F8 && c <= 0x04F9 ||
3729 c >= 0x0531 && c <= 0x0556 ||
3731 c >= 0x0561 && c <= 0x0586 ||
3732 c >= 0x05D0 && c <= 0x05EA ||
3733 c >= 0x05F0 && c <= 0x05F2 ||
3734 c >= 0x0621 && c <= 0x063A ||
3735 c >= 0x0641 && c <= 0x064A ||
3736 c >= 0x0671 && c <= 0x06B7 ||
3737 c >= 0x06BA && c <= 0x06BE ||
3738 c >= 0x06C0 && c <= 0x06CE ||
3739 c >= 0x06D0 && c <= 0x06D3 ||
3741 c >= 0x06E5 && c <= 0x06E6 ||
3742 c >= 0x0905 && c <= 0x0939 ||
3744 c >= 0x0958 && c <= 0x0961 ||
3745 c >= 0x0985 && c <= 0x098C ||
3746 c >= 0x098F && c <= 0x0990 ||
3747 c >= 0x0993 && c <= 0x09A8 ||
3748 c >= 0x09AA && c <= 0x09B0 ||
3750 c >= 0x09B6 && c <= 0x09B9 ||
3751 c >= 0x09DC && c <= 0x09DD ||
3752 c >= 0x09DF && c <= 0x09E1 ||
3753 c >= 0x09F0 && c <= 0x09F1 ||
3754 c >= 0x0A05 && c <= 0x0A0A ||
3755 c >= 0x0A0F && c <= 0x0A10 ||
3756 c >= 0x0A13 && c <= 0x0A28 ||
3757 c >= 0x0A2A && c <= 0x0A30 ||
3758 c >= 0x0A32 && c <= 0x0A33 ||
3759 c >= 0x0A35 && c <= 0x0A36 ||
3760 c >= 0x0A38 && c <= 0x0A39 ||
3761 c >= 0x0A59 && c <= 0x0A5C ||
3763 c >= 0x0A72 && c <= 0x0A74 ||
3764 c >= 0x0A85 && c <= 0x0A8B ||
3766 c >= 0x0A8F && c <= 0x0A91 ||
3767 c >= 0x0A93 && c <= 0x0AA8 ||
3768 c >= 0x0AAA && c <= 0x0AB0 ||
3769 c >= 0x0AB2 && c <= 0x0AB3 ||
3770 c >= 0x0AB5 && c <= 0x0AB9 ||
3773 c >= 0x0B05 && c <= 0x0B0C ||
3774 c >= 0x0B0F && c <= 0x0B10 ||
3775 c >= 0x0B13 && c <= 0x0B28 ||
3776 c >= 0x0B2A && c <= 0x0B30 ||
3777 c >= 0x0B32 && c <= 0x0B33 ||
3778 c >= 0x0B36 && c <= 0x0B39 ||
3780 c >= 0x0B5C && c <= 0x0B5D ||
3781 c >= 0x0B5F && c <= 0x0B61 ||
3782 c >= 0x0B85 && c <= 0x0B8A ||
3783 c >= 0x0B8E && c <= 0x0B90 ||
3784 c >= 0x0B92 && c <= 0x0B95 ||
3785 c >= 0x0B99 && c <= 0x0B9A ||
3787 c >= 0x0B9E && c <= 0x0B9F ||
3788 c >= 0x0BA3 && c <= 0x0BA4 ||
3789 c >= 0x0BA8 && c <= 0x0BAA ||
3790 c >= 0x0BAE && c <= 0x0BB5 ||
3791 c >= 0x0BB7 && c <= 0x0BB9 ||
3792 c >= 0x0C05 && c <= 0x0C0C ||
3793 c >= 0x0C0E && c <= 0x0C10 ||
3794 c >= 0x0C12 && c <= 0x0C28 ||
3795 c >= 0x0C2A && c <= 0x0C33 ||
3796 c >= 0x0C35 && c <= 0x0C39 ||
3797 c >= 0x0C60 && c <= 0x0C61 ||
3798 c >= 0x0C85 && c <= 0x0C8C ||
3799 c >= 0x0C8E && c <= 0x0C90 ||
3800 c >= 0x0C92 && c <= 0x0CA8 ||
3801 c >= 0x0CAA && c <= 0x0CB3 ||
3802 c >= 0x0CB5 && c <= 0x0CB9 ||
3804 c >= 0x0CE0 && c <= 0x0CE1 ||
3805 c >= 0x0D05 && c <= 0x0D0C ||
3806 c >= 0x0D0E && c <= 0x0D10 ||
3807 c >= 0x0D12 && c <= 0x0D28 ||
3808 c >= 0x0D2A && c <= 0x0D39 ||
3809 c >= 0x0D60 && c <= 0x0D61 ||
3810 c >= 0x0E01 && c <= 0x0E2E ||
3812 c >= 0x0E32 && c <= 0x0E33 ||
3813 c >= 0x0E40 && c <= 0x0E45 ||
3814 c >= 0x0E81 && c <= 0x0E82 ||
3816 c >= 0x0E87 && c <= 0x0E88 ||
3819 c >= 0x0E94 && c <= 0x0E97 ||
3820 c >= 0x0E99 && c <= 0x0E9F ||
3821 c >= 0x0EA1 && c <= 0x0EA3 ||
3824 c >= 0x0EAA && c <= 0x0EAB ||
3825 c >= 0x0EAD && c <= 0x0EAE ||
3827 c >= 0x0EB2 && c <= 0x0EB3 ||
3829 c >= 0x0EC0 && c <= 0x0EC4 ||
3830 c >= 0x0F40 && c <= 0x0F47 ||
3831 c >= 0x0F49 && c <= 0x0F69 ||
3832 c >= 0x10A0 && c <= 0x10C5 ||
3833 c >= 0x10D0 && c <= 0x10F6 ||
3835 c >= 0x1102 && c <= 0x1103 ||
3836 c >= 0x1105 && c <= 0x1107 ||
3838 c >= 0x110B && c <= 0x110C ||
3839 c >= 0x110E && c <= 0x1112 ||
3846 c >= 0x1154 && c <= 0x1155 ||
3848 c >= 0x115F && c <= 0x1161 ||
3853 c >= 0x116D && c <= 0x116E ||
3854 c >= 0x1172 && c <= 0x1173 ||
3859 c >= 0x11AE && c <= 0x11AF ||
3860 c >= 0x11B7 && c <= 0x11B8 ||
3862 c >= 0x11BC && c <= 0x11C2 ||
3866 c >= 0x1E00 && c <= 0x1E9B ||
3867 c >= 0x1EA0 && c <= 0x1EF9 ||
3868 c >= 0x1F00 && c <= 0x1F15 ||
3869 c >= 0x1F18 && c <= 0x1F1D ||
3870 c >= 0x1F20 && c <= 0x1F45 ||
3871 c >= 0x1F48 && c <= 0x1F4D ||
3872 c >= 0x1F50 && c <= 0x1F57 ||
3876 c >= 0x1F5F && c <= 0x1F7D ||
3877 c >= 0x1F80 && c <= 0x1FB4 ||
3878 c >= 0x1FB6 && c <= 0x1FBC ||
3880 c >= 0x1FC2 && c <= 0x1FC4 ||
3881 c >= 0x1FC6 && c <= 0x1FCC ||
3882 c >= 0x1FD0 && c <= 0x1FD3 ||
3883 c >= 0x1FD6 && c <= 0x1FDB ||
3884 c >= 0x1FE0 && c <= 0x1FEC ||
3885 c >= 0x1FF2 && c <= 0x1FF4 ||
3886 c >= 0x1FF6 && c <= 0x1FFC ||
3888 c >= 0x212A && c <= 0x212B ||
3890 c >= 0x2180 && c <= 0x2182 ||
3891 c >= 0x3041 && c <= 0x3094 ||
3892 c >= 0x30A1 && c <= 0x30FA ||
3893 c >= 0x3105 && c <= 0x312C ||
3894 c >= 0xAC00 && c <= 0xD7A3 ||
3895 c >= 0x4E00 && c <= 0x9FA5 ||
3897 c >= 0x3021 && c <= 0x3029;
3900 Utilities.isNCNameChar = function(c) {
3901 return c >= 0x0030 && c <= 0x0039
3902 || c >= 0x0660 && c <= 0x0669
3903 || c >= 0x06F0 && c <= 0x06F9
3904 || c >= 0x0966 && c <= 0x096F
3905 || c >= 0x09E6 && c <= 0x09EF
3906 || c >= 0x0A66 && c <= 0x0A6F
3907 || c >= 0x0AE6 && c <= 0x0AEF
3908 || c >= 0x0B66 && c <= 0x0B6F
3909 || c >= 0x0BE7 && c <= 0x0BEF
3910 || c >= 0x0C66 && c <= 0x0C6F
3911 || c >= 0x0CE6 && c <= 0x0CEF
3912 || c >= 0x0D66 && c <= 0x0D6F
3913 || c >= 0x0E50 && c <= 0x0E59
3914 || c >= 0x0ED0 && c <= 0x0ED9
3915 || c >= 0x0F20 && c <= 0x0F29
3919 || Utilities.isLetter(c)
3920 || c >= 0x0300 && c <= 0x0345
3921 || c >= 0x0360 && c <= 0x0361
3922 || c >= 0x0483 && c <= 0x0486
3923 || c >= 0x0591 && c <= 0x05A1
3924 || c >= 0x05A3 && c <= 0x05B9
3925 || c >= 0x05BB && c <= 0x05BD
3927 || c >= 0x05C1 && c <= 0x05C2
3929 || c >= 0x064B && c <= 0x0652
3931 || c >= 0x06D6 && c <= 0x06DC
3932 || c >= 0x06DD && c <= 0x06DF
3933 || c >= 0x06E0 && c <= 0x06E4
3934 || c >= 0x06E7 && c <= 0x06E8
3935 || c >= 0x06EA && c <= 0x06ED
3936 || c >= 0x0901 && c <= 0x0903
3938 || c >= 0x093E && c <= 0x094C
3940 || c >= 0x0951 && c <= 0x0954
3941 || c >= 0x0962 && c <= 0x0963
3942 || c >= 0x0981 && c <= 0x0983
3946 || c >= 0x09C0 && c <= 0x09C4
3947 || c >= 0x09C7 && c <= 0x09C8
3948 || c >= 0x09CB && c <= 0x09CD
3950 || c >= 0x09E2 && c <= 0x09E3
3955 || c >= 0x0A40 && c <= 0x0A42
3956 || c >= 0x0A47 && c <= 0x0A48
3957 || c >= 0x0A4B && c <= 0x0A4D
3958 || c >= 0x0A70 && c <= 0x0A71
3959 || c >= 0x0A81 && c <= 0x0A83
3961 || c >= 0x0ABE && c <= 0x0AC5
3962 || c >= 0x0AC7 && c <= 0x0AC9
3963 || c >= 0x0ACB && c <= 0x0ACD
3964 || c >= 0x0B01 && c <= 0x0B03
3966 || c >= 0x0B3E && c <= 0x0B43
3967 || c >= 0x0B47 && c <= 0x0B48
3968 || c >= 0x0B4B && c <= 0x0B4D
3969 || c >= 0x0B56 && c <= 0x0B57
3970 || c >= 0x0B82 && c <= 0x0B83
3971 || c >= 0x0BBE && c <= 0x0BC2
3972 || c >= 0x0BC6 && c <= 0x0BC8
3973 || c >= 0x0BCA && c <= 0x0BCD
3975 || c >= 0x0C01 && c <= 0x0C03
3976 || c >= 0x0C3E && c <= 0x0C44
3977 || c >= 0x0C46 && c <= 0x0C48
3978 || c >= 0x0C4A && c <= 0x0C4D
3979 || c >= 0x0C55 && c <= 0x0C56
3980 || c >= 0x0C82 && c <= 0x0C83
3981 || c >= 0x0CBE && c <= 0x0CC4
3982 || c >= 0x0CC6 && c <= 0x0CC8
3983 || c >= 0x0CCA && c <= 0x0CCD
3984 || c >= 0x0CD5 && c <= 0x0CD6
3985 || c >= 0x0D02 && c <= 0x0D03
3986 || c >= 0x0D3E && c <= 0x0D43
3987 || c >= 0x0D46 && c <= 0x0D48
3988 || c >= 0x0D4A && c <= 0x0D4D
3991 || c >= 0x0E34 && c <= 0x0E3A
3992 || c >= 0x0E47 && c <= 0x0E4E
3994 || c >= 0x0EB4 && c <= 0x0EB9
3995 || c >= 0x0EBB && c <= 0x0EBC
3996 || c >= 0x0EC8 && c <= 0x0ECD
3997 || c >= 0x0F18 && c <= 0x0F19
4003 || c >= 0x0F71 && c <= 0x0F84
4004 || c >= 0x0F86 && c <= 0x0F8B
4005 || c >= 0x0F90 && c <= 0x0F95
4007 || c >= 0x0F99 && c <= 0x0FAD
4008 || c >= 0x0FB1 && c <= 0x0FB7
4010 || c >= 0x20D0 && c <= 0x20DC
4012 || c >= 0x302A && c <= 0x302F
4023 || c >= 0x3031 && c <= 0x3035
4024 || c >= 0x309D && c <= 0x309E
4025 || c >= 0x30FC && c <= 0x30FE;
4028 Utilities.coalesceText = function(n) {
4029 for (var m = n.firstChild; m != null; m = m.nextSibling) {
4030 if (m.nodeType == 3 /*Node.TEXT_NODE*/ || m.nodeType == 4 /*Node.CDATA_SECTION_NODE*/) {
4031 var s = m.nodeValue;
4034 while (m != null && (m.nodeType == 3 /*Node.TEXT_NODE*/ || m.nodeType == 4 /*Node.CDATA_SECTION_NODE*/)) {
4038 del.parentNode.removeChild(del);
4040 if (first.nodeType == 4 /*Node.CDATA_SECTION_NODE*/) {
4041 var p = first.parentNode;
4042 if (first.nextSibling == null) {
4043 p.removeChild(first);
4044 p.appendChild(p.ownerDocument.createTextNode(s));
4046 var next = first.nextSibling;
4047 p.removeChild(first);
4048 p.insertBefore(p.ownerDocument.createTextNode(s), next);
4051 first.nodeValue = s;
4056 } else if (m.nodeType == 1 /*Node.ELEMENT_NODE*/) {
4057 Utilities.coalesceText(m);
4062 Utilities.instance_of = function(o, c) {
4064 if (o.constructor === c) {
4070 o = o.constructor.superclass;
4075 Utilities.getElementById = function(n, id) {
4076 // Note that this does not check the DTD to check for actual
4077 // attributes of type ID, so this may be a bit wrong.
4078 if (n.nodeType == 1 /*Node.ELEMENT_NODE*/) {
4079 if (n.getAttribute("id") == id
4080 || n.getAttributeNS(null, "id") == id) {
4084 for (var m = n.firstChild; m != null; m = m.nextSibling) {
4085 var res = Utilities.getElementById(m, id);
4093 // XPathException ////////////////////////////////////////////////////////////
4095 XPathException.prototype = {};
4096 XPathException.prototype.constructor = XPathException;
4097 XPathException.superclass = Object.prototype;
4099 function XPathException(c, e) {
4104 XPathException.prototype.toString = function() {
4105 var msg = this.exception ? ": " + this.exception.toString() : "";
4106 switch (this.code) {
4107 case XPathException.INVALID_EXPRESSION_ERR:
4108 return "Invalid expression" + msg;
4109 case XPathException.TYPE_ERR:
4110 return "Type error" + msg;
4114 XPathException.INVALID_EXPRESSION_ERR = 51;
4115 XPathException.TYPE_ERR = 52;
4117 // XPathExpression ///////////////////////////////////////////////////////////
4119 XPathExpression.prototype = {};
4120 XPathExpression.prototype.constructor = XPathExpression;
4121 XPathExpression.superclass = Object.prototype;
4123 function XPathExpression(e, r, p) {
4124 this.xpath = p.parse(e);
4125 this.context = new XPathContext();
4126 this.context.namespaceResolver = new XPathNSResolverWrapper(r);
4129 XPathExpression.prototype.evaluate = function(n, t, res) {
4130 this.context.expressionContextNode = n;
4131 var result = this.xpath.evaluate(this.context);
4132 return new XPathResult(result, t);
4135 // XPathNSResolverWrapper ////////////////////////////////////////////////////
4137 XPathNSResolverWrapper.prototype = {};
4138 XPathNSResolverWrapper.prototype.constructor = XPathNSResolverWrapper;
4139 XPathNSResolverWrapper.superclass = Object.prototype;
4141 function XPathNSResolverWrapper(r) {
4142 this.xpathNSResolver = r;
4145 XPathNSResolverWrapper.prototype.getNamespace = function(prefix, n) {
4146 if (this.xpathNSResolver == null) {
4149 return this.xpathNSResolver.lookupNamespaceURI(prefix);
4152 // NodeXPathNSResolver ///////////////////////////////////////////////////////
4154 NodeXPathNSResolver.prototype = {};
4155 NodeXPathNSResolver.prototype.constructor = NodeXPathNSResolver;
4156 NodeXPathNSResolver.superclass = Object.prototype;
4158 function NodeXPathNSResolver(n) {
4160 this.namespaceResolver = new NamespaceResolver();
4163 NodeXPathNSResolver.prototype.lookupNamespaceURI = function(prefix) {
4164 return this.namespaceResolver.getNamespace(prefix, this.node);
4167 // XPathResult ///////////////////////////////////////////////////////////////
4169 XPathResult.prototype = {};
4170 XPathResult.prototype.constructor = XPathResult;
4171 XPathResult.superclass = Object.prototype;
4173 function XPathResult(v, t) {
4174 if (t == XPathResult.ANY_TYPE) {
4175 if (v.constructor === XString) {
4176 t = XPathResult.STRING_TYPE;
4177 } else if (v.constructor === XNumber) {
4178 t = XPathResult.NUMBER_TYPE;
4179 } else if (v.constructor === XBoolean) {
4180 t = XPathResult.BOOLEAN_TYPE;
4181 } else if (v.constructor === XNodeSet) {
4182 t = XPathResult.UNORDERED_NODE_ITERATOR_TYPE;
4185 this.resultType = t;
4187 case XPathResult.NUMBER_TYPE:
4188 this.numberValue = v.numberValue();
4190 case XPathResult.STRING_TYPE:
4191 this.stringValue = v.stringValue();
4193 case XPathResult.BOOLEAN_TYPE:
4194 this.booleanValue = v.booleanValue();
4196 case XPathResult.ANY_UNORDERED_NODE_TYPE:
4197 case XPathResult.FIRST_UNORDERED_NODE_TYPE:
4198 if (v.constructor === XNodeSet) {
4199 this.singleNodeValue = v.first();
4203 case XPathResult.UNORDERED_NODE_ITERATOR_TYPE:
4204 case XPathResult.ORDERED_NODE_ITERATOR_TYPE:
4205 if (v.constructor === XNodeSet) {
4206 this.invalidIteratorState = false;
4207 this.nodes = v.toArray();
4208 this.iteratorIndex = 0;
4212 case XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE:
4213 case XPathResult.ORDERED_NODE_SNAPSHOT_TYPE:
4214 if (v.constructor === XNodeSet) {
4215 this.nodes = v.toArray();
4216 this.snapshotLength = this.nodes.length;
4221 throw new XPathException(XPathException.TYPE_ERR);
4224 XPathResult.prototype.iterateNext = function() {
4225 if (this.resultType != XPathResult.UNORDERED_NODE_ITERATOR_TYPE
4226 && this.resultType != XPathResult.ORDERED_NODE_ITERATOR_TYPE) {
4227 throw new XPathException(XPathException.TYPE_ERR);
4229 return this.nodes[this.iteratorIndex++];
4232 XPathResult.prototype.snapshotItem = function(i) {
4233 if (this.resultType != XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE
4234 && this.resultType != XPathResult.ORDERED_NODE_SNAPSHOT_TYPE) {
4235 throw new XPathException(XPathException.TYPE_ERR);
4237 return this.nodes[i];
4240 XPathResult.ANY_TYPE = 0;
4241 XPathResult.NUMBER_TYPE = 1;
4242 XPathResult.STRING_TYPE = 2;
4243 XPathResult.BOOLEAN_TYPE = 3;
4244 XPathResult.UNORDERED_NODE_ITERATOR_TYPE = 4;
4245 XPathResult.ORDERED_NODE_ITERATOR_TYPE = 5;
4246 XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE = 6;
4247 XPathResult.ORDERED_NODE_SNAPSHOT_TYPE = 7;
4248 XPathResult.ANY_UNORDERED_NODE_TYPE = 8;
4249 XPathResult.FIRST_ORDERED_NODE_TYPE = 9;
4251 // DOM 3 XPath support ///////////////////////////////////////////////////////
4253 function installDOM3XPathSupport(doc, p) {
4254 doc.createExpression = function(e, r) {
4256 return new XPathExpression(e, r, p);
4258 throw new XPathException(XPathException.INVALID_EXPRESSION_ERR, e);
4261 doc.createNSResolver = function(n) {
4262 return new NodeXPathNSResolver(n);
4264 doc.evaluate = function(e, cn, r, t, res) {
4266 if (t < 0 || t > 9) {
4267 throw { code: 0, toString: function() { return "Request type not supported"; } };
4269 return doc.createExpression(e, r, p).evaluate(cn, t, res);
4273 // ---------------------------------------------------------------------------
4275 // Install DOM 3 XPath support for the current document.
4277 var shouldInstall = true;
4279 if (document.implementation
4280 && document.implementation.hasFeature
4281 && document.implementation.hasFeature("XPath", null)) {
4282 shouldInstall = false;
4286 if (shouldInstall) {
4287 installDOM3XPathSupport(document, new XPathParser());