envjs19 0.3.8.20101029121421

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (279) hide show
  1. data/.jslintrbrc +30 -0
  2. data/.project +17 -0
  3. data/CHANGELOG.rdoc +57 -0
  4. data/DTD/xhtml-lat1.ent +196 -0
  5. data/DTD/xhtml-special.ent +80 -0
  6. data/DTD/xhtml-symbol.ent +237 -0
  7. data/DTD/xhtml.soc +14 -0
  8. data/DTD/xhtml1-frameset.dtd +1235 -0
  9. data/DTD/xhtml1-strict.dtd +978 -0
  10. data/DTD/xhtml1-transitional.dtd +1201 -0
  11. data/DTD/xhtml1.dcl +192 -0
  12. data/Makefile +7 -0
  13. data/Manifest.txt +280 -0
  14. data/README.rdoc +65 -0
  15. data/Rakefile +196 -0
  16. data/Wakefile +11 -0
  17. data/bin/envjsrb +257 -0
  18. data/build.properties +9 -0
  19. data/build.xml +247 -0
  20. data/gm/jquery.js +6002 -0
  21. data/gm/mainx.js +2648 -0
  22. data/gm/sensx.js +135 -0
  23. data/gm/t.js +6 -0
  24. data/gm/x.html +76 -0
  25. data/htmlparser/BrowserTreeBuilder.java +456 -0
  26. data/htmlparser/README +34 -0
  27. data/htmlparser/build.sh +38 -0
  28. data/jsl/jsl +0 -0
  29. data/jsl/jsl.default.conf +129 -0
  30. data/jsl/jsl.exe +0 -0
  31. data/lib/envjs.rb +35 -0
  32. data/lib/envjs/event_loop.js +206 -0
  33. data/lib/envjs/net.rb +3 -0
  34. data/lib/envjs/net/cgi.rb +94 -0
  35. data/lib/envjs/net/file.rb +69 -0
  36. data/lib/envjs/options.rb +11 -0
  37. data/lib/envjs/runtime.rb +346 -0
  38. data/lib/envjs/tempfile.rb +24 -0
  39. data/licenses/GPL-LICENSE.txt +278 -0
  40. data/licenses/MIT-LICENSE.txt +20 -0
  41. data/src/base64.js +80 -0
  42. data/src/build.js +6 -0
  43. data/src/cruft/bad.html +24 -0
  44. data/src/cruft/dom.js +606 -0
  45. data/src/cruft/element.js +297 -0
  46. data/src/cruft/good.html +30 -0
  47. data/src/cruft/good.js +32 -0
  48. data/src/cruft/internal.js +81 -0
  49. data/src/cruft/parser.js +458 -0
  50. data/src/css/properties.js +293 -0
  51. data/src/css/rule.js +22 -0
  52. data/src/css/sizzle.js +717 -0
  53. data/src/css/stylesheet.js +52 -0
  54. data/src/dom/attr.js +55 -0
  55. data/src/dom/cdatasection.js +31 -0
  56. data/src/dom/characterdata.js +119 -0
  57. data/src/dom/comment.js +30 -0
  58. data/src/dom/doctype.js +9 -0
  59. data/src/dom/document.js +1023 -0
  60. data/src/dom/dom.js +134 -0
  61. data/src/dom/element.js +217 -0
  62. data/src/dom/entities.js +273 -0
  63. data/src/dom/exception.js +28 -0
  64. data/src/dom/fragment.js +37 -0
  65. data/src/dom/implementation.js +140 -0
  66. data/src/dom/instruction.js +51 -0
  67. data/src/dom/namednodemap.js +374 -0
  68. data/src/dom/namespace.js +50 -0
  69. data/src/dom/node.js +618 -0
  70. data/src/dom/nodelist.js +195 -0
  71. data/src/dom/parser.js +1207 -0
  72. data/src/dom/text.js +73 -0
  73. data/src/event/event.js +47 -0
  74. data/src/event/mouseevent.js +4 -0
  75. data/src/event/uievent.js +8 -0
  76. data/src/html/a.js +110 -0
  77. data/src/html/anchor.js +80 -0
  78. data/src/html/area.js +57 -0
  79. data/src/html/base.js +26 -0
  80. data/src/html/blockquote-q.js +19 -0
  81. data/src/html/body.js +19 -0
  82. data/src/html/button.js +21 -0
  83. data/src/html/canvas.js +14 -0
  84. data/src/html/col-colgroup.js +49 -0
  85. data/src/html/collection.js +72 -0
  86. data/src/html/cookie.js +153 -0
  87. data/src/html/del-ins.js +25 -0
  88. data/src/html/div.js +28 -0
  89. data/src/html/document.js +364 -0
  90. data/src/html/element.js +382 -0
  91. data/src/html/fieldset.js +19 -0
  92. data/src/html/form.js +484 -0
  93. data/src/html/frame.js +89 -0
  94. data/src/html/frameset.js +25 -0
  95. data/src/html/head.js +44 -0
  96. data/src/html/html.js +0 -0
  97. data/src/html/htmlparser.js +340 -0
  98. data/src/html/iframe.js +26 -0
  99. data/src/html/image.js +0 -0
  100. data/src/html/img.js +62 -0
  101. data/src/html/input-elements.js +307 -0
  102. data/src/html/input.js +65 -0
  103. data/src/html/label.js +26 -0
  104. data/src/html/legend.js +19 -0
  105. data/src/html/link.js +82 -0
  106. data/src/html/map.js +22 -0
  107. data/src/html/meta.js +37 -0
  108. data/src/html/object.js +89 -0
  109. data/src/html/optgroup.js +25 -0
  110. data/src/html/option.js +103 -0
  111. data/src/html/param.js +38 -0
  112. data/src/html/script.js +122 -0
  113. data/src/html/select.js +132 -0
  114. data/src/html/style.js +31 -0
  115. data/src/html/table.js +199 -0
  116. data/src/html/tbody-thead-tfoot.js +92 -0
  117. data/src/html/td-th.js +18 -0
  118. data/src/html/textarea.js +31 -0
  119. data/src/html/title.js +20 -0
  120. data/src/html/tr.js +114 -0
  121. data/src/intro.js +141 -0
  122. data/src/outro.js +70 -0
  123. data/src/parser/html5.detailed.js +10762 -0
  124. data/src/parser/html5.min.js +503 -0
  125. data/src/parser/html5.pretty.js +10815 -0
  126. data/src/parser/intro.js +42 -0
  127. data/src/parser/outro.js +9 -0
  128. data/src/platform/core.js +323 -0
  129. data/src/platform/johnson.js +484 -0
  130. data/src/platform/rhino.js +327 -0
  131. data/src/platform/static/intro.js +41 -0
  132. data/src/platform/static/outro.js +30 -0
  133. data/src/profile/aop.js +238 -0
  134. data/src/profile/profile.js +402 -0
  135. data/src/serializer/xml.js +21 -0
  136. data/src/svg/animatedstring.js +25 -0
  137. data/src/svg/document.js +25 -0
  138. data/src/svg/element.js +22 -0
  139. data/src/svg/locatable.js +17 -0
  140. data/src/svg/rect.js +18 -0
  141. data/src/svg/rectelement.js +24 -0
  142. data/src/svg/stylable.js +49 -0
  143. data/src/svg/svgelement.js +22 -0
  144. data/src/svg/transformable.js +15 -0
  145. data/src/window/css.js +15 -0
  146. data/src/window/dialog.js +16 -0
  147. data/src/window/document.js +28 -0
  148. data/src/window/event.js +265 -0
  149. data/src/window/history.js +62 -0
  150. data/src/window/location.js +156 -0
  151. data/src/window/navigator.js +48 -0
  152. data/src/window/screen.js +53 -0
  153. data/src/window/timer.js +21 -0
  154. data/src/window/window.js +284 -0
  155. data/src/window/xhr.js +135 -0
  156. data/src/xpath/expression.js +49 -0
  157. data/src/xpath/implementation.js +2505 -0
  158. data/src/xpath/result.js +67 -0
  159. data/src/xpath/util.js +551 -0
  160. data/src/xpath/xmltoken.js +149 -0
  161. data/src/xslt/COPYING +34 -0
  162. data/src/xslt/ajaxslt-0.8.1/AUTHORS +1 -0
  163. data/src/xslt/ajaxslt-0.8.1/ChangeLog +136 -0
  164. data/src/xslt/ajaxslt-0.8.1/Makefile +49 -0
  165. data/src/xslt/ajaxslt-0.8.1/README +102 -0
  166. data/src/xslt/ajaxslt-0.8.1/TODO +15 -0
  167. data/src/xslt/ajaxslt-0.8.1/dom.js +566 -0
  168. data/src/xslt/ajaxslt-0.8.1/dom_unittest.html +24 -0
  169. data/src/xslt/ajaxslt-0.8.1/dom_unittest.js +131 -0
  170. data/src/xslt/ajaxslt-0.8.1/simplelog.js +79 -0
  171. data/src/xslt/ajaxslt-0.8.1/test/xpath.html +18 -0
  172. data/src/xslt/ajaxslt-0.8.1/test/xpath_script.js +45 -0
  173. data/src/xslt/ajaxslt-0.8.1/test/xslt.html +58 -0
  174. data/src/xslt/ajaxslt-0.8.1/test/xslt_script.js +33 -0
  175. data/src/xslt/ajaxslt-0.8.1/unittestsuite.html +26 -0
  176. data/src/xslt/ajaxslt-0.8.1/xmltoken.js +149 -0
  177. data/src/xslt/ajaxslt-0.8.1/xmltoken_unittest.html +18 -0
  178. data/src/xslt/ajaxslt-0.8.1/xmltoken_unittest.js +811 -0
  179. data/src/xslt/ajaxslt-0.8.1/xpath_unittest.html +39 -0
  180. data/src/xslt/ajaxslt-0.8.1/xpath_unittest.js +557 -0
  181. data/src/xslt/ajaxslt-0.8.1/xpathdebug.js +234 -0
  182. data/src/xslt/ajaxslt-0.8.1/xslt_unittest.html +138 -0
  183. data/src/xslt/ajaxslt-0.8.1/xslt_unittest.js +68 -0
  184. data/src/xslt/implementation.js +625 -0
  185. data/src/xslt/processor.js +37 -0
  186. data/src/xslt/util.js +449 -0
  187. data/test/base64.js +80 -0
  188. data/test/call-load-test.js +15 -0
  189. data/test/data.js +45 -0
  190. data/test/debug.js +53 -0
  191. data/test/firebug/errorIcon.png +0 -0
  192. data/test/firebug/firebug.css +209 -0
  193. data/test/firebug/firebug.html +23 -0
  194. data/test/firebug/firebug.js +672 -0
  195. data/test/firebug/firebugx.js +10 -0
  196. data/test/firebug/infoIcon.png +0 -0
  197. data/test/firebug/warningIcon.png +0 -0
  198. data/test/fixtures/html/events.html +171 -0
  199. data/test/fixtures/html/iframe1.html +46 -0
  200. data/test/fixtures/html/iframe1a.html +46 -0
  201. data/test/fixtures/html/iframe2.html +45 -0
  202. data/test/fixtures/html/iframe3.html +28 -0
  203. data/test/fixtures/html/iframeN.html +57 -0
  204. data/test/fixtures/html/malformed.html +181 -0
  205. data/test/fixtures/html/scope.html +81 -0
  206. data/test/fixtures/html/trivial.html +19 -0
  207. data/test/fixtures/html/with_js.html +26 -0
  208. data/test/fixtures/images/icon-blue.png +0 -0
  209. data/test/fixtures/js/external_script.js +1 -0
  210. data/test/fixtures/js/script.js +1 -0
  211. data/test/fixtures/js/script_error.js +2 -0
  212. data/test/foo.html +8 -0
  213. data/test/foo.js +40 -0
  214. data/test/html/events.html +171 -0
  215. data/test/html/iframe1.html +46 -0
  216. data/test/html/iframe1a.html +46 -0
  217. data/test/html/iframe2.html +45 -0
  218. data/test/html/iframe3.html +30 -0
  219. data/test/html/iframeN.html +57 -0
  220. data/test/html/malformed.html +181 -0
  221. data/test/html/scope.html +87 -0
  222. data/test/html/script.js +1 -0
  223. data/test/html/trivial.html +19 -0
  224. data/test/html/with_js.html +26 -0
  225. data/test/index.html +328 -0
  226. data/test/java-prototype.js +9 -0
  227. data/test/jquery.js +6002 -0
  228. data/test/primary-tests.js +26 -0
  229. data/test/prototype-test.js +13 -0
  230. data/test/qunit.js +61 -0
  231. data/test/qunit/qunit/qunit.css +17 -0
  232. data/test/qunit/qunit/qunit.js +997 -0
  233. data/test/scope.html +19 -0
  234. data/test/scope.rb +24 -0
  235. data/test/smp/dmathieu/index.html +8 -0
  236. data/test/specs/dist/env.spec.js +1534 -0
  237. data/test/specs/envjs.spec.css +46 -0
  238. data/test/specs/parser/html.js +31 -0
  239. data/test/specs/parser/spec.html +40 -0
  240. data/test/specs/parser/xml.js +31 -0
  241. data/test/specs/qunit.bdd.js +210 -0
  242. data/test/specs/qunit.css +17 -0
  243. data/test/specs/qunit.js +997 -0
  244. data/test/specs/template/spec-0.js +31 -0
  245. data/test/specs/template/spec-1.js +31 -0
  246. data/test/specs/template/spec.html +40 -0
  247. data/test/specs/window/css.js +23 -0
  248. data/test/specs/window/dialog.js +25 -0
  249. data/test/specs/window/document.js +23 -0
  250. data/test/specs/window/event.js +25 -0
  251. data/test/specs/window/history.js +34 -0
  252. data/test/specs/window/location.js +34 -0
  253. data/test/specs/window/navigator.js +71 -0
  254. data/test/specs/window/screen.js +42 -0
  255. data/test/specs/window/spec.html +48 -0
  256. data/test/specs/window/timer.js +26 -0
  257. data/test/specs/window/window.js +53 -0
  258. data/test/specs/xhr/spec.html +47 -0
  259. data/test/specs/xhr/xhr.js +31 -0
  260. data/test/test.js +10 -0
  261. data/test/unit/dom.js +44 -0
  262. data/test/unit/elementmembers.js +92 -0
  263. data/test/unit/events.js +195 -0
  264. data/test/unit/fixtures/external_script.js +1 -0
  265. data/test/unit/form.js +40 -0
  266. data/test/unit/iframe.js +234 -0
  267. data/test/unit/insertion.js +23 -0
  268. data/test/unit/multi-window.js +212 -0
  269. data/test/unit/nu.validator.js +34 -0
  270. data/test/unit/onload.js +90 -0
  271. data/test/unit/parser.js +122 -0
  272. data/test/unit/prototypecompat.js +22 -0
  273. data/test/unit/proxy.js +6 -0
  274. data/test/unit/scope.js +209 -0
  275. data/test/unit/timer.js +115 -0
  276. data/test/unit/window.js +57 -0
  277. data/test/x.js +1 -0
  278. data/test/y.js +1 -0
  279. metadata +367 -0
