xpath-legacy.js 75KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765
  1. /* JavaScript-XPath 0.1.5
  2. * (c) 2007 Cybozu Labs, Inc.
  3. *
  4. * JavaScript-XPath is freely distributable under the terms of an MIT-style license.
  5. * For details, see the JavaScript-XPath web site: http://coderepos.org/share/wiki/JavaScript-XPath
  6. *
  7. /*--------------------------------------------------------------------------*/
  8. if (!document.implementation
  9. || !document.implementation.hasFeature
  10. || !document.implementation.hasFeature("XPath", null)) (function() {
  11. var undefined = void(0);
  12. var defaultConfig = {
  13. targetFrame: undefined
  14. };
  15. var config;
  16. if (window.jsxpath) {
  17. config = window.jsxpath;
  18. }
  19. else {
  20. var scriptElms = document.getElementsByTagName('script');
  21. var scriptElm = scriptElms[scriptElms.length - 1];
  22. var scriptSrc = scriptElm.src;
  23. config = {};
  24. var scriptSrcMatchResult = scriptSrc.match(/\?(.*)$/);
  25. if (scriptSrcMatchResult) {
  26. var configStrings = scriptSrcMatchResult[1].split('&');
  27. for (var i = 0, l = configStrings.length; i < l; i ++) {
  28. var configString = configStrings[i];
  29. var configStringSplited = configString.split('=');
  30. config[configStringSplited[0]] = configStringSplited[1] || true;
  31. }
  32. }
  33. }
  34. for (var n in defaultConfig) {
  35. if (!(n in config)) config[n] = defaultConfig[n]
  36. }
  37. var BinaryExpr;
  38. var FilterExpr;
  39. var FunctionCall;
  40. var Literal;
  41. var NameTest;
  42. var NodeSet;
  43. var NodeType;
  44. var NodeUtil;
  45. var Number;
  46. var PathExpr;
  47. var Step;
  48. var UnaryExpr;
  49. var UnionExpr;
  50. var VariableReference;
  51. /*
  52. * object: user agent identifier
  53. */
  54. var uai = new function() {
  55. var ua = navigator.userAgent;
  56. if (RegExp == undefined) {
  57. if (ua.indexOf("Opera") >= 0) {
  58. this.opera = true;
  59. } else if (ua.indexOf("Netscape") >= 0) {
  60. this.netscape = true;
  61. } else if (ua.indexOf("Mozilla/") == 0) {
  62. this.mozilla = true;
  63. } else {
  64. this.unknown = slide
  65. }
  66. if (ua.indexOf("Gecko/") >= 0) {
  67. this.gecko = true;
  68. }
  69. if (ua.indexOf("Win") >= 0) {
  70. this.windows = true;
  71. } else if (ua.indexOf("Mac") >= 0) {
  72. this.mac = true;
  73. } else if (ua.indexOf("Linux") >= 0) {
  74. this.linux = true;
  75. } else if (ua.indexOf("BSD") >= 0) {
  76. this.bsd = true;
  77. } else if (ua.indexOf("SunOS") >= 0) {
  78. this.sunos = true;
  79. }
  80. }
  81. else {
  82. /* for Trident/Tasman */
  83. /*@cc_on
  84. @if (@_jscript)
  85. function jscriptVersion() {
  86. switch (@_jscript_version) {
  87. case 3.0: return "4.0";
  88. case 5.0: return "5.0";
  89. case 5.1: return "5.01";
  90. case 5.5: return "5.5";
  91. case 5.6:
  92. if ("XMLHttpRequest" in window) return "7.0";
  93. return "6.0";
  94. case 5.7:
  95. return "7.0";
  96. default: return true;
  97. }
  98. }
  99. if (@_win16 || @_win32 || @_win64) {
  100. this.windows = true;
  101. this.trident = jscriptVersion();
  102. } else if (@_mac || navigator.platform.indexOf("Mac") >= 0) {
  103. // '@_mac' may be 'NaN' even if the platform is Mac,
  104. // so we check 'navigator.platform', too.
  105. this.mac = true;
  106. this.tasman = jscriptVersion();
  107. }
  108. if (match = ua.match("MSIE ?(\\d+\\.\\d+)b?;")) {
  109. this.ie = match[1];
  110. this['ie' + match[1].charAt(0)] = true;
  111. }
  112. @else @*/
  113. /* for AppleWebKit */
  114. if (match = ua.match("AppleWebKit/(\\d+(\\.\\d+)*)")) {
  115. this.applewebkit = match[1];
  116. this['applewebkit' + match[1].charAt(0)] = true;
  117. }
  118. /* for Gecko */
  119. else if (typeof(Components) == "object") {
  120. if (match = ua.match("Gecko/(\\d{8})")) {
  121. this.gecko = match[1];
  122. } else if (navigator.product == "Gecko"
  123. && (match = navigator.productSub.match("^(\\d{8})$"))) {
  124. this.gecko = match[1];
  125. }
  126. }
  127. /*@end @*/
  128. if (typeof(opera) == "object" && typeof(opera.version) == "function") {
  129. this.opera = opera.version();
  130. this['opera' + this.opera[0] + this.opera[2]] = true;
  131. } else if (typeof(opera) == "object"
  132. && (match = ua.match("Opera[/ ](\\d+\\.\\d+)"))) {
  133. this.opera = match[1];
  134. } else if (this.ie) {
  135. } else if (match = ua.match("Safari/(\\d+(\\.\\d+)*)")) {
  136. this.safari = match[1];
  137. } else if (match = ua.match("Konqueror/(\\d+(\\.\\d+)*)")) {
  138. this.konqueror = match[1];
  139. } else if (ua.indexOf("(compatible;") < 0
  140. && (match = ua.match("^Mozilla/(\\d+\\.\\d+)"))) {
  141. this.mozilla = match[1];
  142. if (match = ua.match("\\([^(]*rv:(\\d+(\\.\\d+)*).*?\\)"))
  143. this.mozillarv = match[1];
  144. if (match = ua.match("Firefox/(\\d+(\\.\\d+)*)")) {
  145. this.firefox = match[1];
  146. } else if (match = ua.match("Netscape\\d?/(\\d+(\\.\\d+)*)")) {
  147. this.netscape = match[1];
  148. }
  149. } else {
  150. this.unknown = true;
  151. }
  152. if (ua.indexOf("Win 9x 4.90") >= 0) {
  153. this.windows = "ME";
  154. } else if (match = ua.match("Win(dows)? ?(NT ?(\\d+\\.\\d+)?|\\d+|XP|ME|Vista)")) {
  155. this.windows = match[2];
  156. if (match[3]) {
  157. this.winnt = match[3];
  158. } else switch (match[2]) {
  159. case "2000": this.winnt = "5.0"; break;
  160. case "XP": this.winnt = "5.1"; break;
  161. case "Vista": this.winnt = "6.0"; break;
  162. }
  163. } else if (ua.indexOf("Mac") >= 0) {
  164. this.mac = true;
  165. } else if (ua.indexOf("Linux") >= 0) {
  166. this.linux = true;
  167. } else if (match = ua.match("\\w*BSD")) {
  168. this.bsd = match[0];
  169. } else if (ua.indexOf("SunOS") >= 0) {
  170. this.sunos = true;
  171. }
  172. }
  173. };
  174. /**
  175. * pseudo class: Lexer
  176. */
  177. var Lexer = function(source) {
  178. var proto = Lexer.prototype;
  179. var tokens = source.match(proto.regs.token);
  180. for (var i = 0, l = tokens.length; i < l; i ++) {
  181. if (proto.regs.strip.test(tokens[i])) {
  182. tokens.splice(i, 1);
  183. }
  184. }
  185. for (var n in proto) tokens[n] = proto[n];
  186. tokens.index = 0;
  187. return tokens;
  188. };
  189. Lexer.prototype.regs = {
  190. token: /\$?(?:(?![0-9-])[\w-]+:)?(?![0-9-])[\w-]+|\/\/|\.\.|::|\d+(?:\.\d*)?|\.\d+|"[^"]*"|'[^']*'|[!<>]=|(?![0-9-])[\w-]+:\*|\s+|./g,
  191. strip: /^\s/
  192. };
  193. Lexer.prototype.peek = function(i) {
  194. return this[this.index + (i||0)];
  195. };
  196. Lexer.prototype.next = function() {
  197. return this[this.index++];
  198. };
  199. Lexer.prototype.back = function() {
  200. this.index--;
  201. };
  202. Lexer.prototype.empty = function() {
  203. return this.length <= this.index;
  204. };
  205. /**
  206. * class: Ctx
  207. */
  208. var Ctx = function(node, position, last) {
  209. this.node = node;
  210. this.position = position || 1;
  211. this.last = last || 1;
  212. };
  213. /**
  214. * abstract class: BaseExpr
  215. */
  216. var BaseExpr = function() {};
  217. BaseExpr.prototype.number = function(ctx) {
  218. var exrs = this.evaluate(ctx);
  219. if (exrs.isNodeSet) return exrs.number();
  220. return + exrs;
  221. };
  222. BaseExpr.prototype.string = function(ctx) {
  223. var exrs = this.evaluate(ctx);
  224. if (exrs.isNodeSet) return exrs.string();
  225. return '' + exrs;
  226. };
  227. BaseExpr.prototype.bool = function(ctx) {
  228. var exrs = this.evaluate(ctx);
  229. if (exrs.isNodeSet) return exrs.bool();
  230. return !! exrs;
  231. };
  232. /**
  233. * abstract class: BaseExprHasPredicates
  234. */
  235. var BaseExprHasPredicates = function() {};
  236. BaseExprHasPredicates.parsePredicates = function(lexer, expr) {
  237. while (lexer.peek() == '[') {
  238. lexer.next();
  239. if (lexer.empty()) {
  240. throw Error('missing predicate expr');
  241. }
  242. var predicate = BinaryExpr.parse(lexer);
  243. expr.predicate(predicate);
  244. if (lexer.empty()) {
  245. throw Error('unclosed predicate expr');
  246. }
  247. if (lexer.next() != ']') {
  248. lexer.back();
  249. throw Error('bad token: ' + lexer.next());
  250. }
  251. }
  252. };
  253. BaseExprHasPredicates.prototyps = new BaseExpr();
  254. BaseExprHasPredicates.prototype.evaluatePredicates = function(nodeset, start) {
  255. var predicates, predicate, nodes, node, nodeset, position, reverse;
  256. reverse = this.reverse;
  257. predicates = this.predicates;
  258. nodeset.sort();
  259. for (var i = start || 0, l0 = predicates.length; i < l0; i ++) {
  260. predicate = predicates[i];
  261. var deleteIndexes = [];
  262. var nodes = nodeset.list();
  263. for (var j = 0, l1 = nodes.length; j < l1; j ++) {
  264. position = reverse ? (l1 - j) : (j + 1);
  265. exrs = predicate.evaluate(new Ctx(nodes[j], position, l1));
  266. switch (typeof exrs) {
  267. case 'number':
  268. exrs = (position == exrs);
  269. break;
  270. case 'string':
  271. exrs = !!exrs;
  272. break;
  273. case 'object':
  274. exrs = exrs.bool();
  275. break;
  276. }
  277. if (!exrs) {
  278. deleteIndexes.push(j);
  279. }
  280. }
  281. for (var j = deleteIndexes.length - 1, l1 = 0; j >= l1; j --) {
  282. nodeset.del(deleteIndexes[j]);
  283. }
  284. }
  285. return nodeset;
  286. };
  287. /**
  288. * class: BinaryExpr
  289. */
  290. if (!window.BinaryExpr && window.defaultConfig)
  291. window.BinaryExpr = null;
  292. BinaryExpr = function(op, left, right, datatype) {
  293. this.op = op;
  294. this.left = left;
  295. this.right = right;
  296. this.datatype = BinaryExpr.ops[op][2];
  297. this.needContextPosition = left.needContextPosition || right.needContextPosition;
  298. this.needContextNode = left.needContextNode || right.needContextNode;
  299. // Optimize [@id="foo"] and [@name="bar"]
  300. if (this.op == '=') {
  301. if (!right.needContextNode && !right.needContextPosition &&
  302. right.datatype != 'nodeset' && right.datatype != 'void' && left.quickAttr) {
  303. this.quickAttr = true;
  304. this.attrName = left.attrName;
  305. this.attrValueExpr = right;
  306. }
  307. else if (!left.needContextNode && !left.needContextPosition &&
  308. left.datatype != 'nodeset' && left.datatype != 'void' && right.quickAttr) {
  309. this.quickAttr = true;
  310. this.attrName = right.attrName;
  311. this.attrValueExpr = left;
  312. }
  313. }
  314. };
  315. BinaryExpr.compare = function(op, comp, left, right, ctx) {
  316. var type, lnodes, rnodes, nodes, nodeset, primitive;
  317. left = left.evaluate(ctx);
  318. right = right.evaluate(ctx);
  319. if (left.isNodeSet && right.isNodeSet) {
  320. lnodes = left.list();
  321. rnodes = right.list();
  322. for (var i = 0, l0 = lnodes.length; i < l0; i ++)
  323. for (var j = 0, l1 = rnodes.length; j < l1; j ++)
  324. if (comp(NodeUtil.to('string', lnodes[i]), NodeUtil.to('string', rnodes[j])))
  325. return true;
  326. return false;
  327. }
  328. if (left.isNodeSet || right.isNodeSet) {
  329. if (left.isNodeSet)
  330. nodeset = left, primitive = right;
  331. else
  332. nodeset = right, primitive = left;
  333. nodes = nodeset.list();
  334. type = typeof primitive;
  335. for (var i = 0, l = nodes.length; i < l; i ++) {
  336. if (comp(NodeUtil.to(type, nodes[i]), primitive))
  337. return true;
  338. }
  339. return false;
  340. }
  341. if (op == '=' || op == '!=') {
  342. if (typeof left == 'boolean' || typeof right == 'boolean') {
  343. return comp(!!left, !!right);
  344. }
  345. if (typeof left == 'number' || typeof right == 'number') {
  346. return comp(+left, +right);
  347. }
  348. return comp(left, right);
  349. }
  350. return comp(+left, +right);
  351. };
  352. BinaryExpr.ops = {
  353. 'div': [6, function(left, right, ctx) {
  354. return left.number(ctx) / right.number(ctx);
  355. }, 'number'],
  356. 'mod': [6, function(left, right, ctx) {
  357. return left.number(ctx) % right.number(ctx);
  358. }, 'number'],
  359. '*': [6, function(left, right, ctx) {
  360. return left.number(ctx) * right.number(ctx);
  361. }, 'number'],
  362. '+': [5, function(left, right, ctx) {
  363. return left.number(ctx) + right.number(ctx);
  364. }, 'number'],
  365. '-': [5, function(left, right, ctx) {
  366. return left.number(ctx) - right.number(ctx);
  367. }, 'number'],
  368. '<': [4, function(left, right, ctx) {
  369. return BinaryExpr.compare('<',
  370. function(a, b) { return a < b }, left, right, ctx);
  371. }, 'boolean'],
  372. '>': [4, function(left, right, ctx) {
  373. return BinaryExpr.compare('>',
  374. function(a, b) { return a > b }, left, right, ctx);
  375. }, 'boolean'],
  376. '<=': [4, function(left, right, ctx) {
  377. return BinaryExpr.compare('<=',
  378. function(a, b) { return a <= b }, left, right, ctx);
  379. }, 'boolean'],
  380. '>=': [4, function(left, right, ctx) {
  381. return BinaryExpr.compare('>=',
  382. function(a, b) { return a >= b }, left, right, ctx);
  383. }, 'boolean'],
  384. '=': [3, function(left, right, ctx) {
  385. return BinaryExpr.compare('=',
  386. function(a, b) { return a == b }, left, right, ctx);
  387. }, 'boolean'],
  388. '!=': [3, function(left, right, ctx) {
  389. return BinaryExpr.compare('!=',
  390. function(a, b) { return a != b }, left, right, ctx);
  391. }, 'boolean'],
  392. 'and': [2, function(left, right, ctx) {
  393. return left.bool(ctx) && right.bool(ctx);
  394. }, 'boolean'],
  395. 'or': [1, function(left, right, ctx) {
  396. return left.bool(ctx) || right.bool(ctx);
  397. }, 'boolean']
  398. };
  399. BinaryExpr.parse = function(lexer) {
  400. var op, precedence, info, expr, stack = [], index = lexer.index;
  401. while (true) {
  402. if (lexer.empty()) {
  403. throw Error('missing right expression');
  404. }
  405. expr = UnaryExpr.parse(lexer);
  406. op = lexer.next();
  407. if (!op) {
  408. break;
  409. }
  410. info = this.ops[op];
  411. precedence = info && info[0];
  412. if (!precedence) {
  413. lexer.back();
  414. break;
  415. }
  416. while (stack.length && precedence <= this.ops[stack[stack.length-1]][0]) {
  417. expr = new BinaryExpr(stack.pop(), stack.pop(), expr);
  418. }
  419. stack.push(expr, op);
  420. }
  421. while (stack.length) {
  422. expr = new BinaryExpr(stack.pop(), stack.pop(), expr);
  423. }
  424. return expr;
  425. };
  426. BinaryExpr.prototype = new BaseExpr();
  427. BinaryExpr.prototype.evaluate = function(ctx) {
  428. return BinaryExpr.ops[this.op][1](this.left, this.right, ctx);
  429. };
  430. BinaryExpr.prototype.show = function(indent) {
  431. indent = indent || '';
  432. var t = '';
  433. t += indent + 'binary: ' + this.op + '\n';
  434. indent += ' ';
  435. t += this.left.show(indent);
  436. t += this.right.show(indent);
  437. return t;
  438. };
  439. /**
  440. * class: UnaryExpr
  441. */
  442. if (!window.UnaryExpr && window.defaultConfig)
  443. window.UnaryExpr = null;
  444. UnaryExpr = function(op, expr) {
  445. this.op = op;
  446. this.expr = expr;
  447. this.needContextPosition = expr.needContextPosition;
  448. this.needContextNode = expr.needContextNode;
  449. };
  450. UnaryExpr.ops = { '-': 1 };
  451. UnaryExpr.parse = function(lexer) {
  452. var token;
  453. if (this.ops[lexer.peek()])
  454. return new UnaryExpr(lexer.next(), UnaryExpr.parse(lexer));
  455. else
  456. return UnionExpr.parse(lexer);
  457. };
  458. UnaryExpr.prototype = new BaseExpr();
  459. UnaryExpr.prototype.datatype = 'number';
  460. UnaryExpr.prototype.evaluate = function(ctx) {
  461. return - this.expr.number(ctx);
  462. };
  463. UnaryExpr.prototype.show = function(indent) {
  464. indent = indent || '';
  465. var t = '';
  466. t += indent + 'unary: ' + this.op + '\n';
  467. indent += ' ';
  468. t += this.expr.show(indent);
  469. return t;
  470. };
  471. /**
  472. * class: UnionExpr
  473. */
  474. if (!window.UnionExpr && window.defaultConfig)
  475. window.UnionExpr = null;
  476. UnionExpr = function() {
  477. this.paths = [];
  478. };
  479. UnionExpr.ops = { '|': 1 };
  480. UnionExpr.parse = function(lexer) {
  481. var union, expr;
  482. expr = PathExpr.parse(lexer);
  483. if (!this.ops[lexer.peek()])
  484. return expr;
  485. union = new UnionExpr();
  486. union.path(expr);
  487. while (true) {
  488. if (!this.ops[lexer.next()]) break;
  489. if (lexer.empty()) {
  490. throw Error('missing next union location path');
  491. }
  492. union.path(PathExpr.parse(lexer));
  493. }
  494. lexer.back();
  495. return union;
  496. };
  497. UnionExpr.prototype = new BaseExpr();
  498. UnionExpr.prototype.datatype = 'nodeset';
  499. UnionExpr.prototype.evaluate = function(ctx) {
  500. var paths = this.paths;
  501. var nodeset = new NodeSet();
  502. for (var i = 0, l = paths.length; i < l; i ++) {
  503. var exrs = paths[i].evaluate(ctx);
  504. if (!exrs.isNodeSet) throw Error('PathExpr must be nodeset');
  505. nodeset.merge(exrs);
  506. }
  507. return nodeset;
  508. };
  509. UnionExpr.prototype.path = function(path) {
  510. this.paths.push(path);
  511. if (path.needContextPosition) {
  512. this.needContextPosition = true;
  513. }
  514. if (path.needContextNode) {
  515. this.needContextNode = true;
  516. }
  517. }
  518. UnionExpr.prototype.show = function(indent) {
  519. indent = indent || '';
  520. var t = '';
  521. t += indent + 'union:' + '\n';
  522. indent += ' ';
  523. for (var i = 0; i < this.paths.length; i ++) {
  524. t += this.paths[i].show(indent);
  525. }
  526. return t;
  527. };
  528. /**
  529. * class: PathExpr
  530. */
  531. if (!window.PathExpr && window.defaultConfig)
  532. window.PathExpr = null;
  533. PathExpr = function(filter) {
  534. this.filter = filter;
  535. this.steps = [];
  536. this.datatype = filter.datatype;
  537. this.needContextPosition = filter.needContextPosition;
  538. this.needContextNode = filter.needContextNode;
  539. };
  540. PathExpr.ops = { '//': 1, '/': 1 };
  541. PathExpr.parse = function(lexer) {
  542. var op, expr, path, token;
  543. if (this.ops[lexer.peek()]) {
  544. op = lexer.next();
  545. token = lexer.peek();
  546. if (op == '/' && (lexer.empty() ||
  547. (token != '.' && token != '..' && token != '@' && token != '*' &&
  548. !token.match(/(?![0-9])[\w]/)))) {
  549. return FilterExpr.root();
  550. }
  551. path = new PathExpr(FilterExpr.root()); // RootExpr
  552. if (lexer.empty()) {
  553. throw Error('missing next location step');
  554. }
  555. expr = Step.parse(lexer);
  556. path.step(op, expr);
  557. }
  558. else {
  559. expr = FilterExpr.parse(lexer);
  560. if (!expr) {
  561. expr = Step.parse(lexer);
  562. path = new PathExpr(FilterExpr.context());
  563. path.step('/', expr);
  564. }
  565. else if (!this.ops[lexer.peek()])
  566. return expr;
  567. else
  568. path = new PathExpr(expr);
  569. }
  570. while (true) {
  571. if (!this.ops[lexer.peek()]) break;
  572. op = lexer.next();
  573. if (lexer.empty()) {
  574. throw Error('missing next location step');
  575. }
  576. path.step(op, Step.parse(lexer));
  577. }
  578. return path;
  579. };
  580. PathExpr.prototype = new BaseExpr();
  581. PathExpr.prototype.evaluate = function(ctx) {
  582. var nodeset = this.filter.evaluate(ctx);
  583. if (!nodeset.isNodeSet) throw Exception('Filter nodeset must be nodeset type');
  584. var steps = this.steps;
  585. for (var i = 0, l0 = steps.length; i < l0 && nodeset.length; i ++) {
  586. var step = steps[i][1];
  587. var reverse = step.reverse;
  588. var iter = nodeset.iterator(reverse);
  589. var prevNodeset = nodeset;
  590. nodeset = null;
  591. var node, next;
  592. if (!step.needContextPosition && step.axis == 'following') {
  593. for (node = iter(); next = iter(); node = next) {
  594. // Safari 2 node.contains problem
  595. if (uai.applewebkit4) {
  596. var contains = false;
  597. var ancestor = next;
  598. do {
  599. if (ancestor == node) {
  600. contains = true;
  601. break;
  602. }
  603. } while (ancestor = ancestor.parentNode);
  604. if (!contains) break;
  605. }
  606. else {
  607. try { if (!node.contains(next)) break }
  608. catch(e) { if (!(next.compareDocumentPosition(node) & 8)) break }
  609. }
  610. }
  611. nodeset = step.evaluate(new Ctx(node));
  612. }
  613. else if (!step.needContextPosition && step.axis == 'preceding') {
  614. node = iter();
  615. nodeset = step.evaluate(new Ctx(node));
  616. }
  617. else {
  618. node = iter();
  619. var j = 0;
  620. nodeset = step.evaluate(new Ctx(node), false, prevNodeset, j);
  621. while (node = iter()) {
  622. j ++;
  623. nodeset.merge(step.evaluate(new Ctx(node), false, prevNodeset, j));
  624. }
  625. }
  626. }
  627. return nodeset;
  628. };
  629. PathExpr.prototype.step = function(op, step) {
  630. step.op = op;
  631. this.steps.push([op, step]);
  632. this.quickAttr = false;
  633. if (this.steps.length == 1) {
  634. if (op == '/' && step.axis == 'attribute') {
  635. var test = step.test;
  636. if (!test.notOnlyElement && test.name != '*') {
  637. this.quickAttr = true;
  638. this.attrName = test.name;
  639. }
  640. }
  641. }
  642. };
  643. PathExpr.prototype.show = function(indent) {
  644. indent = indent || '';
  645. var t = '';
  646. t += indent + 'path:' + '\n';
  647. indent += ' ';
  648. t += indent + 'filter:' + '\n';
  649. t += this.filter.show(indent + ' ');
  650. if (this.steps.length) {
  651. t += indent + 'steps:' + '\n';
  652. indent += ' ';
  653. for (var i = 0; i < this.steps.length; i ++) {
  654. var step = this.steps[i];
  655. t += indent + 'operator: ' + step[0] + '\n';
  656. t += step[1].show(indent);
  657. }
  658. }
  659. return t;
  660. };
  661. /**
  662. * class: FilterExpr
  663. */
  664. if (!window.FilterExpr && window.defaultConfig)
  665. window.FilterExpr = null;
  666. FilterExpr = function(primary) {
  667. this.primary = primary;
  668. this.predicates = [];
  669. this.datatype = primary.datatype;
  670. this.needContextPosition = primary.needContextPosition;
  671. this.needContextNode = primary.needContextNode;
  672. };
  673. FilterExpr.parse = function(lexer) {
  674. var expr, filter, token, ch;
  675. token = lexer.peek();
  676. ch = token.charAt(0);
  677. switch (ch) {
  678. case '$':
  679. expr = VariableReference.parse(lexer);
  680. break;
  681. case '(':
  682. lexer.next();
  683. expr = BinaryExpr.parse(lexer);
  684. if (lexer.empty()) {
  685. throw Error('unclosed "("');
  686. }
  687. if (lexer.next() != ')') {
  688. lexer.back();
  689. throw Error('bad token: ' + lexer.next());
  690. }
  691. break;
  692. case '"':
  693. case "'":
  694. expr = Literal.parse(lexer);
  695. break;
  696. default:
  697. if (!isNaN(+token)) {
  698. expr = Number.parse(lexer);
  699. }
  700. else if (NodeType.types[token]) {
  701. return null;
  702. }
  703. else if (ch.match(/(?![0-9])[\w]/) && lexer.peek(1) == '(') {
  704. expr = FunctionCall.parse(lexer);
  705. }
  706. else {
  707. return null;
  708. }
  709. break;
  710. }
  711. if (lexer.peek() != '[') return expr;
  712. filter = new FilterExpr(expr);
  713. BaseExprHasPredicates.parsePredicates(lexer, filter);
  714. return filter;
  715. };
  716. FilterExpr.root = function() {
  717. return new FunctionCall('root-node');
  718. };
  719. FilterExpr.context = function() {
  720. return new FunctionCall('context-node');
  721. };
  722. FilterExpr.prototype = new BaseExprHasPredicates();
  723. FilterExpr.prototype.evaluate = function(ctx) {
  724. var nodeset = this.primary.evaluate(ctx);
  725. if(!nodeset.isNodeSet) {
  726. if (this.predicates.length)
  727. throw Error(
  728. 'Primary result must be nodeset type ' +
  729. 'if filter have predicate expression');
  730. return nodeset;
  731. }
  732. return this.evaluatePredicates(nodeset);
  733. };
  734. FilterExpr.prototype.predicate = function(predicate) {
  735. this.predicates.push(predicate);
  736. };
  737. FilterExpr.prototype.show = function(indent) {
  738. indent = indent || '';
  739. var t = '';
  740. t += indent + 'filter: ' + '\n';
  741. indent += ' ';
  742. t += this.primary.show(indent);
  743. if (this.predicates.length) {
  744. t += indent + 'predicates: ' + '\n';
  745. indent += ' ';
  746. for (var i = 0; i < this.predicates.length; i ++) {
  747. t += this.predicates[i].show(indent);
  748. }
  749. }
  750. return t;
  751. };
  752. if (!window.NodeUtil && window.defaultConfig)
  753. window.NodeUtil = null;
  754. NodeUtil = {
  755. to: function(valueType, node) {
  756. var type = node.nodeType;
  757. /*@cc_on
  758. if (type == 1 && node.nodeName.toLowerCase() == 'title') {
  759. t = node.text;
  760. }
  761. else
  762. @*/
  763. if (type == 9 || type == 1) {
  764. if (type == 9) {
  765. node = node.documentElement;
  766. }
  767. else {
  768. node = node.firstChild;
  769. }
  770. for (var t = '', stack = [], i = 0; node;) {
  771. do {
  772. if (node.nodeType != 1) {
  773. t += node.nodeValue;
  774. }
  775. /*@cc_on
  776. else if (node.nodeName.toLowerCase() == 'title') {
  777. t += node.text;
  778. }
  779. @*/
  780. stack[i++] = node; // push
  781. } while (node = node.firstChild);
  782. while (i && !(node = stack[--i].nextSibling)) {}
  783. }
  784. }
  785. else {
  786. var t = node.nodeValue;
  787. }
  788. switch (valueType) {
  789. case 'number':
  790. return + t;
  791. case 'boolean':
  792. return !! t;
  793. default:
  794. return t;
  795. }
  796. },
  797. attrPropMap: {
  798. name: 'name',
  799. 'class': 'className',
  800. dir: 'dir',
  801. id: 'id',
  802. name: 'name',
  803. title: 'title'
  804. },
  805. attrMatch: function(node, attrName, attrValue) {
  806. /*@cc_on @if (@_jscript)
  807. var propName = NodeUtil.attrPropMap[attrName];
  808. if (!attrName ||
  809. attrValue == null && (
  810. propName && node[propName] ||
  811. !propName && node.getAttribute && node.getAttribute(attrName)
  812. ) ||
  813. attrValue != null && (
  814. propName && node[propName] == attrValue ||
  815. !propName && node.getAttribute && node.getAttribute(attrName) == attrValue
  816. )) {
  817. @else @*/
  818. if (!attrName ||
  819. attrValue == null && node.hasAttribute && node.hasAttribute(attrName) ||
  820. attrValue != null && node.getAttribute && node.getAttribute(attrName) == attrValue) {
  821. /*@end @*/
  822. return true;
  823. }
  824. else {
  825. return false;
  826. }
  827. },
  828. getDescendantNodes: function(test, node, nodeset, attrName, attrValue, prevNodeset, prevIndex) {
  829. if (prevNodeset) {
  830. prevNodeset.delDescendant(node, prevIndex);
  831. }
  832. /*@cc_on
  833. if (!test.notOnlyElement || test.type == 8 || (attrName && test.type == 0)) {
  834. var all = node.all;
  835. if (!all) {
  836. return nodeset;
  837. }
  838. var name = test.name;
  839. if (test.type == 8) name = '!';
  840. else if (test.type == 0) name = '*';
  841. if (name != '*') {
  842. all = all.tags(name);
  843. if (!all) {
  844. return nodeset;
  845. }
  846. }
  847. if (attrName) {
  848. var result = []
  849. var i = 0;
  850. if (attrValue != null && (attrName == 'id' || attrName == 'name')) {
  851. all = all[attrValue];
  852. if (!all) {
  853. return nodeset;
  854. }
  855. if (!all.length) {
  856. all = [all];
  857. }
  858. }
  859. while (node = all[i++]) {
  860. if (NodeUtil.attrMatch(node, attrName, attrValue)) result.push(node);
  861. }
  862. all = result;
  863. }
  864. var i = 0;
  865. while (node = all[i++]) {
  866. if (name != '*' || node.tagName != '!') {
  867. nodeset.push(node);
  868. }
  869. }
  870. return nodeset;
  871. }
  872. (function (parent) {
  873. var g = arguments.callee;
  874. var node = parent.firstChild;
  875. if (node) {
  876. for (; node; node = node.nextSibling) {
  877. if (NodeUtil.attrMatch(node, attrName, attrValue)) {
  878. if (test.match(node)) nodeset.push(node);
  879. }
  880. g(node);
  881. }
  882. }
  883. })(node);
  884. return nodeset;
  885. @*/
  886. if (attrValue && attrName == 'id' && node.getElementById) {
  887. node = node.getElementById(attrValue);
  888. if (node && test.match(node)) {
  889. nodeset.push(node);
  890. }
  891. }
  892. else if (attrValue && attrName == 'name' && node.getElementsByName) {
  893. var nodes = node.getElementsByName(attrValue);
  894. for (var i = 0, l = nodes.length; i < l; i ++) {
  895. node = nodes[i];
  896. if (uai.opera ? (node.name == attrValue && test.match(node)) : test.match(node)) {
  897. nodeset.push(node);
  898. }
  899. }
  900. }
  901. else if (attrValue && attrName == 'class' && node.getElementsByClassName) {
  902. var nodes = node.getElementsByClassName(attrValue);
  903. for (var i = 0, l = nodes.length; i < l; i ++) {
  904. node = nodes[i];
  905. if (node.className == attrValue && test.match(node)) {
  906. nodeset.push(node);
  907. }
  908. }
  909. }
  910. else if (test.notOnlyElement) {
  911. (function (parent) {
  912. var f = arguments.callee;
  913. for (var node = parent.firstChild; node; node = node.nextSibling) {
  914. if (NodeUtil.attrMatch(node, attrName, attrValue)) {
  915. if (test.match(node.nodeType)) nodeset.push(node);
  916. }
  917. f(node);
  918. }
  919. })(node);
  920. }
  921. else {
  922. var name = test.name;
  923. if (node.getElementsByTagName) {
  924. var nodes = node.getElementsByTagName(name);
  925. if (nodes) {
  926. var i = 0;
  927. while (node = nodes[i++]) {
  928. if (NodeUtil.attrMatch(node, attrName, attrValue)) nodeset.push(node);
  929. }
  930. }
  931. }
  932. }
  933. return nodeset;
  934. },
  935. getChildNodes: function(test, node, nodeset, attrName, attrValue) {
  936. /*@cc_on
  937. var children;
  938. if ((!test.notOnlyElement || test.type == 8 || (attrName && test.type == 0)) && (children = node.children)) {
  939. var name, elm;
  940. name = test.name;
  941. if (test.type == 8) name = '!';
  942. else if (test.type == 0) name = '*';
  943. if (name != '*') {
  944. children = children.tags(name);
  945. if (!children) {
  946. return nodeset;
  947. }
  948. }
  949. if (attrName) {
  950. var result = []
  951. var i = 0;
  952. if (attrName == 'id' || attrName == 'name') {
  953. children = children[attrValue];
  954. if (!children) {
  955. return nodeset;
  956. }
  957. if (!children.length) {
  958. children = [children];
  959. }
  960. }
  961. while (node = children[i++]) {
  962. if (NodeUtil.attrMatch(node, attrName, attrValue)) result.push(node);
  963. }
  964. children = result;
  965. }
  966. var i = 0;
  967. while (node = children[i++]) {
  968. if (name != '*' || node.tagName != '!') {
  969. nodeset.push(node);
  970. }
  971. }
  972. return nodeset;
  973. }
  974. for (var i = 0, node = node.firstChild; node; i++, node = node.nextSibling) {
  975. if (NodeUtil.attrMatch(node, attrName, attrValue)) {
  976. if (test.match(node)) nodeset.push(node);
  977. }
  978. }
  979. return nodeset;
  980. @*/
  981. for (var node = node.firstChild; node; node = node.nextSibling) {
  982. if (NodeUtil.attrMatch(node, attrName, attrValue)) {
  983. if (test.match(node)) nodeset.push(node);
  984. }
  985. }
  986. return nodeset;
  987. }
  988. };
  989. /*@cc_on
  990. var AttributeWrapper = function(node, parent, sourceIndex) {
  991. this.node = node;
  992. this.nodeType = 2;
  993. this.nodeValue = node.nodeValue;
  994. this.nodeName = node.nodeName;
  995. this.parentNode = parent;
  996. this.ownerElement = parent;
  997. this.parentSourceIndex = sourceIndex;
  998. };
  999. @*/
  1000. /**
  1001. * class: Step
  1002. */
  1003. if (!window.Step && window.defaultConfig)
  1004. window.Step = null;
  1005. Step = function(axis, test) {
  1006. // TODO check arguments and throw axis error
  1007. this.axis = axis;
  1008. this.reverse = Step.axises[axis][0];
  1009. this.func = Step.axises[axis][1];
  1010. this.test = test;
  1011. this.predicates = [];
  1012. this._quickAttr = Step.axises[axis][2]
  1013. };
  1014. Step.axises = {
  1015. ancestor: [true, function(test, node, nodeset, _, __, prevNodeset, prevIndex) {
  1016. while (node = node.parentNode) {
  1017. if (prevNodeset && node.nodeType == 1) {
  1018. prevNodeset.reserveDelByNode(node, prevIndex, true);
  1019. }
  1020. if (test.match(node)) nodeset.unshift(node);
  1021. }
  1022. return nodeset;
  1023. }],
  1024. 'ancestor-or-self': [true, function(test, node, nodeset, _, __, prevNodeset, prevIndex) {
  1025. do {
  1026. if (prevNodeset && node.nodeType == 1) {
  1027. prevNodeset.reserveDelByNode(node, prevIndex, true);
  1028. }
  1029. if (test.match(node)) nodeset.unshift(node);
  1030. } while (node = node.parentNode)
  1031. return nodeset;
  1032. }],
  1033. attribute: [false, function(test, node, nodeset) {
  1034. var attrs = node.attributes;
  1035. if (attrs) {
  1036. /*@cc_on
  1037. var sourceIndex = node.sourceIndex;
  1038. @*/
  1039. if ((test.notOnlyElement && test.type == 0) || test.name == '*') {
  1040. for (var i = 0, l = attrs.length; i < l; i ++) {
  1041. var attr = attrs[i];
  1042. /*@cc_on @if (@_jscript)
  1043. if (attr.nodeValue) {
  1044. nodeset.push(new AttributeWrapper(attr, node, sourceIndex));
  1045. }
  1046. @else @*/
  1047. nodeset.push(attr);
  1048. /*@end @*/
  1049. }
  1050. }
  1051. else {
  1052. var attr = attrs.getNamedItem(test.name)
  1053. /*@cc_on @if (@_jscript)
  1054. if (attr && attr.nodeValue) {
  1055. attr = new AttributeWrapper(attr, node, sourceIndex);;
  1056. @else @*/
  1057. if (attr) {
  1058. /*@end @*/
  1059. nodeset.push(attr);
  1060. }
  1061. }
  1062. }
  1063. return nodeset;
  1064. }],
  1065. child: [false, NodeUtil.getChildNodes, true],
  1066. descendant: [false, NodeUtil.getDescendantNodes, true],
  1067. 'descendant-or-self': [false, function(test, node, nodeset, attrName, attrValue, prevNodeset, prevIndex) {
  1068. if (NodeUtil.attrMatch(node, attrName, attrValue)) {
  1069. if (test.match(node)) nodeset.push(node);
  1070. }
  1071. return NodeUtil.getDescendantNodes(test, node, nodeset, attrName, attrValue, prevNodeset, prevIndex);
  1072. }, true],
  1073. following: [false, function(test, node, nodeset, attrName, attrValue) {
  1074. do {
  1075. var child = node;
  1076. while (child = child.nextSibling) {
  1077. if (NodeUtil.attrMatch(child, attrName, attrValue)) {
  1078. if (test.match(child)) nodeset.push(child);
  1079. }
  1080. nodeset = NodeUtil.getDescendantNodes(test, child, nodeset, attrName, attrValue);
  1081. }
  1082. } while (node = node.parentNode);
  1083. return nodeset;
  1084. }, true],
  1085. 'following-sibling': [false, function(test, node, nodeset, _, __, prevNodeset, prevIndex) {
  1086. while (node = node.nextSibling) {
  1087. if (prevNodeset && node.nodeType == 1) {
  1088. prevNodeset.reserveDelByNode(node, prevIndex);
  1089. }
  1090. if (test.match(node)) {
  1091. nodeset.push(node);
  1092. }
  1093. }
  1094. return nodeset;
  1095. }],
  1096. namespace: [false, function(test, node, nodeset) {
  1097. // not implemented
  1098. return nodeset;
  1099. }],
  1100. parent: [false, function(test, node, nodeset) {
  1101. if (node.nodeType == 9) {
  1102. return nodeset;
  1103. }
  1104. if (node.nodeType == 2) {
  1105. nodeset.push(node.ownerElement);
  1106. return nodeset;
  1107. }
  1108. var node = node.parentNode;
  1109. if (test.match(node)) nodeset.push(node);
  1110. return nodeset;
  1111. }],
  1112. preceding: [true, function(test, node, nodeset, attrName, attrValue) {
  1113. var parents = [];
  1114. do {
  1115. parents.unshift(node);
  1116. } while (node = node.parentNode);
  1117. for (var i = 1, l0 = parents.length; i < l0; i ++) {
  1118. var siblings = [];
  1119. node = parents[i];
  1120. while (node = node.previousSibling) {
  1121. siblings.unshift(node);
  1122. }
  1123. for (var j = 0, l1 = siblings.length; j < l1; j ++) {
  1124. node = siblings[j];
  1125. if (NodeUtil.attrMatch(node, attrName, attrValue)) {
  1126. if (test.match(node)) nodeset.push(node);
  1127. }
  1128. nodeset = NodeUtil.getDescendantNodes(test, node, nodeset, attrName, attrValue);
  1129. }
  1130. }
  1131. return nodeset;
  1132. }, true],
  1133. 'preceding-sibling': [true, function(test, node, nodeset, _, __, prevNodeset, prevIndex) {
  1134. while (node = node.previousSibling) {
  1135. if (prevNodeset && node.nodeType == 1) {
  1136. prevNodeset.reserveDelByNode(node, prevIndex, true);
  1137. }
  1138. if (test.match(node)) {
  1139. nodeset.unshift(node)
  1140. }
  1141. }
  1142. return nodeset;
  1143. }],
  1144. self: [false, function(test, node, nodeset) {
  1145. if (test.match(node)) nodeset.push(node);
  1146. return nodeset;
  1147. }]
  1148. };
  1149. Step.parse = function(lexer) {
  1150. var axis, test, step, token;
  1151. if (lexer.peek() == '.') {
  1152. step = this.self();
  1153. lexer.next();
  1154. }
  1155. else if (lexer.peek() == '..') {
  1156. step = this.parent();
  1157. lexer.next();
  1158. }
  1159. else {
  1160. if (lexer.peek() == '@') {
  1161. axis = 'attribute';
  1162. lexer.next();
  1163. if (lexer.empty()) {
  1164. throw Error('missing attribute name');
  1165. }
  1166. }
  1167. else {
  1168. if (lexer.peek(1) == '::') {
  1169. if (!lexer.peek().charAt(0).match(/(?![0-9])[\w]/)) {
  1170. throw Error('bad token: ' + lexer.next());
  1171. }
  1172. axis = lexer.next();
  1173. lexer.next();
  1174. if (!this.axises[axis]) {
  1175. throw Error('invalid axis: ' + axis);
  1176. }
  1177. if (lexer.empty()) {
  1178. throw Error('missing node name');
  1179. }
  1180. }
  1181. else {
  1182. axis = 'child';
  1183. }
  1184. }
  1185. token = lexer.peek();
  1186. if (!token.charAt(0).match(/(?![0-9])[\w]/)) {
  1187. if (token == '*') {
  1188. test = NameTest.parse(lexer)
  1189. }
  1190. else {
  1191. throw Error('bad token: ' + lexer.next());
  1192. }
  1193. }
  1194. else {
  1195. if (lexer.peek(1) == '(') {
  1196. if (!NodeType.types[token]) {
  1197. throw Error('invalid node type: ' + token);
  1198. }
  1199. test = NodeType.parse(lexer)
  1200. }
  1201. else {
  1202. test = NameTest.parse(lexer);
  1203. }
  1204. }
  1205. step = new Step(axis, test);
  1206. }
  1207. BaseExprHasPredicates.parsePredicates(lexer, step);
  1208. return step;
  1209. };
  1210. Step.self = function() {
  1211. return new Step('self', new NodeType('node'));
  1212. };
  1213. Step.parent = function() {
  1214. return new Step('parent', new NodeType('node'));
  1215. };
  1216. Step.prototype = new BaseExprHasPredicates();
  1217. Step.prototype.evaluate = function(ctx, special, prevNodeset, prevIndex) {
  1218. var node = ctx.node;
  1219. var reverse = false;
  1220. if (!special && this.op == '//') {
  1221. if (!this.needContextPosition && this.axis == 'child') {
  1222. if (this.quickAttr) {
  1223. var attrValue = this.attrValueExpr ? this.attrValueExpr.string(ctx) : null;
  1224. var nodeset = NodeUtil.getDescendantNodes(this.test, node, new NodeSet(), this.attrName, attrValue, prevNodeset, prevIndex);
  1225. nodeset = this.evaluatePredicates(nodeset, 1);
  1226. }
  1227. else {
  1228. var nodeset = NodeUtil.getDescendantNodes(this.test, node, new NodeSet(), null, null, prevNodeset, prevIndex);
  1229. nodeset = this.evaluatePredicates(nodeset);
  1230. }
  1231. }
  1232. else {
  1233. var step = new Step('descendant-or-self', new NodeType('node'));
  1234. var nodes = step.evaluate(ctx, false, prevNodeset, prevIndex).list();
  1235. var nodeset = null;
  1236. step.op = '/';
  1237. for (var i = 0, l = nodes.length; i < l; i ++) {
  1238. if (!nodeset) {
  1239. nodeset = this.evaluate(new Ctx(nodes[i]), true);
  1240. }
  1241. else {
  1242. nodeset.merge(this.evaluate(new Ctx(nodes[i]), true));
  1243. }
  1244. }
  1245. nodeset = nodeset || new NodeSet();
  1246. }
  1247. }
  1248. else {
  1249. if (this.needContextPosition) {
  1250. prevNodeset = null;
  1251. prevIndex = null;
  1252. }
  1253. if (this.quickAttr) {
  1254. var attrValue = this.attrValueExpr ? this.attrValueExpr.string(ctx) : null;
  1255. var nodeset = this.func(this.test, node, new NodeSet(), this.attrName, attrValue, prevNodeset, prevIndex);
  1256. nodeset = this.evaluatePredicates(nodeset, 1);
  1257. }
  1258. else {
  1259. var nodeset = this.func(this.test, node, new NodeSet(), null, null, prevNodeset, prevIndex);
  1260. nodeset = this.evaluatePredicates(nodeset);
  1261. }
  1262. if (prevNodeset) {
  1263. prevNodeset.doDel();
  1264. }
  1265. }
  1266. return nodeset;
  1267. };
  1268. Step.prototype.predicate = function(predicate) {
  1269. this.predicates.push(predicate);
  1270. if (predicate.needContextPosition ||
  1271. predicate.datatype == 'number'||
  1272. predicate.datatype == 'void') {
  1273. this.needContextPosition = true;
  1274. }
  1275. if (this._quickAttr && this.predicates.length == 1 && predicate.quickAttr) {
  1276. var attrName = predicate.attrName;
  1277. /*@cc_on @if (@_jscript)
  1278. this.attrName = attrName.toLowerCase();
  1279. @else @*/
  1280. this.attrName = attrName;
  1281. /*@end @*/
  1282. this.attrValueExpr = predicate.attrValueExpr;
  1283. this.quickAttr = true;
  1284. }
  1285. };
  1286. Step.prototype.show = function(indent) {
  1287. indent = indent || '';
  1288. var t = '';
  1289. t += indent + 'step: ' + '\n';
  1290. indent += ' ';
  1291. if (this.axis) t += indent + 'axis: ' + this.axis + '\n';
  1292. t += this.test.show(indent);
  1293. if (this.predicates.length) {
  1294. t += indent + 'predicates: ' + '\n';
  1295. indent += ' ';
  1296. for (var i = 0; i < this.predicates.length; i ++) {
  1297. t += this.predicates[i].show(indent);
  1298. }
  1299. }
  1300. return t;
  1301. };
  1302. /**
  1303. * NodeType
  1304. */
  1305. if (!window.NodeType && window.defaultConfig)
  1306. window.NodeType = null;
  1307. NodeType = function(name, literal) {
  1308. this.name = name;
  1309. this.literal = literal;
  1310. switch (name) {
  1311. case 'comment':
  1312. this.type = 8;
  1313. break;
  1314. case 'text':
  1315. this.type = 3;
  1316. break;
  1317. case 'processing-instruction':
  1318. this.type = 7;
  1319. break;
  1320. case 'node':
  1321. this.type = 0;
  1322. break;
  1323. }
  1324. };
  1325. NodeType.types = {
  1326. 'comment':1, 'text':1, 'processing-instruction':1, 'node':1
  1327. };
  1328. NodeType.parse = function(lexer) {
  1329. var type, literal, ch;
  1330. type = lexer.next();
  1331. lexer.next();
  1332. if (lexer.empty()) {
  1333. throw Error('bad nodetype');
  1334. }
  1335. ch = lexer.peek().charAt(0);
  1336. if (ch == '"' || ch == "'") {
  1337. literal = Literal.parse(lexer);
  1338. }
  1339. if (lexer.empty()) {
  1340. throw Error('bad nodetype');
  1341. }
  1342. if (lexer.next() != ')') {
  1343. lexer.back();
  1344. throw Error('bad token ' + lexer.next());
  1345. }
  1346. return new NodeType(type, literal);
  1347. };
  1348. NodeType.prototype = new BaseExpr();
  1349. NodeType.prototype.notOnlyElement = true;
  1350. NodeType.prototype.match = function(node) {
  1351. return !this.type || this.type == node.nodeType;
  1352. };
  1353. NodeType.prototype.show = function(indent) {
  1354. indent = indent || '';
  1355. var t = '';
  1356. t += indent + 'nodetype: ' + this.type + '\n';
  1357. if (this.literal) {
  1358. indent += ' ';
  1359. t += this.literal.show(indent);
  1360. }
  1361. return t;
  1362. };
  1363. /**
  1364. * NodeType
  1365. */
  1366. if (!window.NameTest && window.defaultConfig)
  1367. window.NameTest = null;
  1368. NameTest = function(name) {
  1369. this.name = name.toLowerCase();
  1370. };
  1371. NameTest.parse = function(lexer) {
  1372. if (lexer.peek() != '*' && lexer.peek(1) == ':' && lexer.peek(2) == '*') {
  1373. return new NameTest(lexer.next() + lexer.next() + lexer.next());
  1374. }
  1375. return new NameTest(lexer.next());
  1376. };
  1377. NameTest.prototype = new BaseExpr();
  1378. NameTest.prototype.match = function(node) {
  1379. var type = node.nodeType;
  1380. if (type == 1 || type == 2) {
  1381. if (this.name == '*' || this.name == node.nodeName.toLowerCase()) {
  1382. return true;
  1383. }
  1384. }
  1385. return false;
  1386. };
  1387. NameTest.prototype.show = function(indent) {
  1388. indent = indent || '';
  1389. var t = '';
  1390. t += indent + 'nametest: ' + this.name + '\n';
  1391. return t;
  1392. };
  1393. /**
  1394. * class: VariableRefernce
  1395. */
  1396. if (!window.VariableReference && window.defaultConfig)
  1397. window.VariableReference = null;
  1398. VariableReference = function(name) {
  1399. this.name = name.substring(1);
  1400. };
  1401. VariableReference.parse = function(lexer) {
  1402. var token = lexer.next();
  1403. if (token.length < 2) {
  1404. throw Error('unnamed variable reference');
  1405. }
  1406. return new VariableReference(token)
  1407. };
  1408. VariableReference.prototype = new BaseExpr();
  1409. VariableReference.prototype.datatype = 'void';
  1410. VariableReference.prototype.show = function(indent) {
  1411. indent = indent || '';
  1412. var t = '';
  1413. t += indent + 'variable: ' + this.name + '\n';
  1414. return t;
  1415. };
  1416. /**
  1417. * class: Literal
  1418. */
  1419. if (!window.Literal && window.defaultConfig)
  1420. window.Literal = null;
  1421. Literal = function(text) {
  1422. this.text = text.substring(1, text.length - 1);
  1423. };
  1424. Literal.parse = function(lexer) {
  1425. var token = lexer.next();
  1426. if (token.length < 2) {
  1427. throw Error('unclosed literal string');
  1428. }
  1429. return new Literal(token)
  1430. };
  1431. Literal.prototype = new BaseExpr();
  1432. Literal.prototype.datatype = 'string';
  1433. Literal.prototype.evaluate = function(ctx) {
  1434. return this.text;
  1435. };
  1436. Literal.prototype.show = function(indent) {
  1437. indent = indent || '';
  1438. var t = '';
  1439. t += indent + 'literal: ' + this.text + '\n';
  1440. return t;
  1441. };
  1442. /**
  1443. * class: Number
  1444. */
  1445. if (!window.Number && window.defaultConfig)
  1446. window.Number = null;
  1447. Number = function(digit) {
  1448. this.digit = +digit;
  1449. };
  1450. Number.parse = function(lexer) {
  1451. return new Number(lexer.next());
  1452. };
  1453. Number.prototype = new BaseExpr();
  1454. Number.prototype.datatype = 'number';
  1455. Number.prototype.evaluate = function(ctx) {
  1456. return this.digit;
  1457. };
  1458. Number.prototype.show = function(indent) {
  1459. indent = indent || '';
  1460. var t = '';
  1461. t += indent + 'number: ' + this.digit + '\n';
  1462. return t;
  1463. };
  1464. /**
  1465. * class: FunctionCall
  1466. */
  1467. if (!window.FunctionCall && window.defaultConfig)
  1468. window.FunctionCall = null;
  1469. FunctionCall = function(name) {
  1470. var info = FunctionCall.funcs[name];
  1471. this.name = name;
  1472. this.func = info[0];
  1473. this.args = [];
  1474. this.datatype = info[1];
  1475. if (info[2]) {
  1476. this.needContextPosition = true;
  1477. }
  1478. this.needContextNodeInfo = info[3];
  1479. this.needContextNode = this.needContextNodeInfo[0]
  1480. };
  1481. FunctionCall.funcs = {
  1482. // Original Function
  1483. 'context-node': [function() {
  1484. if (arguments.length != 0) {
  1485. throw Error('Function context-node expects ()');
  1486. }
  1487. var ns;
  1488. ns = new NodeSet();
  1489. ns.push(this.node);
  1490. return ns;
  1491. }, 'nodeset', false, [true]],
  1492. // Original Function
  1493. 'root-node': [function() {
  1494. if (arguments.length != 0) {
  1495. throw Error('Function root-node expects ()');
  1496. }
  1497. var ns, ctxn;
  1498. ns = new NodeSet();
  1499. ctxn = this.node;
  1500. if (ctxn.nodeType == 9)
  1501. ns.push(ctxn);
  1502. else
  1503. ns.push(ctxn.ownerDocument);
  1504. return ns;
  1505. }, 'nodeset', false, []],
  1506. last: [function() {
  1507. if (arguments.length != 0) {
  1508. throw Error('Function last expects ()');
  1509. }
  1510. return this.last;
  1511. }, 'number', true, []],
  1512. position: [function() {
  1513. if (arguments.length != 0) {
  1514. throw Error('Function position expects ()');
  1515. }
  1516. return this.position;
  1517. }, 'number', true, []],
  1518. count: [function(ns) {
  1519. if (arguments.length != 1 || !(ns = ns.evaluate(this)).isNodeSet) {
  1520. throw Error('Function count expects (nodeset)');
  1521. }
  1522. return ns.length;
  1523. }, 'number', false, []],
  1524. id: [function(s) {
  1525. var ids, ns, i, id, elm, ctxn, doc;
  1526. if (arguments.length != 1) {
  1527. throw Error('Function id expects (object)');
  1528. }
  1529. ctxn = this.node;
  1530. if (ctxn.nodeType == 9)
  1531. doc = ctxn;
  1532. else
  1533. doc = ctxn.ownerDocument;
  1534. /*@cc_on
  1535. all = doc.all;
  1536. @*/
  1537. s = s.string(this);
  1538. ids = s.split(/\s+/);
  1539. ns = new NodeSet();
  1540. for (i = 0, l = ids.length; i < l; i ++) {
  1541. id = ids[i];
  1542. /*@cc_on @if (@_jscript)
  1543. elm = all[id];
  1544. if (elm) {
  1545. if (elm.length) {
  1546. var elms = elm;
  1547. for (var j = 0, l0 = elms.length; j < l0; j ++) {
  1548. var elem = elms[j];
  1549. if (id == elem.id) {
  1550. ns.push(elem);
  1551. break;
  1552. }
  1553. }
  1554. }
  1555. else if (id == elm.id) {
  1556. ns.push(elm)
  1557. }
  1558. }
  1559. @else @*/
  1560. elm = doc.getElementById(id);
  1561. if (uai.opera && elm.id != id) {
  1562. var elms = doc.getElementsByName(id);
  1563. for (var j = 0, l0 = elms.length; j < l0; j ++) {
  1564. elm = elms[j];
  1565. if (elm.id == id) {
  1566. ns.push(elm);
  1567. }
  1568. }
  1569. }
  1570. else {
  1571. if (elm) ns.push(elm)
  1572. }
  1573. /*@end @*/
  1574. }
  1575. ns.isSorted = false;
  1576. return ns;
  1577. }, 'nodeset', false, []],
  1578. 'local-name': [function(ns) {
  1579. var nd;
  1580. switch (arguments.length) {
  1581. case 0:
  1582. nd = this.node;
  1583. break;
  1584. case 1:
  1585. if ((ns = ns.evaluate(this)).isNodeSet) {
  1586. nd = ns.first();
  1587. break;
  1588. }
  1589. default:
  1590. throw Error('Function local-name expects (nodeset?)');
  1591. break;
  1592. }
  1593. return '' + nd.nodeName.toLowerCase();
  1594. }, 'string', false, [true, false]],
  1595. name: [function(ns) {
  1596. // not implemented
  1597. return FunctionCall.funcs['local-name'][0].apply(this, arguments);
  1598. }, 'string', false, [true, false]],
  1599. 'namespace-uri': [function(ns) {
  1600. // not implemented
  1601. return '';
  1602. }, 'string', false, [true, false]],
  1603. string: [function(s) {
  1604. switch (arguments.length) {
  1605. case 0:
  1606. s = NodeUtil.to('string', this.node);
  1607. break;
  1608. case 1:
  1609. s = s.string(this);
  1610. break;
  1611. default:
  1612. throw Error('Function string expects (object?)');
  1613. break;
  1614. }
  1615. return s;
  1616. }, 'string', false, [true, false]],
  1617. concat: [function(s1, s2) {
  1618. if (arguments.length < 2) {
  1619. throw Error('Function concat expects (string, string[, ...])');
  1620. }
  1621. for (var t = '', i = 0, l = arguments.length; i < l; i ++) {
  1622. t += arguments[i].string(this);
  1623. }
  1624. return t;
  1625. }, 'string', false, []],
  1626. 'starts-with': [function(s1, s2) {
  1627. if (arguments.length != 2) {
  1628. throw Error('Function starts-with expects (string, string)');
  1629. }
  1630. s1 = s1.string(this);
  1631. s2 = s2.string(this);
  1632. return s1.indexOf(s2) == 0;
  1633. }, 'boolean', false, []],
  1634. contains: [function(s1, s2) {
  1635. if (arguments.length != 2) {
  1636. throw Error('Function contains expects (string, string)');
  1637. }
  1638. s1 = s1.string(this);
  1639. s2 = s2.string(this);
  1640. return s1.indexOf(s2) != -1;
  1641. }, 'boolean', false, []],
  1642. substring: [function(s, n1, n2) {
  1643. var a1, a2;
  1644. s = s.string(this);
  1645. n1 = n1.number(this);
  1646. switch (arguments.length) {
  1647. case 2:
  1648. n2 = s.length - n1 + 1;
  1649. break;
  1650. case 3:
  1651. n2 = n2.number(this);
  1652. break;
  1653. default:
  1654. throw Error('Function substring expects (string, string)');
  1655. break;
  1656. }
  1657. n1 = Math.round(n1);
  1658. n2 = Math.round(n2);
  1659. a1 = n1 - 1;
  1660. a2 = n1 + n2 - 1;
  1661. if (a2 == Infinity) {
  1662. return s.substring(a1 < 0 ? 0 : a1);
  1663. }
  1664. else {
  1665. return s.substring(a1 < 0 ? 0 : a1, a2)
  1666. }
  1667. }, 'string', false, []],
  1668. 'substring-before': [function(s1, s2) {
  1669. var n;
  1670. if (arguments.length != 2) {
  1671. throw Error('Function substring-before expects (string, string)');
  1672. }
  1673. s1 = s1.string(this);
  1674. s2 = s2.string(this);
  1675. n = s1.indexOf(s2);
  1676. if (n == -1) return '';
  1677. return s1.substring(0, n);
  1678. }, 'string', false, []],
  1679. 'substring-after': [function(s1, s2) {
  1680. if (arguments.length != 2) {
  1681. throw Error('Function substring-after expects (string, string)');
  1682. }
  1683. s1 = s1.string(this);
  1684. s2 = s2.string(this);
  1685. var n = s1.indexOf(s2);
  1686. if (n == -1) return '';
  1687. return s1.substring(n + s2.length);
  1688. }, 'string', false, []],
  1689. 'string-length': [function(s) {
  1690. switch (arguments.length) {
  1691. case 0:
  1692. s = NodeUtil.to('string', this.node);
  1693. break;
  1694. case 1:
  1695. s = s.string(this);
  1696. break;
  1697. default:
  1698. throw Error('Function string-length expects (string?)');
  1699. break;
  1700. }
  1701. return s.length;
  1702. }, 'number', false, [true, false]],
  1703. 'normalize-space': [function(s) {
  1704. switch (arguments.length) {
  1705. case 0:
  1706. s = NodeUtil.to('string', this.node);
  1707. break;
  1708. case 1:
  1709. s = s.string(this);
  1710. break;
  1711. default:
  1712. throw Error('Function normalize-space expects (string?)');
  1713. break;
  1714. }
  1715. return s.replace(/\s+/g, ' ').replace(/^ /, '').replace(/ $/, '');
  1716. }, 'string', false, [true, false]],
  1717. translate: [function(s1, s2, s3) {
  1718. if (arguments.length != 3) {
  1719. throw Error('Function translate expects (string, string, string)');
  1720. }
  1721. s1 = s1.string(this);
  1722. s2 = s2.string(this);
  1723. s3 = s3.string(this);
  1724. var map = [];
  1725. for (var i = 0, l = s2.length; i < l; i ++) {
  1726. var ch = s2.charAt(i);
  1727. if (!map[ch]) map[ch] = s3.charAt(i) || '';
  1728. }
  1729. for (var t = '', i = 0, l = s1.length; i < l; i ++) {
  1730. var ch = s1.charAt(i);
  1731. var replace = map[ch]
  1732. t += (replace != undefined) ? replace : ch;
  1733. }
  1734. return t;
  1735. }, 'string', false, []],
  1736. 'boolean': [function(b) {
  1737. if (arguments.length != 1) {
  1738. throw Error('Function boolean expects (object)');
  1739. }
  1740. return b.bool(this)
  1741. }, 'boolean', false, []],
  1742. not: [function(b) {
  1743. if (arguments.length != 1) {
  1744. throw Error('Function not expects (object)');
  1745. }
  1746. return !b.bool(this)
  1747. }, 'boolean', false, []],
  1748. 'true': [function() {
  1749. if (arguments.length != 0) {
  1750. throw Error('Function true expects ()');
  1751. }
  1752. return true;
  1753. }, 'boolean', false, []],
  1754. 'false': [function() {
  1755. if (arguments.length != 0) {
  1756. throw Error('Function false expects ()');
  1757. }
  1758. return false;
  1759. }, 'boolean', false, []],
  1760. lang: [function(s) {
  1761. // not implemented
  1762. return false;
  1763. }, 'boolean', false, []],
  1764. number: [function(n) {
  1765. switch (arguments.length) {
  1766. case 0:
  1767. n = NodeUtil.to('number', this.node);
  1768. break;
  1769. case 1:
  1770. n = n.number(this);
  1771. break;
  1772. default:
  1773. throw Error('Function number expects (object?)');
  1774. break;
  1775. }
  1776. return n;
  1777. }, 'number', false, [true, false]],
  1778. sum: [function(ns) {
  1779. var nodes, n, i, l;
  1780. if (arguments.length != 1 || !(ns = ns.evaluate(this)).isNodeSet) {
  1781. throw Error('Function sum expects (nodeset)');
  1782. }
  1783. nodes = ns.list();
  1784. n = 0;
  1785. for (i = 0, l = nodes.length; i < l; i ++) {
  1786. n += NodeUtil.to('number', nodes[i]);
  1787. }
  1788. return n;
  1789. }, 'number', false, []],
  1790. floor: [function(n) {
  1791. if (arguments.length != 1) {
  1792. throw Error('Function floor expects (number)');
  1793. }
  1794. n = n.number(this);
  1795. return Math.floor(n);
  1796. }, 'number', false, []],
  1797. ceiling: [function(n) {
  1798. if (arguments.length != 1) {
  1799. throw Error('Function ceiling expects (number)');
  1800. }
  1801. n = n.number(this);
  1802. return Math.ceil(n);
  1803. }, 'number', false, []],
  1804. round: [function(n) {
  1805. if (arguments.length != 1) {
  1806. throw Error('Function round expects (number)');
  1807. }
  1808. n = n.number(this);
  1809. return Math.round(n);
  1810. }, 'number', false, []]
  1811. };
  1812. FunctionCall.parse = function(lexer) {
  1813. var expr, func = new FunctionCall(lexer.next());
  1814. lexer.next();
  1815. while (lexer.peek() != ')') {
  1816. if (lexer.empty()) {
  1817. throw Error('missing function argument list');
  1818. }
  1819. expr = BinaryExpr.parse(lexer);
  1820. func.arg(expr);
  1821. if (lexer.peek() != ',') break;
  1822. lexer.next();
  1823. }
  1824. if (lexer.empty()) {
  1825. throw Error('unclosed function argument list');
  1826. }
  1827. if (lexer.next() != ')') {
  1828. lexer.back();
  1829. throw Error('bad token: ' + lexer.next());
  1830. }
  1831. return func
  1832. };
  1833. FunctionCall.prototype = new BaseExpr();
  1834. FunctionCall.prototype.evaluate = function (ctx) {
  1835. return this.func.apply(ctx, this.args);
  1836. };
  1837. FunctionCall.prototype.arg = function(arg) {
  1838. this.args.push(arg);
  1839. if (arg.needContextPosition) {
  1840. this.needContextPosition = true;
  1841. }
  1842. var args = this.args;
  1843. if (arg.needContextNode) {
  1844. args.needContexNode = true;
  1845. }
  1846. this.needContextNode = args.needContextNode ||
  1847. this.needContextNodeInfo[args.length];
  1848. };
  1849. FunctionCall.prototype.show = function(indent) {
  1850. indent = indent || '';
  1851. var t = '';
  1852. t += indent + 'function: ' + this.name + '\n';
  1853. indent += ' ';
  1854. if (this.args.length) {
  1855. t += indent + 'arguments: ' + '\n';
  1856. indent += ' ';
  1857. for (var i = 0; i < this.args.length; i ++) {
  1858. t += this.args[i].show(indent);
  1859. }
  1860. }
  1861. return t;
  1862. };
  1863. /*@cc_on @if (@_jscript)
  1864. var NodeWrapper = function(node, sourceIndex, subIndex, attributeName) {
  1865. this.node = node;
  1866. this.nodeType = node.nodeType;
  1867. this.sourceIndex = sourceIndex;
  1868. this.subIndex = subIndex;
  1869. this.attributeName = attributeName || '';
  1870. this.order = String.fromCharCode(sourceIndex) + String.fromCharCode(subIndex) + attributeName;
  1871. };
  1872. NodeWrapper.prototype.toString = function() {
  1873. return this.order;
  1874. };
  1875. @else @*/
  1876. var NodeID = {
  1877. uuid: 1,
  1878. get: function(node) {
  1879. return node.__jsxpath_id__ || (node.__jsxpath_id__ = this.uuid++);
  1880. }
  1881. };
  1882. /*@end @*/
  1883. if (!window.NodeSet && window.defaultConfig)
  1884. window.NodeSet = null;
  1885. NodeSet = function() {
  1886. this.length = 0;
  1887. this.nodes = [];
  1888. this.seen = {};
  1889. this.idIndexMap = null;
  1890. this.reserveDels = [];
  1891. };
  1892. NodeSet.prototype.isNodeSet = true;
  1893. NodeSet.prototype.isSorted = true;
  1894. /*@_cc_on
  1895. NodeSet.prototype.shortcut = true;
  1896. @*/
  1897. NodeSet.prototype.merge = function(nodeset) {
  1898. this.isSorted = false;
  1899. if (nodeset.only) {
  1900. return this.push(nodeset.only);
  1901. }
  1902. if (this.only){
  1903. var only = this.only;
  1904. delete this.only;
  1905. this.push(only);
  1906. this.length --;
  1907. }
  1908. var nodes = nodeset.nodes;
  1909. for (var i = 0, l = nodes.length; i < l; i ++) {
  1910. this._add(nodes[i]);
  1911. }
  1912. };
  1913. NodeSet.prototype.sort = function() {
  1914. if (this.only) return;
  1915. if (this.sortOff) return;
  1916. if (!this.isSorted) {
  1917. this.isSorted = true;
  1918. this.idIndexMap = null;
  1919. /*@cc_on
  1920. if (this.shortcut) {
  1921. this.nodes.sort();
  1922. }
  1923. else {
  1924. this.nodes.sort(function(a, b) {
  1925. var result;
  1926. result = a.sourceIndex - b.sourceIndex;
  1927. if (result == 0)
  1928. return a.subIndex - a.subIndex;
  1929. else
  1930. return result;
  1931. });
  1932. }
  1933. return;
  1934. @*/
  1935. var nodes = this.nodes;
  1936. nodes.sort(function(a, b) {
  1937. if (a == b) return 0;
  1938. if (a.compareDocumentPosition) {
  1939. var result = a.compareDocumentPosition(b);
  1940. if (result & 2) return 1;
  1941. if (result & 4) return -1;
  1942. return 0;
  1943. }
  1944. else {
  1945. var node1 = a, node2 = b, ancestor1 = a, ancestor2 = b, deep1 = 0, deep2 = 0;
  1946. while(ancestor1 = ancestor1.parentNode) deep1 ++;
  1947. while(ancestor2 = ancestor2.parentNode) deep2 ++;
  1948. // same deep
  1949. if (deep1 > deep2) {
  1950. while (deep1-- != deep2) node1 = node1.parentNode;
  1951. if (node1 == node2) return 1;
  1952. }
  1953. else if (deep2 > deep1) {
  1954. while (deep2-- != deep1) node2 = node2.parentNode;
  1955. if (node1 == node2) return -1;
  1956. }
  1957. while ((ancestor1 = node1.parentNode) != (ancestor2 = node2.parentNode)) {
  1958. node1 = ancestor1;
  1959. node2 = ancestor2;
  1960. }
  1961. // node1 is node2's sibling
  1962. while (node1 = node1.nextSibling) if (node1 == node2) return -1;
  1963. return 1;
  1964. }
  1965. });
  1966. }
  1967. };
  1968. /*@cc_on @if (@_jscript)
  1969. NodeSet.prototype.sourceOffset = 1;
  1970. NodeSet.prototype.subOffset = 2;
  1971. NodeSet.prototype.createWrapper = function(node) {
  1972. var parent, child, attributes, attributesLength, sourceIndex, subIndex, attributeName;
  1973. sourceIndex = node.sourceIndex;
  1974. if (typeof sourceIndex != 'number') {
  1975. type = node.nodeType;
  1976. switch (type) {
  1977. case 2:
  1978. parent = node.parentNode;
  1979. sourceIndex = node.parentSourceIndex;
  1980. subIndex = -1;
  1981. attributeName = node.nodeName;
  1982. break;
  1983. case 9:
  1984. subIndex = -2;
  1985. sourceIndex = -1;
  1986. break;
  1987. default:
  1988. child = node;
  1989. subIndex = 0;
  1990. do {
  1991. subIndex ++;
  1992. sourceIndex = child.sourceIndex;
  1993. if (sourceIndex) {
  1994. parent = child;
  1995. child = child.lastChild;
  1996. if (!child) {
  1997. child = parent;
  1998. break;
  1999. }
  2000. subIndex ++;
  2001. }
  2002. } while (child = child.previousSibling);
  2003. if (!sourceIndex) {
  2004. sourceIndex = node.parentNode.sourceIndex;
  2005. }
  2006. break;
  2007. }
  2008. }
  2009. else {
  2010. subIndex = -2;
  2011. }
  2012. sourceIndex += this.sourceOffset;
  2013. subIndex += this.subOffset;
  2014. return new NodeWrapper(node, sourceIndex, subIndex, attributeName);
  2015. };
  2016. NodeSet.prototype.reserveDelBySourceIndexAndSubIndex = function(sourceIndex, subIndex, offset, reverse) {
  2017. var map = this.createIdIndexMap();
  2018. var index;
  2019. if ((map = map[sourceIndex]) && (index = map[subIndex])) {
  2020. if (reverse && (this.length - offset - 1) > index || !reverse && offset < index) {
  2021. var obj = {
  2022. value: index,
  2023. order: String.fromCharCode(index),
  2024. toString: function() { return this.order },
  2025. valueOf: function() { return this.value }
  2026. };
  2027. this.reserveDels.push(obj);
  2028. }
  2029. }
  2030. };
  2031. @else @*/
  2032. NodeSet.prototype.reserveDelByNodeID = function(id, offset, reverse) {
  2033. var map = this.createIdIndexMap();
  2034. var index;
  2035. if (index = map[id]) {
  2036. if (reverse && (this.length - offset - 1) > index || !reverse && offset < index) {
  2037. var obj = {
  2038. value: index,
  2039. order: String.fromCharCode(index),
  2040. toString: function() { return this.order },
  2041. valueOf: function() { return this.value }
  2042. };
  2043. this.reserveDels.push(obj);
  2044. }
  2045. }
  2046. };
  2047. /*@end @*/
  2048. NodeSet.prototype.reserveDelByNode = function(node, offset, reverse) {
  2049. /*@cc_on @if (@_jscript)
  2050. node = this.createWrapper(node);
  2051. this.reserveDelBySourceIndexAndSubIndex(node.sourceIndex, node.subIndex, offset, reverse);
  2052. @else @*/
  2053. this.reserveDelByNodeID(NodeID.get(node), offset, reverse);
  2054. /*@end @*/
  2055. };
  2056. NodeSet.prototype.doDel = function() {
  2057. if (!this.reserveDels.length) return;
  2058. if (this.length < 0x10000) {
  2059. var dels = this.reserveDels.sort(function(a, b) { return b - a });
  2060. }
  2061. else {
  2062. var dels = this.reserveDels.sort(function(a, b) { return b - a });
  2063. }
  2064. for (var i = 0, l = dels.length; i < l; i ++) {
  2065. this.del(dels[i]);
  2066. }
  2067. this.reserveDels = [];
  2068. this.idIndexMap = null;
  2069. };
  2070. NodeSet.prototype.createIdIndexMap = function() {
  2071. if (this.idIndexMap) {
  2072. return this.idIndexMap;
  2073. }
  2074. else {
  2075. var map = this.idIndexMap = {};
  2076. var nodes = this.nodes;
  2077. for (var i = 0, l = nodes.length; i < l; i ++) {
  2078. var node = nodes[i];
  2079. /*@cc_on @if (@_jscript)
  2080. var sourceIndex = node.sourceIndex;
  2081. var subIndex = node.subIndex;
  2082. if (!map[sourceIndex]) map[sourceIndex] = {};
  2083. map[sourceIndex][subIndex] = i;
  2084. @else @*/
  2085. var id = NodeID.get(node);
  2086. map[id] = i;
  2087. /*@end @*/
  2088. }
  2089. return map;
  2090. }
  2091. };
  2092. NodeSet.prototype.del = function(index) {
  2093. this.length --;
  2094. if (this.only) {
  2095. delete this.only;
  2096. }
  2097. else {
  2098. var node = this.nodes.splice(index, 1)[0];
  2099. if (this._first == node) {
  2100. delete this._first;
  2101. delete this._firstSourceIndex;
  2102. delete this._firstSubIndex;
  2103. }
  2104. /*@cc_on @if (@_jscript)
  2105. delete this.seen[node.sourceIndex][node.subIndex];
  2106. @else @*/
  2107. delete this.seen[NodeID.get(node)];
  2108. /*@end @*/
  2109. }
  2110. };
  2111. NodeSet.prototype.delDescendant = function(elm, offset) {
  2112. if (this.only) return;
  2113. var nodeType = elm.nodeType;
  2114. if (nodeType != 1 && nodeType != 9) return;
  2115. if (uai.applewebkit4) return;
  2116. // element || document
  2117. if (!elm.contains) {
  2118. if (nodeType == 1) {
  2119. var _elm = elm;
  2120. elm = {
  2121. contains: function(node) {
  2122. return node.compareDocumentPosition(_elm) & 8;
  2123. }
  2124. };
  2125. }
  2126. else {
  2127. // document
  2128. elm = {
  2129. contains: function() {
  2130. return true;
  2131. }
  2132. };
  2133. }
  2134. }
  2135. var nodes = this.nodes;
  2136. for (var i = offset + 1; i < nodes.length; i ++) {
  2137. /*@cc_on @if (@_jscript)
  2138. if (nodes[i].node.nodeType == 1 && elm.contains(nodes[i].node)) {
  2139. @else @*/
  2140. if (elm.contains(nodes[i])) {
  2141. /*@end @*/
  2142. this.del(i);
  2143. i --;
  2144. }
  2145. }
  2146. };
  2147. NodeSet.prototype._add = function(node, reverse) {
  2148. /*@cc_on @if (@_jscript)
  2149. var first, firstSourceIndex, firstSubIndex, sourceIndex, subIndex, attributeName;
  2150. sourceIndex = node.sourceIndex;
  2151. subIndex = node.subIndex;
  2152. attributeName = node.attributeName;
  2153. seen = this.seen;
  2154. seen = seen[sourceIndex] || (seen[sourceIndex] = {});
  2155. if (node.nodeType == 2) {
  2156. seen = seen[subIndex] || (seen[subIndex] = {});
  2157. if (seen[attributeName]) {
  2158. return true;
  2159. }
  2160. seen[attributeName] = true;
  2161. }
  2162. else {
  2163. if (seen[subIndex]) {
  2164. return true;
  2165. }
  2166. seen[subIndex] = true;
  2167. }
  2168. if (sourceIndex >= 0x10000 || subIndex >= 0x10000) {
  2169. this.shortcut = false;
  2170. }
  2171. // if this._first is undefined and this.nodes is not empty
  2172. // then first node shortcut is disabled.
  2173. if (this._first || this.nodes.length == 0) {
  2174. first = this._first;
  2175. firstSourceIndex = this._firstSourceIndex;
  2176. firstSubIndex = this._firstSubIndex;
  2177. if (!first || firstSourceIndex > sourceIndex || (firstSourceIndex == sourceIndex && firstSubIndex > subIndex)) {
  2178. this._first = node;
  2179. this._firstSourceIndex = sourceIndex;
  2180. this._firstSubIndex = subIndex
  2181. }
  2182. }
  2183. @else @*/
  2184. var seen = this.seen;
  2185. var id = NodeID.get(node);
  2186. if (seen[id]) return true;
  2187. seen[id] = true;
  2188. /*@end @*/
  2189. this.length++;
  2190. if (reverse)
  2191. this.nodes.unshift(node);
  2192. else
  2193. this.nodes.push(node);
  2194. };
  2195. NodeSet.prototype.unshift = function(node) {
  2196. if (!this.length) {
  2197. this.length ++;
  2198. this.only = node;
  2199. return
  2200. }
  2201. if (this.only){
  2202. var only = this.only;
  2203. delete this.only;
  2204. this.unshift(only);
  2205. this.length --;
  2206. }
  2207. /*@cc_on
  2208. node = this.createWrapper(node);
  2209. @*/
  2210. return this._add(node, true);
  2211. };
  2212. NodeSet.prototype.push = function(node) {
  2213. if (!this.length) {
  2214. this.length ++;
  2215. this.only = node;
  2216. return;
  2217. }
  2218. if (this.only) {
  2219. var only = this.only;
  2220. delete this.only;
  2221. this.push(only);
  2222. this.length --;
  2223. }
  2224. /*@cc_on
  2225. node = this.createWrapper(node);
  2226. @*/
  2227. return this._add(node);
  2228. };
  2229. NodeSet.prototype.first = function() {
  2230. if (this.only) return this.only;
  2231. /*@cc_on
  2232. if (this._first) return this._first.node;
  2233. if (this.nodes.length > 1) this.sort();
  2234. var node = this.nodes[0];
  2235. return node ? node.node : undefined;
  2236. @*/
  2237. if (this.nodes.length > 1) this.sort();
  2238. return this.nodes[0];
  2239. };
  2240. NodeSet.prototype.list = function() {
  2241. if (this.only) return [this.only];
  2242. this.sort();
  2243. /*@cc_on
  2244. var i, l, nodes, results;
  2245. nodes = this.nodes;
  2246. results = [];
  2247. for (i = 0, l = nodes.length; i < l; i ++) {
  2248. results.push(nodes[i].node);
  2249. }
  2250. return results;
  2251. @*/
  2252. return this.nodes;
  2253. };
  2254. NodeSet.prototype.string = function() {
  2255. var node = this.only || this.first();
  2256. return node ? NodeUtil.to('string', node) : '';
  2257. };
  2258. NodeSet.prototype.bool = function() {
  2259. return !! (this.length || this.only);
  2260. };
  2261. NodeSet.prototype.number = function() {
  2262. return + this.string();
  2263. };
  2264. NodeSet.prototype.iterator = function(reverse) {
  2265. this.sort();
  2266. var nodeset = this;
  2267. if (!reverse) {
  2268. var count = 0;
  2269. return function() {
  2270. if (nodeset.only && count++ == 0) return nodeset.only;
  2271. /*@cc_on @if(@_jscript)
  2272. var wrapper = nodeset.nodes[count++];
  2273. if (wrapper) return wrapper.node;
  2274. return undefined;
  2275. @else @*/
  2276. return nodeset.nodes[count++];
  2277. /*@end @*/
  2278. };
  2279. }
  2280. else {
  2281. var count = 0;
  2282. return function() {
  2283. var index = nodeset.length - (count++) - 1;
  2284. if (nodeset.only && index == 0) return nodeset.only;
  2285. /*@cc_on @if(@_jscript)
  2286. var wrapper = nodeset.nodes[index];
  2287. if (wrapper) return wrapper.node;
  2288. return undefined;
  2289. @else @*/
  2290. return nodeset.nodes[index];
  2291. /*@end @*/
  2292. };
  2293. }
  2294. };
  2295. var install = function(win) {
  2296. win = win || this;
  2297. win.XPathExpression = function(expr) {
  2298. if (!expr.length) {
  2299. throw Error('no expression');
  2300. }
  2301. var lexer = this.lexer = Lexer(expr);
  2302. if (lexer.empty()) {
  2303. throw Error('no expression');
  2304. }
  2305. this.expr = BinaryExpr.parse(lexer);
  2306. if (!lexer.empty()) {
  2307. throw Error('bad token: ' + lexer.next());
  2308. }
  2309. };
  2310. win.XPathExpression.prototype.evaluate = function(node, type) {
  2311. return new XPathResult(this.expr.evaluate(new Ctx(node)), type);
  2312. };
  2313. win.XPathResult = function (value, type) {
  2314. if (type == 0) {
  2315. switch (typeof value) {
  2316. case 'object': type ++; // 4
  2317. case 'boolean': type ++; // 3
  2318. case 'string': type ++; // 2
  2319. case 'number': type ++; // 1
  2320. }
  2321. }
  2322. this.resultType = type;
  2323. switch (type) {
  2324. case 1:
  2325. this.numberValue = value.isNodeSet ? value.number() : +value;
  2326. return;
  2327. case 2:
  2328. this.stringValue = value.isNodeSet ? value.string() : '' + value;
  2329. return;
  2330. case 3:
  2331. this.booleanValue = value.isNodeSet ? value.bool() : !! value;
  2332. return;
  2333. case 4: case 5: case 6: case 7:
  2334. this.nodes = value.list();
  2335. this.snapshotLength = value.length;
  2336. this.index = 0;
  2337. this.invalidIteratorState = false;
  2338. break;
  2339. case 8: case 9:
  2340. this.singleNodeValue = value.first();
  2341. return;
  2342. }
  2343. };
  2344. win.XPathResult.prototype.iterateNext = function() { return this.nodes[this.index++] };
  2345. win.XPathResult.prototype.snapshotItem = function(i) { return this.nodes[i] };
  2346. win.XPathResult.ANY_TYPE = 0;
  2347. win.XPathResult.NUMBER_TYPE = 1;
  2348. win.XPathResult.STRING_TYPE = 2;
  2349. win.XPathResult.BOOLEAN_TYPE = 3;
  2350. win.XPathResult.UNORDERED_NODE_ITERATOR_TYPE = 4;
  2351. win.XPathResult.ORDERED_NODE_ITERATOR_TYPE = 5;
  2352. win.XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE = 6;
  2353. win.XPathResult.ORDERED_NODE_SNAPSHOT_TYPE = 7;
  2354. win.XPathResult.ANY_UNORDERED_NODE_TYPE = 8;
  2355. win.XPathResult.FIRST_ORDERED_NODE_TYPE = 9;
  2356. win.document.createExpression = function(expr) {
  2357. return new XPathExpression(expr, null);
  2358. };
  2359. win.document.evaluate = function(expr, context, _, type) {
  2360. return document.createExpression(expr, null).evaluate(context, type);
  2361. };
  2362. };
  2363. var win;
  2364. if (config.targetFrame) {
  2365. var frame = document.getElementById(config.targetFrame);
  2366. if (frame) win = frame.contentWindow;
  2367. }
  2368. install(win || window);
  2369. })();
  2370. // Thanks for reading this source code. We love JavaScript.