envjs 0.1.7 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (187) hide show
  1. data/.jslintrbrc +29 -0
  2. data/.project +17 -0
  3. data/CHANGELOG.rdoc +3 -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 +287 -0
  14. data/{README → README.rdoc} +24 -3
  15. data/Rakefile +196 -0
  16. data/Wakefile +24 -0
  17. data/build.properties +9 -0
  18. data/build.xml +247 -0
  19. data/gm/jquery.js +6002 -0
  20. data/gm/mainx.js +2648 -0
  21. data/gm/sensx.js +135 -0
  22. data/gm/t.js +6 -0
  23. data/gm/x.html +76 -0
  24. data/htmlparser/BrowserTreeBuilder.java +456 -0
  25. data/htmlparser/README +34 -0
  26. data/htmlparser/build.sh +38 -0
  27. data/jsl/jsl +0 -0
  28. data/jsl/jsl.default.conf +129 -0
  29. data/jsl/jsl.exe +0 -0
  30. data/lib/envjs.rb +2 -0
  31. data/lib/envjs/env.js +22 -3
  32. data/lib/envjs/event_loop.js +2 -0
  33. data/lib/envjs/static.js +155 -21
  34. data/licenses/GPL-LICENSE.txt +278 -0
  35. data/licenses/MIT-LICENSE.txt +20 -0
  36. data/src/base64.js +80 -0
  37. data/src/build.js +6 -0
  38. data/src/cruft/bad.html +24 -0
  39. data/src/cruft/dom.js +606 -0
  40. data/src/cruft/element.js +297 -0
  41. data/src/cruft/good.html +30 -0
  42. data/src/cruft/good.js +32 -0
  43. data/src/cruft/internal.js +81 -0
  44. data/src/cruft/parser.js +458 -0
  45. data/src/css/properties.js +293 -0
  46. data/src/css/rule.js +22 -0
  47. data/src/css/sizzle.js +717 -0
  48. data/src/css/stylesheet.js +52 -0
  49. data/src/dom/attr.js +55 -0
  50. data/src/dom/cdatasection.js +31 -0
  51. data/src/dom/characterdata.js +119 -0
  52. data/src/dom/comment.js +30 -0
  53. data/src/dom/doctype.js +9 -0
  54. data/src/dom/document.js +553 -0
  55. data/src/dom/dom.js +134 -0
  56. data/src/dom/element.js +217 -0
  57. data/src/dom/entities.js +273 -0
  58. data/src/dom/exception.js +28 -0
  59. data/src/dom/fragment.js +37 -0
  60. data/src/dom/implementation.js +602 -0
  61. data/src/dom/instruction.js +51 -0
  62. data/src/dom/namednodemap.js +374 -0
  63. data/src/dom/namespace.js +50 -0
  64. data/src/dom/node.js +618 -0
  65. data/src/dom/nodelist.js +195 -0
  66. data/src/dom/parser.js +1207 -0
  67. data/src/dom/text.js +73 -0
  68. data/src/event/event.js +39 -0
  69. data/src/event/mouseevent.js +4 -0
  70. data/src/event/uievent.js +8 -0
  71. data/src/html/a.js +110 -0
  72. data/src/html/anchor.js +80 -0
  73. data/src/html/area.js +57 -0
  74. data/src/html/base.js +26 -0
  75. data/src/html/blockquote-q.js +19 -0
  76. data/src/html/body.js +19 -0
  77. data/src/html/button.js +21 -0
  78. data/src/html/canvas.js +14 -0
  79. data/src/html/col-colgroup.js +49 -0
  80. data/src/html/collection.js +72 -0
  81. data/src/html/cookie.js +151 -0
  82. data/src/html/del-ins.js +25 -0
  83. data/src/html/div.js +28 -0
  84. data/src/html/document.js +359 -0
  85. data/src/html/element.js +380 -0
  86. data/src/html/fieldset.js +19 -0
  87. data/src/html/form.js +484 -0
  88. data/src/html/frame.js +89 -0
  89. data/src/html/frameset.js +25 -0
  90. data/src/html/head.js +44 -0
  91. data/src/html/html.js +0 -0
  92. data/src/html/htmlparser.js +340 -0
  93. data/src/html/iframe.js +26 -0
  94. data/src/html/image.js +0 -0
  95. data/src/html/img.js +62 -0
  96. data/src/html/input-elements.js +307 -0
  97. data/src/html/input.js +65 -0
  98. data/src/html/label.js +26 -0
  99. data/src/html/legend.js +19 -0
  100. data/src/html/link.js +82 -0
  101. data/src/html/map.js +22 -0
  102. data/src/html/meta.js +37 -0
  103. data/src/html/object.js +89 -0
  104. data/src/html/optgroup.js +25 -0
  105. data/src/html/option.js +97 -0
  106. data/src/html/param.js +38 -0
  107. data/src/html/script.js +122 -0
  108. data/src/html/select.js +129 -0
  109. data/src/html/style.js +31 -0
  110. data/src/html/table.js +199 -0
  111. data/src/html/tbody-thead-tfoot.js +91 -0
  112. data/src/html/td-th.js +18 -0
  113. data/src/html/textarea.js +25 -0
  114. data/src/html/title.js +20 -0
  115. data/src/html/tr.js +114 -0
  116. data/src/intro.js +141 -0
  117. data/src/outro.js +70 -0
  118. data/src/parser/html5.detailed.js +10762 -0
  119. data/src/parser/html5.min.js +503 -0
  120. data/src/parser/html5.pretty.js +10815 -0
  121. data/src/parser/intro.js +42 -0
  122. data/src/parser/outro.js +9 -0
  123. data/src/platform/core.js +323 -0
  124. data/src/platform/johnson.js +479 -0
  125. data/src/platform/rhino.js +327 -0
  126. data/src/platform/static/intro.js +41 -0
  127. data/src/platform/static/outro.js +30 -0
  128. data/src/profile/aop.js +238 -0
  129. data/src/profile/profile.js +402 -0
  130. data/src/serializer/xml.js +21 -0
  131. data/src/svg/animatedstring.js +25 -0
  132. data/src/svg/document.js +25 -0
  133. data/src/svg/element.js +22 -0
  134. data/src/svg/locatable.js +17 -0
  135. data/src/svg/rect.js +18 -0
  136. data/src/svg/rectelement.js +24 -0
  137. data/src/svg/stylable.js +49 -0
  138. data/src/svg/svgelement.js +22 -0
  139. data/src/svg/transformable.js +15 -0
  140. data/src/window/css.js +15 -0
  141. data/src/window/dialog.js +16 -0
  142. data/src/window/document.js +28 -0
  143. data/src/window/event.js +262 -0
  144. data/src/window/history.js +62 -0
  145. data/src/window/location.js +138 -0
  146. data/src/window/navigator.js +48 -0
  147. data/src/window/screen.js +53 -0
  148. data/src/window/timer.js +21 -0
  149. data/src/window/window.js +284 -0
  150. data/src/window/xhr.js +127 -0
  151. data/src/xpath/expression.js +49 -0
  152. data/src/xpath/implementation.js +2482 -0
  153. data/src/xpath/result.js +67 -0
  154. data/src/xpath/util.js +551 -0
  155. data/src/xpath/xmltoken.js +149 -0
  156. data/src/xslt/COPYING +34 -0
  157. data/src/xslt/ajaxslt-0.8.1/AUTHORS +1 -0
  158. data/src/xslt/ajaxslt-0.8.1/ChangeLog +136 -0
  159. data/src/xslt/ajaxslt-0.8.1/Makefile +49 -0
  160. data/src/xslt/ajaxslt-0.8.1/README +102 -0
  161. data/src/xslt/ajaxslt-0.8.1/TODO +15 -0
  162. data/src/xslt/ajaxslt-0.8.1/dom.js +566 -0
  163. data/src/xslt/ajaxslt-0.8.1/dom_unittest.html +24 -0
  164. data/src/xslt/ajaxslt-0.8.1/dom_unittest.js +131 -0
  165. data/src/xslt/ajaxslt-0.8.1/simplelog.js +79 -0
  166. data/src/xslt/ajaxslt-0.8.1/test/xpath.html +18 -0
  167. data/src/xslt/ajaxslt-0.8.1/test/xpath_script.js +45 -0
  168. data/src/xslt/ajaxslt-0.8.1/test/xslt.html +58 -0
  169. data/src/xslt/ajaxslt-0.8.1/test/xslt_script.js +33 -0
  170. data/src/xslt/ajaxslt-0.8.1/unittestsuite.html +26 -0
  171. data/src/xslt/ajaxslt-0.8.1/xmltoken.js +149 -0
  172. data/src/xslt/ajaxslt-0.8.1/xmltoken_unittest.html +18 -0
  173. data/src/xslt/ajaxslt-0.8.1/xmltoken_unittest.js +811 -0
  174. data/src/xslt/ajaxslt-0.8.1/xpath_unittest.html +39 -0
  175. data/src/xslt/ajaxslt-0.8.1/xpath_unittest.js +557 -0
  176. data/src/xslt/ajaxslt-0.8.1/xpathdebug.js +234 -0
  177. data/src/xslt/ajaxslt-0.8.1/xslt_unittest.html +138 -0
  178. data/src/xslt/ajaxslt-0.8.1/xslt_unittest.js +68 -0
  179. data/src/xslt/implementation.js +625 -0
  180. data/src/xslt/processor.js +37 -0
  181. data/src/xslt/util.js +449 -0
  182. data/test/foo.html +8 -0
  183. data/test/foo.js +40 -0
  184. data/test/jquery.js +6002 -0
  185. data/test/x.js +1 -0
  186. data/test/y.js +1 -0
  187. metadata +245 -14
@@ -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
+ }