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.
- data/.jslintrbrc +30 -0
- data/.project +17 -0
- data/CHANGELOG.rdoc +57 -0
- data/DTD/xhtml-lat1.ent +196 -0
- data/DTD/xhtml-special.ent +80 -0
- data/DTD/xhtml-symbol.ent +237 -0
- data/DTD/xhtml.soc +14 -0
- data/DTD/xhtml1-frameset.dtd +1235 -0
- data/DTD/xhtml1-strict.dtd +978 -0
- data/DTD/xhtml1-transitional.dtd +1201 -0
- data/DTD/xhtml1.dcl +192 -0
- data/Makefile +7 -0
- data/Manifest.txt +280 -0
- data/README.rdoc +65 -0
- data/Rakefile +196 -0
- data/Wakefile +11 -0
- data/bin/envjsrb +257 -0
- data/build.properties +9 -0
- data/build.xml +247 -0
- data/gm/jquery.js +6002 -0
- data/gm/mainx.js +2648 -0
- data/gm/sensx.js +135 -0
- data/gm/t.js +6 -0
- data/gm/x.html +76 -0
- data/htmlparser/BrowserTreeBuilder.java +456 -0
- data/htmlparser/README +34 -0
- data/htmlparser/build.sh +38 -0
- data/jsl/jsl +0 -0
- data/jsl/jsl.default.conf +129 -0
- data/jsl/jsl.exe +0 -0
- data/lib/envjs.rb +35 -0
- data/lib/envjs/event_loop.js +206 -0
- data/lib/envjs/net.rb +3 -0
- data/lib/envjs/net/cgi.rb +94 -0
- data/lib/envjs/net/file.rb +69 -0
- data/lib/envjs/options.rb +11 -0
- data/lib/envjs/runtime.rb +346 -0
- data/lib/envjs/tempfile.rb +24 -0
- data/licenses/GPL-LICENSE.txt +278 -0
- data/licenses/MIT-LICENSE.txt +20 -0
- data/src/base64.js +80 -0
- data/src/build.js +6 -0
- data/src/cruft/bad.html +24 -0
- data/src/cruft/dom.js +606 -0
- data/src/cruft/element.js +297 -0
- data/src/cruft/good.html +30 -0
- data/src/cruft/good.js +32 -0
- data/src/cruft/internal.js +81 -0
- data/src/cruft/parser.js +458 -0
- data/src/css/properties.js +293 -0
- data/src/css/rule.js +22 -0
- data/src/css/sizzle.js +717 -0
- data/src/css/stylesheet.js +52 -0
- data/src/dom/attr.js +55 -0
- data/src/dom/cdatasection.js +31 -0
- data/src/dom/characterdata.js +119 -0
- data/src/dom/comment.js +30 -0
- data/src/dom/doctype.js +9 -0
- data/src/dom/document.js +1023 -0
- data/src/dom/dom.js +134 -0
- data/src/dom/element.js +217 -0
- data/src/dom/entities.js +273 -0
- data/src/dom/exception.js +28 -0
- data/src/dom/fragment.js +37 -0
- data/src/dom/implementation.js +140 -0
- data/src/dom/instruction.js +51 -0
- data/src/dom/namednodemap.js +374 -0
- data/src/dom/namespace.js +50 -0
- data/src/dom/node.js +618 -0
- data/src/dom/nodelist.js +195 -0
- data/src/dom/parser.js +1207 -0
- data/src/dom/text.js +73 -0
- data/src/event/event.js +47 -0
- data/src/event/mouseevent.js +4 -0
- data/src/event/uievent.js +8 -0
- data/src/html/a.js +110 -0
- data/src/html/anchor.js +80 -0
- data/src/html/area.js +57 -0
- data/src/html/base.js +26 -0
- data/src/html/blockquote-q.js +19 -0
- data/src/html/body.js +19 -0
- data/src/html/button.js +21 -0
- data/src/html/canvas.js +14 -0
- data/src/html/col-colgroup.js +49 -0
- data/src/html/collection.js +72 -0
- data/src/html/cookie.js +153 -0
- data/src/html/del-ins.js +25 -0
- data/src/html/div.js +28 -0
- data/src/html/document.js +364 -0
- data/src/html/element.js +382 -0
- data/src/html/fieldset.js +19 -0
- data/src/html/form.js +484 -0
- data/src/html/frame.js +89 -0
- data/src/html/frameset.js +25 -0
- data/src/html/head.js +44 -0
- data/src/html/html.js +0 -0
- data/src/html/htmlparser.js +340 -0
- data/src/html/iframe.js +26 -0
- data/src/html/image.js +0 -0
- data/src/html/img.js +62 -0
- data/src/html/input-elements.js +307 -0
- data/src/html/input.js +65 -0
- data/src/html/label.js +26 -0
- data/src/html/legend.js +19 -0
- data/src/html/link.js +82 -0
- data/src/html/map.js +22 -0
- data/src/html/meta.js +37 -0
- data/src/html/object.js +89 -0
- data/src/html/optgroup.js +25 -0
- data/src/html/option.js +103 -0
- data/src/html/param.js +38 -0
- data/src/html/script.js +122 -0
- data/src/html/select.js +132 -0
- data/src/html/style.js +31 -0
- data/src/html/table.js +199 -0
- data/src/html/tbody-thead-tfoot.js +92 -0
- data/src/html/td-th.js +18 -0
- data/src/html/textarea.js +31 -0
- data/src/html/title.js +20 -0
- data/src/html/tr.js +114 -0
- data/src/intro.js +141 -0
- data/src/outro.js +70 -0
- data/src/parser/html5.detailed.js +10762 -0
- data/src/parser/html5.min.js +503 -0
- data/src/parser/html5.pretty.js +10815 -0
- data/src/parser/intro.js +42 -0
- data/src/parser/outro.js +9 -0
- data/src/platform/core.js +323 -0
- data/src/platform/johnson.js +484 -0
- data/src/platform/rhino.js +327 -0
- data/src/platform/static/intro.js +41 -0
- data/src/platform/static/outro.js +30 -0
- data/src/profile/aop.js +238 -0
- data/src/profile/profile.js +402 -0
- data/src/serializer/xml.js +21 -0
- data/src/svg/animatedstring.js +25 -0
- data/src/svg/document.js +25 -0
- data/src/svg/element.js +22 -0
- data/src/svg/locatable.js +17 -0
- data/src/svg/rect.js +18 -0
- data/src/svg/rectelement.js +24 -0
- data/src/svg/stylable.js +49 -0
- data/src/svg/svgelement.js +22 -0
- data/src/svg/transformable.js +15 -0
- data/src/window/css.js +15 -0
- data/src/window/dialog.js +16 -0
- data/src/window/document.js +28 -0
- data/src/window/event.js +265 -0
- data/src/window/history.js +62 -0
- data/src/window/location.js +156 -0
- data/src/window/navigator.js +48 -0
- data/src/window/screen.js +53 -0
- data/src/window/timer.js +21 -0
- data/src/window/window.js +284 -0
- data/src/window/xhr.js +135 -0
- data/src/xpath/expression.js +49 -0
- data/src/xpath/implementation.js +2505 -0
- data/src/xpath/result.js +67 -0
- data/src/xpath/util.js +551 -0
- data/src/xpath/xmltoken.js +149 -0
- data/src/xslt/COPYING +34 -0
- data/src/xslt/ajaxslt-0.8.1/AUTHORS +1 -0
- data/src/xslt/ajaxslt-0.8.1/ChangeLog +136 -0
- data/src/xslt/ajaxslt-0.8.1/Makefile +49 -0
- data/src/xslt/ajaxslt-0.8.1/README +102 -0
- data/src/xslt/ajaxslt-0.8.1/TODO +15 -0
- data/src/xslt/ajaxslt-0.8.1/dom.js +566 -0
- data/src/xslt/ajaxslt-0.8.1/dom_unittest.html +24 -0
- data/src/xslt/ajaxslt-0.8.1/dom_unittest.js +131 -0
- data/src/xslt/ajaxslt-0.8.1/simplelog.js +79 -0
- data/src/xslt/ajaxslt-0.8.1/test/xpath.html +18 -0
- data/src/xslt/ajaxslt-0.8.1/test/xpath_script.js +45 -0
- data/src/xslt/ajaxslt-0.8.1/test/xslt.html +58 -0
- data/src/xslt/ajaxslt-0.8.1/test/xslt_script.js +33 -0
- data/src/xslt/ajaxslt-0.8.1/unittestsuite.html +26 -0
- data/src/xslt/ajaxslt-0.8.1/xmltoken.js +149 -0
- data/src/xslt/ajaxslt-0.8.1/xmltoken_unittest.html +18 -0
- data/src/xslt/ajaxslt-0.8.1/xmltoken_unittest.js +811 -0
- data/src/xslt/ajaxslt-0.8.1/xpath_unittest.html +39 -0
- data/src/xslt/ajaxslt-0.8.1/xpath_unittest.js +557 -0
- data/src/xslt/ajaxslt-0.8.1/xpathdebug.js +234 -0
- data/src/xslt/ajaxslt-0.8.1/xslt_unittest.html +138 -0
- data/src/xslt/ajaxslt-0.8.1/xslt_unittest.js +68 -0
- data/src/xslt/implementation.js +625 -0
- data/src/xslt/processor.js +37 -0
- data/src/xslt/util.js +449 -0
- data/test/base64.js +80 -0
- data/test/call-load-test.js +15 -0
- data/test/data.js +45 -0
- data/test/debug.js +53 -0
- data/test/firebug/errorIcon.png +0 -0
- data/test/firebug/firebug.css +209 -0
- data/test/firebug/firebug.html +23 -0
- data/test/firebug/firebug.js +672 -0
- data/test/firebug/firebugx.js +10 -0
- data/test/firebug/infoIcon.png +0 -0
- data/test/firebug/warningIcon.png +0 -0
- data/test/fixtures/html/events.html +171 -0
- data/test/fixtures/html/iframe1.html +46 -0
- data/test/fixtures/html/iframe1a.html +46 -0
- data/test/fixtures/html/iframe2.html +45 -0
- data/test/fixtures/html/iframe3.html +28 -0
- data/test/fixtures/html/iframeN.html +57 -0
- data/test/fixtures/html/malformed.html +181 -0
- data/test/fixtures/html/scope.html +81 -0
- data/test/fixtures/html/trivial.html +19 -0
- data/test/fixtures/html/with_js.html +26 -0
- data/test/fixtures/images/icon-blue.png +0 -0
- data/test/fixtures/js/external_script.js +1 -0
- data/test/fixtures/js/script.js +1 -0
- data/test/fixtures/js/script_error.js +2 -0
- data/test/foo.html +8 -0
- data/test/foo.js +40 -0
- data/test/html/events.html +171 -0
- data/test/html/iframe1.html +46 -0
- data/test/html/iframe1a.html +46 -0
- data/test/html/iframe2.html +45 -0
- data/test/html/iframe3.html +30 -0
- data/test/html/iframeN.html +57 -0
- data/test/html/malformed.html +181 -0
- data/test/html/scope.html +87 -0
- data/test/html/script.js +1 -0
- data/test/html/trivial.html +19 -0
- data/test/html/with_js.html +26 -0
- data/test/index.html +328 -0
- data/test/java-prototype.js +9 -0
- data/test/jquery.js +6002 -0
- data/test/primary-tests.js +26 -0
- data/test/prototype-test.js +13 -0
- data/test/qunit.js +61 -0
- data/test/qunit/qunit/qunit.css +17 -0
- data/test/qunit/qunit/qunit.js +997 -0
- data/test/scope.html +19 -0
- data/test/scope.rb +24 -0
- data/test/smp/dmathieu/index.html +8 -0
- data/test/specs/dist/env.spec.js +1534 -0
- data/test/specs/envjs.spec.css +46 -0
- data/test/specs/parser/html.js +31 -0
- data/test/specs/parser/spec.html +40 -0
- data/test/specs/parser/xml.js +31 -0
- data/test/specs/qunit.bdd.js +210 -0
- data/test/specs/qunit.css +17 -0
- data/test/specs/qunit.js +997 -0
- data/test/specs/template/spec-0.js +31 -0
- data/test/specs/template/spec-1.js +31 -0
- data/test/specs/template/spec.html +40 -0
- data/test/specs/window/css.js +23 -0
- data/test/specs/window/dialog.js +25 -0
- data/test/specs/window/document.js +23 -0
- data/test/specs/window/event.js +25 -0
- data/test/specs/window/history.js +34 -0
- data/test/specs/window/location.js +34 -0
- data/test/specs/window/navigator.js +71 -0
- data/test/specs/window/screen.js +42 -0
- data/test/specs/window/spec.html +48 -0
- data/test/specs/window/timer.js +26 -0
- data/test/specs/window/window.js +53 -0
- data/test/specs/xhr/spec.html +47 -0
- data/test/specs/xhr/xhr.js +31 -0
- data/test/test.js +10 -0
- data/test/unit/dom.js +44 -0
- data/test/unit/elementmembers.js +92 -0
- data/test/unit/events.js +195 -0
- data/test/unit/fixtures/external_script.js +1 -0
- data/test/unit/form.js +40 -0
- data/test/unit/iframe.js +234 -0
- data/test/unit/insertion.js +23 -0
- data/test/unit/multi-window.js +212 -0
- data/test/unit/nu.validator.js +34 -0
- data/test/unit/onload.js +90 -0
- data/test/unit/parser.js +122 -0
- data/test/unit/prototypecompat.js +22 -0
- data/test/unit/proxy.js +6 -0
- data/test/unit/scope.js +209 -0
- data/test/unit/timer.js +115 -0
- data/test/unit/window.js +57 -0
- data/test/x.js +1 -0
- data/test/y.js +1 -0
- 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
|
+
}
|