@@ -0,0 +1,234 @@
1
+ // Copyright 2005 Google Inc.
2
+ // All Rights Reserved
3
+ //
4
+ // Debug stuff for the XPath parser. Also used by XSLT.
5
+
6
+ TokenExpr.prototype.toString = function() {
7
+ return this.value;
8
+ }
9
+
10
+ TokenExpr.prototype.parseTree = function(indent) {
11
+ var ret = indent + '[token] ' + this.value + '\n';
12
+ return ret;
13
+ }
14
+
15
+ LocationExpr.prototype.toString = function() {
16
+ var ret = '';
17
+ if (this.absolute) {
18
+ ret += '/';
19
+ }
20
+ for (var i = 0; i < this.steps.length; ++i) {
21
+ if (i > 0) {
22
+ ret += '/';
23
+ }
24
+ ret += this.steps[i].toString();
25
+ }
26
+ return ret;
27
+ }
28
+
29
+ LocationExpr.prototype.parseTree = function(indent) {
30
+ var ret = indent + '[location] ' +
31
+ (this.absolute ? 'absolute' : 'relative') + '\n';
32
+ for (var i = 0; i < this.steps.length; ++i) {
33
+ ret += this.steps[i].parseTree(indent + ' ');
34
+ }
35
+ return ret;
36
+ }
37
+
38
+ StepExpr.prototype.toString = function() {
39
+ var ret = this.axis + '::' + this.nodetest.toString();
40
+ for (var i = 0; i < this.predicate.length; ++i) {
41
+ ret += this.predicate[i].toString();
42
+ }
43
+ return ret;
44
+ }
45
+
46
+ StepExpr.prototype.parseTree = function(indent) {
47
+ var ret = indent + '[step]\n' +
48
+ indent + ' [axis] ' + this.axis + '\n' +
49
+ this.nodetest.parseTree(indent + ' ');
50
+ for (var i = 0; i < this.predicate.length; ++i) {
51
+ ret += this.predicate[i].parseTree(indent + ' ');
52
+ }
53
+ return ret;
54
+ }
55
+
56
+ NodeTestAny.prototype.toString = function() {
57
+ return 'node()';
58
+ }
59
+
60
+ NodeTestAny.prototype.parseTree = function(indent) {
61
+ return indent + '[nodetest] ' + this.toString() + '\n';
62
+ }
63
+
64
+ NodeTestElementOrAttribute.prototype.toString = function() {
65
+ return '*';
66
+ }
67
+
68
+ NodeTestElementOrAttribute.prototype.parseTree = NodeTestAny.prototype.parseTree;
69
+
70
+ NodeTestText.prototype.toString = function() {
71
+ return 'text()';
72
+ }
73
+
74
+ NodeTestText.prototype.parseTree = NodeTestAny.prototype.parseTree;
75
+
76
+ NodeTestComment.prototype.toString = function() {
77
+ return 'comment()';
78
+ }
79
+
80
+ NodeTestComment.prototype.parseTree = NodeTestAny.prototype.parseTree;
81
+
82
+ NodeTestPI.prototype.toString = function() {
83
+ return 'processing-instruction()';
84
+ }
85
+
86
+ NodeTestPI.prototype.parseTree = NodeTestAny.prototype.parseTree;
87
+
88
+ NodeTestNC.prototype.toString = function() {
89
+ return this.nsprefix + ':*';
90
+ }
91
+
92
+ NodeTestNC.prototype.parseTree = NodeTestAny.prototype.parseTree;
93
+
94
+ NodeTestName.prototype.toString = function() {
95
+ return this.name;
96
+ }
97
+
98
+ NodeTestName.prototype.parseTree = NodeTestAny.prototype.parseTree;
99
+
100
+ PredicateExpr.prototype.toString = function() {
101
+ var ret = '[' + this.expr.toString() + ']';
102
+ return ret;
103
+ }
104
+
105
+ PredicateExpr.prototype.parseTree = function(indent) {
106
+ var ret = indent + '[predicate]\n' + this.expr.parseTree(indent + ' ');
107
+ return ret;
108
+ }
109
+
110
+ FunctionCallExpr.prototype.toString = function() {
111
+ var ret = this.name.value + '(';
112
+ for (var i = 0; i < this.args.length; ++i) {
113
+ if (i > 0) {
114
+ ret += ', ';
115
+ }
116
+ ret += this.args[i].toString();
117
+ }
118
+ ret += ')';
119
+ return ret;
120
+ }
121
+
122
+ FunctionCallExpr.prototype.parseTree = function(indent) {
123
+ var ret = indent + '[function call] ' + this.name.value + '\n';
124
+ for (var i = 0; i < this.args.length; ++i) {
125
+ ret += this.args[i].parseTree(indent + ' ');
126
+ }
127
+ return ret;
128
+ }
129
+
130
+ UnionExpr.prototype.toString = function() {
131
+ return this.expr1.toString() + ' | ' + this.expr2.toString();
132
+ }
133
+
134
+ UnionExpr.prototype.parseTree = function(indent) {
135
+ var ret = indent + '[union]\n' +
136
+ this.expr1.parseTree(indent + ' ') +
137
+ this.expr2.parseTree(indent + ' ');
138
+ return ret;
139
+ }
140
+
141
+ PathExpr.prototype.toString = function() {
142
+ var ret = '{path: {' + this.filter.toString() + '} {' + this.rel.toString() +
143
+ '}}';
144
+ return ret;
145
+ }
146
+
147
+ PathExpr.prototype.parseTree = function(indent) {
148
+ var ret = indent + '[path]\n' +
149
+ indent + '- filter:\n' +
150
+ this.filter.parseTree(indent + ' ') +
151
+ indent + '- location path:\n' +
152
+ this.rel.parseTree(indent + ' ');
153
+ return ret;
154
+ }
155
+
156
+ FilterExpr.prototype.toString = function() {
157
+ var ret = this.expr.toString();
158
+ for (var i = 0; i < this.predicate.length; ++i) {
159
+ ret += this.predicate[i].toString();
160
+ }
161
+ return ret;
162
+ }
163
+
164
+ FilterExpr.prototype.parseTree = function(indent) {
165
+ var ret = indent + '[filter]\n' +
166
+ indent + '- expr:\n' +
167
+ this.expr.parseTree(indent + ' ');
168
+ indent + '- predicates:\n';
169
+ for (var i = 0; i < this.predicate.length; ++i) {
170
+ ret += this.predicate[i].parseTree(indent + ' ');
171
+ }
172
+ return ret;
173
+ }
174
+
175
+ UnaryMinusExpr.prototype.toString = function() {
176
+ return '-' + this.expr.toString();
177
+ }
178
+
179
+ UnaryMinusExpr.prototype.parseTree = function(indent) {
180
+ return indent + '[unary] -\n' + this.expr.parseTree(indent + ' ');
181
+ }
182
+
183
+ BinaryExpr.prototype.toString = function() {
184
+ return this.expr1.toString() + ' ' + this.op.value + ' ' +
185
+ this.expr2.toString();
186
+ }
187
+
188
+ BinaryExpr.prototype.parseTree = function(indent) {
189
+ return indent + '[binary] ' + this.op.value + '\n' +
190
+ this.expr1.parseTree(indent + ' ') +
191
+ this.expr2.parseTree(indent + ' ');
192
+ }
193
+
194
+ LiteralExpr.prototype.toString = function() {
195
+ return '"' + this.value + '"';
196
+ }
197
+
198
+ LiteralExpr.prototype.parseTree = function(indent) {
199
+ return indent + '[literal] ' + this.toString() + '\n';
200
+ }
201
+
202
+ NumberExpr.prototype.toString = function() {
203
+ return '' + this.value;
204
+ }
205
+
206
+ NumberExpr.prototype.parseTree = function(indent) {
207
+ return indent + '[number] ' + this.toString() + '\n';
208
+ }
209
+
210
+ VariableExpr.prototype.toString = function() {
211
+ return '$' + this.name;
212
+ }
213
+
214
+ VariableExpr.prototype.parseTree = function(indent) {
215
+ return indent + '[variable] ' + this.toString() + '\n';
216
+ }
217
+
218
+ XNode.prototype.toString = function() {
219
+ return this.nodeName;
220
+ }
221
+
222
+ ExprContext.prototype.toString = function() {
223
+ return '[' + this.position + '/' + this.nodelist.length + '] ' +
224
+ this.node.nodeName;
225
+ }
226
+
227
+ function Value_toString() {
228
+ return this.type + ': ' + this.value;
229
+ }
230
+
231
+ StringValue.prototype.toString = Value_toString;
232
+ NumberValue.prototype.toString = Value_toString;
233
+ BooleanValue.prototype.toString = Value_toString;
234
+ NodeSetValue.prototype.toString = Value_toString;
@@ -0,0 +1,138 @@
1
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
2
+ "http://www.w3.org/TR/html4/loose.dtd">
3
+
4
+ <html>
5
+ <head>
6
+ <title>JsUnit test page for file xslt.js of goog-ajaxslt</title>
7
+ <script language="JavaScript" type="text/javascript"
8
+ src="jsunit/app/jsUnitCore.js"></script>
9
+ <script language="JavaScript" type="text/javascript"
10
+ src="xmltoken.js"></script>
11
+ <script language="JavaScript" type="text/javascript"
12
+ src="util.js"></script>
13
+ <script language="JavaScript" type="text/javascript"
14
+ src="dom.js"></script>
15
+ <script language="JavaScript" type="text/javascript"
16
+ src="xpath.js"></script>
17
+ <script language="JavaScript" type="text/javascript"
18
+ src="xslt.js"></script>
19
+ <script language="JavaScript" type="text/javascript"
20
+ src="xslt_unittest.js"></script>
21
+ </head>
22
+
23
+ <body>
24
+ This is a <a href="http://www.jsunit.net/">jsUnit</a> test
25
+ page. Run it using the <a
26
+ href="jsunit/testRunner.html">jsUnit runner</a>.
27
+
28
+ <!-- used in the test cases -->
29
+
30
+ <textarea id="xml">
31
+ <all>
32
+ <item pos="2">A</item>
33
+ <item pos="3">B</item>
34
+ <item pos="1">C</item>
35
+ </all>
36
+ </textarea>
37
+
38
+ <textarea id="xslt-for-each-sort">
39
+ <xsl:stylesheet>
40
+ <xsl:template match="/">
41
+ <xsl:for-each select="//item">
42
+ <xsl:sort select="@pos"/>
43
+ <xsl:value-of select="."/>
44
+ </xsl:for-each>
45
+ </xsl:template>
46
+ </xsl:stylesheet>
47
+ </textarea>
48
+
49
+ <textarea id="xslt-for-each-sort-ascending">
50
+ <xsl:stylesheet>
51
+ <xsl:template match="/">
52
+ <xsl:for-each select="//item">
53
+ <xsl:sort select="." order="ascending"/>
54
+ <xsl:value-of select="."/>
55
+ </xsl:for-each>
56
+ </xsl:template>
57
+ </xsl:stylesheet>
58
+ </textarea>
59
+
60
+ <textarea id="xslt-for-each-sort-descending">
61
+ <xsl:stylesheet>
62
+ <xsl:template match="/">
63
+ <xsl:for-each select="//item">
64
+ <xsl:sort select="." order="descending"/>
65
+ <xsl:value-of select="."/>
66
+ </xsl:for-each>
67
+ </xsl:template>
68
+ </xsl:stylesheet>
69
+ </textarea>
70
+
71
+ <textarea id="xml-apply-templates">
72
+ <all>
73
+ <item type="X">A</item>
74
+ <item type="Y">B</item>
75
+ <item type="X">C</item>
76
+ </all>
77
+ </textarea>
78
+
79
+ <textarea id="xslt-apply-templates">
80
+ <xsl:stylesheet>
81
+ <xsl:template match="/">
82
+ <xsl:apply-templates select="//item"/>
83
+ </xsl:template>
84
+ <xsl:template match="item[@type='X']">
85
+ <xsl:value-of select="."/>
86
+ </xsl:template>
87
+ <xsl:template match="item[@type='Y']">
88
+ <xsl:value-of select="."/>
89
+ </xsl:template>
90
+ </xsl:stylesheet>
91
+ </textarea>
92
+
93
+ <textarea id="xslt-global-variables">
94
+ <xsl:stylesheet>
95
+ <xsl:variable name="x" select="'x'"/>
96
+ <xsl:variable name="y" select="'y'"/>
97
+ <xsl:variable name="z">
98
+ <xsl:text>z</xsl:text>
99
+ </xsl:variable>
100
+ <xsl:template match="/">
101
+ <xsl:value-of select="$x"/>
102
+ <xsl:value-of select="$z"/>
103
+ <xsl:for-each select="//item">
104
+ <xsl:value-of select="$y"/>
105
+ </xsl:for-each>
106
+ </xsl:template>
107
+ </xsl:stylesheet>
108
+ </textarea>
109
+
110
+ <textarea id="xslt-top-level-output">
111
+ <xsl:stylesheet>
112
+ <xsl:template match="/">
113
+ <xsl:element name="x">
114
+ <xsl:attribute name="y">
115
+ <xsl:text>z</xsl:text>
116
+ </xsl:attribute>
117
+ <xsl:text>k</xsl:text>
118
+ </xsl:element>
119
+ </xsl:template>
120
+ </xsl:stylesheet>
121
+ </textarea>
122
+
123
+ <textarea id="xslt-copy">
124
+ <xsl:stylesheet>
125
+ <xsl:template match="/">
126
+ <xsl:for-each select="//item">
127
+ <xsl:copy>
128
+ <xsl:for-each select="@*|node()">
129
+ <xsl:copy/>
130
+ </xsl:for-each>
131
+ </xsl:copy>
132
+ </xsl:for-each>
133
+ </xsl:template>
134
+ </xsl:stylesheet>
135
+ </textarea>
136
+
137
+ </body>
138
+ </html>
@@ -0,0 +1,68 @@
1
+ // Copyright 2006, Google Inc.
2
+ // All Rights Reserved.
3
+ //
4
+ // Unit test for the XSLT processor.
5
+ //
6
+ // Author: Steffen Meschkat <mesch@google.com>
7
+
8
+ //********************************************
9
+ // DGF BEWARE! You MUST update this function if you add tests!
10
+ //********************************************
11
+ function exposeTestFunctionNames() {
12
+ return ['testForEachSort', 'testForEachSortAscending', 'testForEachSortDescending', 'testApplyTemplates', 'testGlobalVariables', 'testTopLevelOutput', 'testCopy'];
13
+ }
14
+
15
+ function el(id) {
16
+ return document.getElementById(id);
17
+ }
18
+
19
+ function testForEachSort() {
20
+ var xml = xmlParse(el('xml').value);
21
+ var xslt = xmlParse(el('xslt-for-each-sort').value);
22
+ var html = xsltProcess(xml, xslt);
23
+ assertEquals("CAB", html);
24
+ }
25
+
26
+ function testForEachSortAscending() {
27
+ var xml = xmlParse(el('xml').value);
28
+ var xslt = xmlParse(el('xslt-for-each-sort-ascending').value);
29
+ var html = xsltProcess(xml, xslt);
30
+ assertEquals("ABC", html);
31
+ }
32
+
33
+ function testForEachSortDescending() {
34
+ var xml = xmlParse(el('xml').value);
35
+ var xslt = xmlParse(el('xslt-for-each-sort-descending').value);
36
+ var html = xsltProcess(xml, xslt);
37
+ assertEquals("CBA", html);
38
+ }
39
+
40
+ function testApplyTemplates() {
41
+ var xml = xmlParse(el('xml-apply-templates').value);
42
+ var xslt = xmlParse(el('xslt-apply-templates').value);
43
+ var html = xsltProcess(xml, xslt);
44
+ assertEquals("ABC", html);
45
+ }
46
+
47
+ function testGlobalVariables() {
48
+ var xml = xmlParse(el('xml').value);
49
+ var xslt = xmlParse(el('xslt-global-variables').value);
50
+ var html = xsltProcess(xml, xslt);
51
+ assertEquals("xzyyy", html);
52
+ }
53
+
54
+ function testTopLevelOutput() {
55
+ var xml = xmlParse(el('xml').value);
56
+ var xslt = xmlParse(el('xslt-top-level-output').value);
57
+ var html = xsltProcess(xml, xslt);
58
+ assertEquals('<x y="z">k</x>', html);
59
+ }
60
+
61
+ function testCopy() {
62
+ var xml = xmlParse(el('xml').value);
63
+ var xslt = xmlParse(el('xslt-copy').value);
64
+ var html = xsltProcess(xml, xslt);
65
+ assertEquals('<item pos="2">A</item>' +
66
+ '<item pos="3">B</item>' +
67
+ '<item pos="1">C</item>', html);
68
+ }
@@ -0,0 +1,625 @@
1
+ // Copyright 2005 Google Inc.
2
+ // All Rights Reserved
3
+ //
4
+ //
5
+ // An XSL-T processor written in JavaScript. The implementation is NOT
6
+ // complete; some xsl element are left out.
7
+ //
8
+ // References:
9
+ //
10
+ // [XSLT] XSL-T Specification
11
+ // <http://www.w3.org/TR/1999/REC-xslt-19991116>.
12
+ //
13
+ // [ECMA] ECMAScript Language Specification
14
+ // <http://www.ecma-international.org/publications/standards/Ecma-262.htm>.
15
+ //
16
+ // The XSL processor API has one entry point, the function
17
+ // xsltProcessContext(). It receives as arguments the starting point in the
18
+ // input document as an XPath expression context, the DOM root node of
19
+ // the XSL-T stylesheet, and a DOM node that receives the output.
20
+ //
21
+ // NOTE: Actually, XSL-T processing according to the specification is
22
+ // defined as operation on text documents, not as operation on DOM
23
+ // trees. So, strictly speaking, this implementation is not an XSL-T
24
+ // processor, but the processing engine that needs to be complemented
25
+ // by an XML parser and serializer in order to be complete. Those two
26
+ // are found in the file xml.js.
27
+ //
28
+ //
29
+ // TODO(mesch): add jsdoc comments. Use more coherent naming. Finish
30
+ // remaining XSLT features.
31
+ //
32
+ //
33
+ // Author: Steffen Meschkat <mesch@google.com>
34
+
35
+
36
+ // The exported entry point of the XSL-T processor, as explained
37
+ // above.
38
+ //
39
+ // @param xmlDoc The input document root, as DOM node.
40
+ // @param template The stylesheet document root, as DOM node.
41
+ // @return the processed document, as XML text in a string.
42
+
43
+ function xsltProcess(xmlDoc, stylesheet) {
44
+ var output = domCreateDocumentFragment(new XDocument);
45
+ xsltProcessContext(new ExprContext(xmlDoc), stylesheet, output);
46
+ var ret = xmlText(output);
47
+ return ret;
48
+ }
49
+
50
+ // The main entry point of the XSL-T processor, as explained above.
51
+ //
52
+ // @param input The input document root, as XPath ExprContext.
53
+ // @param template The stylesheet document root, as DOM node.
54
+ // @param the root of the generated output, as DOM node.
55
+
56
+ function xsltProcessContext(input, template, output) {
57
+ var outputDocument = xmlOwnerDocument(output);
58
+
59
+ var nodename = template.nodeName.split(/:/);
60
+ if (nodename.length == 1 || nodename[0] != 'xsl') {
61
+ xsltPassThrough(input, template, output, outputDocument);
62
+
63
+ } else {
64
+ switch(nodename[1]) {
65
+ case 'apply-imports':
66
+ alert('not implemented: ' + nodename[1]);
67
+ break;
68
+
69
+ case 'apply-templates':
70
+ var select = xmlGetAttribute(template, 'select');
71
+ var nodes;
72
+ if (select) {
73
+ nodes = xpathEval(select,input).nodeSetValue();
74
+ } else {
75
+ nodes = input.node.childNodes;
76
+ }
77
+
78
+ var sortContext = input.clone(nodes[0], 0, nodes);
79
+ xsltWithParam(sortContext, template);
80
+ xsltSort(sortContext, template);
81
+
82
+ var mode = xmlGetAttribute(template, 'mode');
83
+ var top = template.ownerDocument.documentElement;
84
+ var templates = [];
85
+ for (var i = 0; i < top.childNodes.length; ++i) {
86
+ var c = top.childNodes[i];
87
+ if (c.nodeType == DOM_ELEMENT_NODE &&
88
+ c.nodeName == 'xsl:template' &&
89
+ c.getAttribute('mode') == mode) {
90
+ templates.push(c);
91
+ }
92
+ }
93
+ for (var j = 0; j < sortContext.contextSize(); ++j) {
94
+ var nj = sortContext.nodelist[j];
95
+ for (var i = 0; i < templates.length; ++i) {
96
+ xsltProcessContext(sortContext.clone(nj, j), templates[i], output);
97
+ }
98
+ }
99
+ break;
100
+
101
+ case 'attribute':
102
+ var nameexpr = xmlGetAttribute(template, 'name');
103
+ var name = xsltAttributeValue(nameexpr, input);
104
+ var node = domCreateDocumentFragment(outputDocument);
105
+ xsltChildNodes(input, template, node);
106
+ var value = xmlValue(node);
107
+ domSetAttribute(output, name, value);
108
+ break;
109
+
110
+ case 'attribute-set':
111
+ alert('not implemented: ' + nodename[1]);
112
+ break;
113
+
114
+ case 'call-template':
115
+ var name = xmlGetAttribute(template, 'name');
116
+ var top = template.ownerDocument.documentElement;
117
+
118
+ var paramContext = input.clone();
119
+ xsltWithParam(paramContext, template);
120
+
121
+ for (var i = 0; i < top.childNodes.length; ++i) {
122
+ var c = top.childNodes[i];
123
+ if (c.nodeType == DOM_ELEMENT_NODE &&
124
+ c.nodeName == 'xsl:template' &&
125
+ domGetAttribute(c, 'name') == name) {
126
+ xsltChildNodes(paramContext, c, output);
127
+ break;
128
+ }
129
+ }
130
+ break;
131
+
132
+ case 'choose':
133
+ xsltChoose(input, template, output);
134
+ break;
135
+
136
+ case 'comment':
137
+ var node = domCreateDocumentFragment(outputDocument);
138
+ xsltChildNodes(input, template, node);
139
+ var commentData = xmlValue(node);
140
+ var commentNode = domCreateComment(outputDocument, commentData);
141
+ output.appendChild(commentNode);
142
+ break;
143
+
144
+ case 'copy':
145
+ var node = xsltCopy(output, input.node, outputDocument);
146
+ if (node) {
147
+ xsltChildNodes(input, template, node);
148
+ }
149
+ break;
150
+
151
+ case 'copy-of':
152
+ var select = xmlGetAttribute(template, 'select');
153
+ var value = xpathEval(select, input);
154
+ if (value.type == 'node-set') {
155
+ var nodes = value.nodeSetValue();
156
+ for (var i = 0; i < nodes.length; ++i) {
157
+ xsltCopyOf(output, nodes[i], outputDocument);
158
+ }
159
+
160
+ } else {
161
+ var node = domCreateTextNode(outputDocument, value.stringValue());
162
+ domAppendChild(output, node);
163
+ }
164
+ break;
165
+
166
+ case 'decimal-format':
167
+ alert('not implemented: ' + nodename[1]);
168
+ break;
169
+
170
+ case 'element':
171
+ var nameexpr = xmlGetAttribute(template, 'name');
172
+ var name = xsltAttributeValue(nameexpr, input);
173
+ var node = domCreateElement(outputDocument, name);
174
+ domAppendChild(output, node);
175
+ xsltChildNodes(input, template, node);
176
+ break;
177
+
178
+ case 'fallback':
179
+ alert('not implemented: ' + nodename[1]);
180
+ break;
181
+
182
+ case 'for-each':
183
+ xsltForEach(input, template, output);
184
+ break;
185
+
186
+ case 'if':
187
+ var test = xmlGetAttribute(template, 'test');
188
+ if (xpathEval(test, input).booleanValue()) {
189
+ xsltChildNodes(input, template, output);
190
+ }
191
+ break;
192
+
193
+ case 'import':
194
+ alert('not implemented: ' + nodename[1]);
195
+ break;
196
+
197
+ case 'include':
198
+ alert('not implemented: ' + nodename[1]);
199
+ break;
200
+
201
+ case 'key':
202
+ alert('not implemented: ' + nodename[1]);
203
+ break;
204
+
205
+ case 'message':
206
+ alert('not implemented: ' + nodename[1]);
207
+ break;
208
+
209
+ case 'namespace-alias':
210
+ alert('not implemented: ' + nodename[1]);
211
+ break;
212
+
213
+ case 'number':
214
+ alert('not implemented: ' + nodename[1]);
215
+ break;
216
+
217
+ case 'otherwise':
218
+ alert('error if here: ' + nodename[1]);
219
+ break;
220
+
221
+ case 'output':
222
+ // Ignored. -- Since we operate on the DOM, and all further use
223
+ // of the output of the XSL transformation is determined by the
224
+ // browser that we run in, this parameter is not applicable to
225
+ // this implementation.
226
+ break;
227
+
228
+ case 'preserve-space':
229
+ alert('not implemented: ' + nodename[1]);
230
+ break;
231
+
232
+ case 'processing-instruction':
233
+ alert('not implemented: ' + nodename[1]);
234
+ break;
235
+
236
+ case 'sort':
237
+ // just ignore -- was handled by xsltSort()
238
+ break;
239
+
240
+ case 'strip-space':
241
+ alert('not implemented: ' + nodename[1]);
242
+ break;
243
+
244
+ case 'stylesheet':
245
+ case 'transform':
246
+ xsltChildNodes(input, template, output);
247
+ break;
248
+
249
+ case 'template':
250
+ var match = xmlGetAttribute(template, 'match');
251
+ if (match && xsltMatch(match, input)) {
252
+ xsltChildNodes(input, template, output);
253
+ }
254
+ break;
255
+
256
+ case 'text':
257
+ var text = xmlValue(template);
258
+ var node = domCreateTextNode(outputDocument, text);
259
+ output.appendChild(node);
260
+ break;
261
+
262
+ case 'value-of':
263
+ var select = xmlGetAttribute(template, 'select');
264
+ var value = xpathEval(select, input).stringValue();
265
+ var node = domCreateTextNode(outputDocument, value);
266
+ output.appendChild(node);
267
+ break;
268
+
269
+ case 'param':
270
+ xsltVariable(input, template, false);
271
+ break;
272
+
273
+ case 'variable':
274
+ xsltVariable(input, template, true);
275
+ break;
276
+
277
+ case 'when':
278
+ alert('error if here: ' + nodename[1]);
279
+ break;
280
+
281
+ case 'with-param':
282
+ alert('error if here: ' + nodename[1]);
283
+ break;
284
+
285
+ default:
286
+ alert('error if here: ' + nodename[1]);
287
+ break;
288
+ }
289
+ }
290
+ }
291
+
292
+
293
+ // Sets parameters defined by xsl:with-param child nodes of the
294
+ // current template node, in the current input context. This happens
295
+ // before the operation specified by the current template node is
296
+ // executed.
297
+
298
+ function xsltWithParam(input, template) {
299
+ for (var i = 0; i < template.childNodes.length; ++i) {
300
+ var c = template.childNodes[i];
301
+ if (c.nodeType == DOM_ELEMENT_NODE && c.nodeName == 'xsl:with-param') {
302
+ xsltVariable(input, c, true);
303
+ }
304
+ }
305
+ }
306
+
307
+
308
+ // Orders the current node list in the input context according to the
309
+ // sort order specified by xsl:sort child nodes of the current
310
+ // template node. This happens before the operation specified by the
311
+ // current template node is executed.
312
+ //
313
+ // TODO(mesch): case-order is not implemented.
314
+
315
+ function xsltSort(input, template) {
316
+ var sort = [];
317
+ for (var i = 0; i < template.childNodes.length; ++i) {
318
+ var c = template.childNodes[i];
319
+ if (c.nodeType == DOM_ELEMENT_NODE && c.nodeName == 'xsl:sort') {
320
+ var select = xmlGetAttribute(c, 'select');
321
+ var expr = xpathParse(select);
322
+ var type = xmlGetAttribute(c, 'data-type') || 'text';
323
+ var order = xmlGetAttribute(c, 'order') || 'ascending';
324
+ sort.push({ expr: expr, type: type, order: order });
325
+ }
326
+ }
327
+
328
+ xpathSort(input, sort);
329
+ }
330
+
331
+
332
+ // Evaluates a variable or parameter and set it in the current input
333
+ // context. Implements xsl:variable, xsl:param, and xsl:with-param.
334
+ //
335
+ // @param override flag that defines if the value computed here
336
+ // overrides the one already in the input context if that is the
337
+ // case. I.e. decides if this is a default value or a local
338
+ // value. xsl:variable and xsl:with-param override; xsl:param doesn't.
339
+
340
+ function xsltVariable(input, template, override) {
341
+ var name = xmlGetAttribute(template, 'name');
342
+ var select = xmlGetAttribute(template, 'select');
343
+
344
+ var value;
345
+
346
+ if (template.childNodes.length > 0) {
347
+ var root = domCreateDocumentFragment(template.ownerDocument);
348
+ xsltChildNodes(input, template, root);
349
+ value = new NodeSetValue([root]);
350
+
351
+ } else if (select) {
352
+ value = xpathEval(select, input);
353
+
354
+ } else {
355
+ value = new StringValue('');
356
+ }
357
+
358
+ if (override || !input.getVariable(name)) {
359
+ input.setVariable(name, value);
360
+ }
361
+ }
362
+
363
+
364
+ // Implements xsl:chose and its child nodes xsl:when and
365
+ // xsl:otherwise.
366
+
367
+ function xsltChoose(input, template, output) {
368
+ for (var i = 0; i < template.childNodes.length; ++i) {
369
+ var childNode = template.childNodes[i];
370
+ if (childNode.nodeType != DOM_ELEMENT_NODE) {
371
+ continue;
372
+
373
+ } else if (childNode.nodeName == 'xsl:when') {
374
+ var test = xmlGetAttribute(childNode, 'test');
375
+ if (xpathEval(test, input).booleanValue()) {
376
+ xsltChildNodes(input, childNode, output);
377
+ break;
378
+ }
379
+
380
+ } else if (childNode.nodeName == 'xsl:otherwise') {
381
+ xsltChildNodes(input, childNode, output);
382
+ break;
383
+ }
384
+ }
385
+ }
386
+
387
+
388
+ // Implements xsl:for-each.
389
+
390
+ function xsltForEach(input, template, output) {
391
+ var select = xmlGetAttribute(template, 'select');
392
+ var nodes = xpathEval(select, input).nodeSetValue();
393
+ var sortContext = input.clone(nodes[0], 0, nodes);
394
+ xsltSort(sortContext, template);
395
+ for (var i = 0; i < sortContext.contextSize(); ++i) {
396
+ var ni = sortContext.nodelist[i];
397
+ xsltChildNodes(sortContext.clone(ni, i), template, output);
398
+ }
399
+ }
400
+
401
+
402
+ // Traverses the template node tree. Calls the main processing
403
+ // function with the current input context for every child node of the
404
+ // current template node.
405
+
406
+ function xsltChildNodes(input, template, output) {
407
+ // Clone input context to keep variables declared here local to the
408
+ // siblings of the children.
409
+ var context = input.clone();
410
+ for (var i = 0; i < template.childNodes.length; ++i) {
411
+ xsltProcessContext(context, template.childNodes[i], output);
412
+ }
413
+ }
414
+
415
+
416
+ // Passes template text to the output. The current template node does
417
+ // not specify an XSL-T operation and therefore is appended to the
418
+ // output with all its attributes. Then continues traversing the
419
+ // template node tree.
420
+
421
+ function xsltPassThrough(input, template, output, outputDocument) {
422
+ if (template.nodeType == DOM_TEXT_NODE) {
423
+ if (xsltPassText(template)) {
424
+ var node = domCreateTextNode(outputDocument, template.nodeValue);
425
+ domAppendChild(output, node);
426
+ }
427
+
428
+ } else if (template.nodeType == DOM_ELEMENT_NODE) {
429
+ var node = domCreateElement(outputDocument, template.nodeName);
430
+ for (var i = 0; i < template.attributes.length; ++i) {
431
+ var a = template.attributes[i];
432
+ if (a) {
433
+ var name = a.nodeName;
434
+ var value = xsltAttributeValue(a.nodeValue, input);
435
+ domSetAttribute(node, name, value);
436
+ }
437
+ }
438
+ domAppendChild(output, node);
439
+ xsltChildNodes(input, template, node);
440
+
441
+ } else {
442
+ // This applies also to the DOCUMENT_NODE of the XSL stylesheet,
443
+ // so we don't have to treat it specially.
444
+ xsltChildNodes(input, template, output);
445
+ }
446
+ }
447
+
448
+ // Determines if a text node in the XSLT template document is to be
449
+ // stripped according to XSLT whitespace stipping rules.
450
+ //
451
+ // See [XSLT], section 3.4.
452
+ //
453
+ // TODO(mesch): Whitespace stripping on the input document is
454
+ // currently not implemented.
455
+
456
+ function xsltPassText(template) {
457
+ if (!template.nodeValue.match(/^\s*$/)) {
458
+ return true;
459
+ }
460
+
461
+ var element = template.parentNode;
462
+ if (element.nodeName == 'xsl:text') {
463
+ return true;
464
+ }
465
+
466
+ while (element && element.nodeType == DOM_ELEMENT_NODE) {
467
+ var xmlspace = domGetAttribute(element, 'xml:space');
468
+ if (xmlspace) {
469
+ if (xmlspace == 'default') {
470
+ return false;
471
+ } else if (xmlspace == 'preserve') {
472
+ return true;
473
+ }
474
+ }
475
+
476
+ element = element.parentNode;
477
+ }
478
+
479
+ return false;
480
+ }
481
+
482
+ // Evaluates an XSL-T attribute value template. Attribute value
483
+ // templates are attributes on XSL-T elements that contain XPath
484
+ // expressions in braces {}. The XSL-T expressions are evaluated in
485
+ // the current input context. NOTE(mesch): We are using stringSplit()
486
+ // instead of string.split() for IE compatibility, see comment on
487
+ // stringSplit().
488
+
489
+ function xsltAttributeValue(value, context) {
490
+ var parts = stringSplit(value, '{');
491
+ if (parts.length == 1) {
492
+ return value;
493
+ }
494
+
495
+ var ret = '';
496
+ for (var i = 0; i < parts.length; ++i) {
497
+ var rp = stringSplit(parts[i], '}');
498
+ if (rp.length != 2) {
499
+ // first literal part of the value
500
+ ret += parts[i];
501
+ continue;
502
+ }
503
+
504
+ var val = xpathEval(rp[0], context).stringValue();
505
+ ret += val + rp[1];
506
+ }
507
+
508
+ return ret;
509
+ }
510
+
511
+
512
+ // Wrapper function to access attribute values of template element
513
+ // nodes. Currently this calls xmlResolveEntities because in some DOM
514
+ // implementations the return value of node.getAttributeValue()
515
+ // contains unresolved XML entities, although the DOM spec requires
516
+ // that entity references are resolved by te DOM.
517
+ function xmlGetAttribute(node, name) {
518
+ // TODO(mesch): This should not be necessary if the DOM is working
519
+ // correctly. The DOM is responsible for resolving entities, not the
520
+ // application.
521
+ var value = domGetAttribute(node, name);
522
+ if (value) {
523
+ return xmlResolveEntities(value);
524
+ } else {
525
+ return value;
526
+ }
527
+ };
528
+
529
+
530
+ // Implements xsl:copy-of for node-set values of the select
531
+ // expression. Recurses down the source node tree, which is part of
532
+ // the input document.
533
+ //
534
+ // @param {Node} dst the node being copied to, part of output document,
535
+ // @param {Node} src the node being copied, part in input document,
536
+ // @param {Document} dstDocument
537
+
538
+ function xsltCopyOf(dst, src, dstDocument) {
539
+ if (src.nodeType == DOM_DOCUMENT_FRAGMENT_NODE ||
540
+ src.nodeType == DOM_DOCUMENT_NODE) {
541
+ for (var i = 0; i < src.childNodes.length; ++i) {
542
+ arguments.callee(dst, src.childNodes[i], dstDocument);
543
+ }
544
+ } else {
545
+ var node = xsltCopy(dst, src, dstDocument);
546
+ if (node) {
547
+ // This was an element node -- recurse to attributes and
548
+ // children.
549
+ for (var i = 0; i < src.attributes.length; ++i) {
550
+ arguments.callee(node, src.attributes[i], dstDocument);
551
+ }
552
+
553
+ for (var i = 0; i < src.childNodes.length; ++i) {
554
+ arguments.callee(node, src.childNodes[i], dstDocument);
555
+ }
556
+ }
557
+ }
558
+ }
559
+
560
+
561
+ // Implements xsl:copy for all node types.
562
+ //
563
+ // @param {Node} dst the node being copied to, part of output document,
564
+ // @param {Node} src the node being copied, part in input document,
565
+ // @param {Document} dstDocument
566
+ // @return {Node|Null} If an element node was created, the element
567
+ // node. Otherwise null.
568
+
569
+ function xsltCopy(dst, src, dstDocument) {
570
+ if (src.nodeType == DOM_ELEMENT_NODE) {
571
+ var node = domCreateElement(dstDocument, src.nodeName);
572
+ domAppendChild(dst, node);
573
+ return node;
574
+ }
575
+
576
+ if (src.nodeType == DOM_TEXT_NODE) {
577
+ var node = domCreateTextNode(dstDocument, src.nodeValue);
578
+ domAppendChild(dst, node);
579
+
580
+ } else if (src.nodeType == DOM_CDATA_SECTION_NODE) {
581
+ var node = domCreateCDATASection(dstDocument, src.nodeValue);
582
+ domAppendChild(dst, node);
583
+
584
+ } else if (src.nodeType == DOM_COMMENT_NODE) {
585
+ var node = domCreateComment(dstDocument, src.nodeValue);
586
+ domAppendChild(dst, node);
587
+
588
+ } else if (src.nodeType == DOM_ATTRIBUTE_NODE) {
589
+ domSetAttribute(dst, src.nodeName, src.nodeValue);
590
+ }
591
+
592
+ return null;
593
+ }
594
+
595
+
596
+ // Evaluates an XPath expression in the current input context as a
597
+ // match (see [XSLT] section 5.2, paragraph 1).
598
+ function xsltMatch(match, context) {
599
+ var expr = xpathParse(match);
600
+
601
+ var ret;
602
+ // Shortcut for the most common case.
603
+ if (expr.steps && !expr.absolute && expr.steps.length == 1 &&
604
+ expr.steps[0].axis == 'child' && expr.steps[0].predicate.length == 0) {
605
+ ret = expr.steps[0].nodetest.evaluate(context).booleanValue();
606
+
607
+ } else {
608
+
609
+ ret = false;
610
+ var node = context.node;
611
+
612
+ while (!ret && node) {
613
+ var result = expr.evaluate(context.clone(node,0,[node])).nodeSetValue();
614
+ for (var i = 0; i < result.length; ++i) {
615
+ if (result[i] == context.node) {
616
+ ret = true;
617
+ break;
618
+ }
619
+ }
620
+ node = node.parentNode;
621
+ }
622
+ }
623
+
624
+ return ret;
625
+ }