xslt-processor 1.1.5 → 1.2.0

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 (90) hide show
  1. package/README.md +3 -1
  2. package/dom/functions.d.ts +11 -5
  3. package/dom/functions.js +11 -6
  4. package/dom/functions.js.map +1 -1
  5. package/dom/util.d.ts +2 -21
  6. package/dom/util.js +3 -111
  7. package/dom/util.js.map +1 -1
  8. package/dom/xdocument.d.ts +9 -9
  9. package/dom/xdocument.js.map +1 -1
  10. package/dom/xml-functions.d.ts +3 -3
  11. package/dom/xml-functions.js +41 -25
  12. package/dom/xml-functions.js.map +1 -1
  13. package/dom/xml-output-options.d.ts +1 -0
  14. package/dom/xnode.d.ts +8 -4
  15. package/dom/xnode.js +30 -11
  16. package/dom/xnode.js.map +1 -1
  17. package/package.json +1 -1
  18. package/umd/dom/functions.d.ts +11 -5
  19. package/umd/dom/util.d.ts +2 -21
  20. package/umd/dom/xdocument.d.ts +9 -9
  21. package/umd/dom/xml-functions.d.ts +3 -3
  22. package/umd/dom/xml-output-options.d.ts +1 -0
  23. package/umd/dom/xnode.d.ts +8 -4
  24. package/umd/xpath/common-function.d.ts +8 -0
  25. package/umd/xpath/expr-context.d.ts +79 -6
  26. package/umd/xpath/expressions/function-call-expr.d.ts +3 -41
  27. package/umd/xpath/expressions/location-expr.d.ts +2 -1
  28. package/umd/xpath/expressions/step-expr.d.ts +16 -6
  29. package/umd/xpath/expressions/union-expr.d.ts +4 -4
  30. package/umd/xpath/functions/index.d.ts +2 -0
  31. package/umd/xpath/functions/internal-functions.d.ts +2 -0
  32. package/umd/xpath/functions/non-standard.d.ts +12 -0
  33. package/umd/xpath/functions/standard.d.ts +33 -0
  34. package/umd/xpath/tokens.d.ts +2 -1
  35. package/umd/xpath/xpath.d.ts +27 -12
  36. package/umd/xslt/xslt-options.d.ts +1 -0
  37. package/umd/xslt/xslt.d.ts +32 -18
  38. package/umd/xslt-processor.js +2 -2
  39. package/umd/xslt-processor.js.map +1 -1
  40. package/xpath/common-function.d.ts +8 -0
  41. package/xpath/common-function.js +33 -0
  42. package/xpath/common-function.js.map +1 -0
  43. package/xpath/expr-context.d.ts +79 -6
  44. package/xpath/expr-context.js +82 -59
  45. package/xpath/expr-context.js.map +1 -1
  46. package/xpath/expressions/filter-expr.js +1 -1
  47. package/xpath/expressions/filter-expr.js.map +1 -1
  48. package/xpath/expressions/function-call-expr.d.ts +3 -41
  49. package/xpath/expressions/function-call-expr.js +42 -346
  50. package/xpath/expressions/function-call-expr.js.map +1 -1
  51. package/xpath/expressions/location-expr.d.ts +2 -1
  52. package/xpath/expressions/location-expr.js +9 -9
  53. package/xpath/expressions/location-expr.js.map +1 -1
  54. package/xpath/expressions/path-expr.js +2 -2
  55. package/xpath/expressions/path-expr.js.map +1 -1
  56. package/xpath/expressions/step-expr.d.ts +16 -6
  57. package/xpath/expressions/step-expr.js +184 -113
  58. package/xpath/expressions/step-expr.js.map +1 -1
  59. package/xpath/expressions/union-expr.d.ts +4 -4
  60. package/xpath/expressions/union-expr.js +3 -3
  61. package/xpath/expressions/union-expr.js.map +1 -1
  62. package/xpath/functions/index.d.ts +2 -0
  63. package/xpath/functions/index.js +19 -0
  64. package/xpath/functions/index.js.map +1 -0
  65. package/xpath/functions/internal-functions.d.ts +2 -0
  66. package/xpath/functions/internal-functions.js +23 -0
  67. package/xpath/functions/internal-functions.js.map +1 -0
  68. package/xpath/functions/non-standard.d.ts +12 -0
  69. package/xpath/functions/non-standard.js +46 -0
  70. package/xpath/functions/non-standard.js.map +1 -0
  71. package/xpath/functions/standard.d.ts +33 -0
  72. package/xpath/functions/standard.js +345 -0
  73. package/xpath/functions/standard.js.map +1 -0
  74. package/xpath/node-test-element-or-attribute.js +1 -1
  75. package/xpath/node-test-name.js +1 -1
  76. package/xpath/tokens.d.ts +2 -1
  77. package/xpath/tokens.js +19 -17
  78. package/xpath/tokens.js.map +1 -1
  79. package/xpath/values/index.js +32 -0
  80. package/xpath/values/index.js.map +1 -1
  81. package/xpath/values/string-value.js +0 -32
  82. package/xpath/values/string-value.js.map +1 -1
  83. package/xpath/xpath.d.ts +27 -12
  84. package/xpath/xpath.js +96 -75
  85. package/xpath/xpath.js.map +1 -1
  86. package/xpathdebug.js +4 -4
  87. package/xslt/xslt-options.d.ts +1 -0
  88. package/xslt/xslt.d.ts +32 -18
  89. package/xslt/xslt.js +232 -171
  90. package/xslt/xslt.js.map +1 -1
package/xslt/xslt.js CHANGED
@@ -42,9 +42,17 @@ var expressions_1 = require("../xpath/expressions");
42
42
  */
43
43
  var Xslt = /** @class */ (function () {
44
44
  function Xslt(options) {
45
- if (options === void 0) { options = { escape: true }; }
45
+ if (options === void 0) { options = {
46
+ escape: true,
47
+ selfClosingTags: true,
48
+ parameters: []
49
+ }; }
46
50
  this.xPath = new xpath_1.XPath();
47
- this.options = options;
51
+ this.options = {
52
+ escape: options.escape || true,
53
+ selfClosingTags: options.selfClosingTags || true,
54
+ parameters: options.parameters || []
55
+ };
48
56
  this.outputMethod = 'xml';
49
57
  this.outputOmitXmlDeclaration = 'no';
50
58
  }
@@ -52,23 +60,24 @@ var Xslt = /** @class */ (function () {
52
60
  * The exported entry point of the XSL-T processor.
53
61
  * @param xmlDoc The input document root, as DOM node.
54
62
  * @param stylesheet The stylesheet document root, as DOM node.
55
- * @param parameters Additional parameters to be set as variables.
56
63
  * @returns the processed document, as XML text in a string.
57
64
  */
58
- Xslt.prototype.xsltProcess = function (xmlDoc, stylesheet, parameters) {
59
- var output = new dom_1.XDocument();
60
- output.appendChild(dom_1.XNode.clone(xmlDoc.childNodes[0], output));
61
- var expressionContext = new xpath_1.ExprContext([output]);
62
- if (parameters && parameters.length > 0) {
63
- for (var _i = 0, parameters_1 = parameters; _i < parameters_1.length; _i++) {
64
- var parameter = parameters_1[_i];
65
+ Xslt.prototype.xsltProcess = function (xmlDoc, stylesheet) {
66
+ var outputDocument = new dom_1.XDocument();
67
+ this.outputDocument = outputDocument;
68
+ // output.appendChild(XNode.clone(xmlDoc.childNodes[0], output));
69
+ var expressionContext = new xpath_1.ExprContext([xmlDoc], [outputDocument]);
70
+ if (this.options.parameters.length > 0) {
71
+ for (var _i = 0, _a = this.options.parameters; _i < _a.length; _i++) {
72
+ var parameter = _a[_i];
65
73
  expressionContext.setVariable(parameter.name, new values_1.StringValue(parameter.value));
66
74
  }
67
75
  }
68
- this.xsltProcessContext(expressionContext, stylesheet, output, parameters || []);
69
- var ret = (0, dom_1.xmlTransformedText)(output, {
76
+ this.xsltProcessContext(expressionContext, stylesheet, outputDocument);
77
+ var ret = (0, dom_1.xmlTransformedText)(outputDocument, {
70
78
  cData: false,
71
- escape: this.options.escape
79
+ escape: this.options.escape,
80
+ selfClosingTags: this.options.selfClosingTags
72
81
  });
73
82
  return ret;
74
83
  };
@@ -77,90 +86,101 @@ var Xslt = /** @class */ (function () {
77
86
  * @param context The input document root, as XPath ExprContext.
78
87
  * @param template The stylesheet document root, as DOM node.
79
88
  * @param output the root of the generated output, as DOM node.
80
- * @param _parameters Extra parameters.
81
89
  */
82
- Xslt.prototype.xsltProcessContext = function (context, template, output, _parameters) {
83
- var outputDocument = (0, dom_1.xmlOwnerDocument)(output);
90
+ Xslt.prototype.xsltProcessContext = function (context, template, output) {
91
+ var _this = this;
84
92
  if (!this.isXsltElement(template)) {
85
- this.xsltPassThrough(context, template, output, outputDocument);
93
+ this.xsltPassThrough(context, template, output);
86
94
  }
87
95
  else {
88
- var name_1, top_1, nameExpr = void 0, node = void 0, select = void 0, value = void 0, nodes = void 0, sortContext = void 0, mode = void 0, templates = void 0, paramContext = void 0, commentData = void 0, commentNode = void 0, test_1, match = void 0, text = void 0;
96
+ var name_1, top_1, nameExpr = void 0, node = void 0, select = void 0, value = void 0, nodes = void 0, mode = void 0, templates = void 0, paramContext = void 0, commentData = void 0, commentNode = void 0, test_1, match = void 0, text = void 0;
89
97
  switch (template.localName) {
90
98
  case 'apply-imports':
91
- throw "not implemented: ".concat(template.localName);
99
+ throw new Error("not implemented: ".concat(template.localName));
92
100
  case 'apply-templates':
93
101
  select = (0, dom_1.xmlGetAttribute)(template, 'select');
94
102
  if (select) {
95
103
  nodes = this.xPath.xPathEval(select, context).nodeSetValue();
96
104
  }
97
105
  else {
98
- nodes = context.nodelist[context.position].childNodes;
106
+ nodes = context.nodeList[context.position].childNodes;
99
107
  }
100
- sortContext = context.clone(nodes, 0);
101
- this.xsltWithParam(sortContext, template, _parameters);
102
- this.xsltSort(sortContext, template);
108
+ // TODO: Check why apply-templates was sorting and filing parameters
109
+ // automatically.
110
+ /* this.xsltWithParam(sortContext, template);
111
+ this.xsltSort(sortContext, template); */
103
112
  mode = (0, dom_1.xmlGetAttribute)(template, 'mode');
104
113
  top_1 = template.ownerDocument.documentElement;
105
114
  templates = [];
106
- for (var i = 0; i < top_1.childNodes.length; ++i) {
107
- var c = top_1.childNodes[i];
108
- var matchAttribute = c.getAttributeValue('match');
109
- // Avoiding infinite loops.
110
- if (matchAttribute && matchAttribute.startsWith('/')) {
115
+ for (var _i = 0, _a = top_1.childNodes
116
+ .filter(function (c) { return c.nodeType == constants_1.DOM_ELEMENT_NODE &&
117
+ _this.isXsltElement(c, 'template'); }); _i < _a.length; _i++) {
118
+ var element = _a[_i];
119
+ // Actual template should be executed.
120
+ // `<xsl:apply-templates>` should have an ancestor `<xsl:template>`
121
+ // for comparison.
122
+ var templateAncestor = template.getAncestorByLocalName("template");
123
+ if (templateAncestor === undefined) {
111
124
  continue;
112
125
  }
113
- if (c.nodeType == constants_1.DOM_ELEMENT_NODE &&
114
- this.isXsltElement(c, 'template') &&
115
- (!mode || c.getAttributeValue('mode') == mode)) {
116
- templates.push(c);
126
+ if (templateAncestor.id === element.id) {
127
+ continue;
128
+ }
129
+ if (!mode || element.getAttributeValue('mode') === mode) {
130
+ templates.push(element);
117
131
  }
118
132
  }
119
- for (var j = 0; j < sortContext.contextSize(); ++j) {
120
- for (var i = 0; i < templates.length; ++i) {
121
- this.xsltProcessContext(sortContext.clone(sortContext.nodelist, j), templates[i], output, _parameters);
133
+ var modifiedContext = context.clone(nodes);
134
+ for (var i = 0; i < templates.length; ++i) {
135
+ for (var j = 0; j < modifiedContext.contextSize(); ++j) {
136
+ var clonedContext_1 = modifiedContext.clone([modifiedContext.nodeList[j]], undefined, 0, undefined);
137
+ clonedContext_1.inApplyTemplates = true;
138
+ // The output depth should be restarted, since
139
+ // another template is being applied from this point.
140
+ clonedContext_1.outputDepth = 0;
141
+ this.xsltProcessContext(clonedContext_1, templates[i], output);
122
142
  }
123
143
  }
124
144
  break;
125
145
  case 'attribute':
126
146
  nameExpr = (0, dom_1.xmlGetAttribute)(template, 'name');
127
147
  name_1 = this.xsltAttributeValue(nameExpr, context);
128
- node = (0, dom_1.domCreateDocumentFragment)(outputDocument);
129
- this.xsltChildNodes(context, template, node, _parameters);
148
+ node = (0, dom_1.domCreateDocumentFragment)(this.outputDocument);
149
+ this.xsltChildNodes(context, template, node);
130
150
  value = (0, dom_1.xmlValue2)(node);
131
151
  (0, dom_1.domSetTransformedAttribute)(output, name_1, value);
132
152
  break;
133
153
  case 'attribute-set':
134
- throw "not implemented: ".concat(template.localName);
154
+ throw new Error("not implemented: ".concat(template.localName));
135
155
  case 'call-template':
136
156
  name_1 = (0, dom_1.xmlGetAttribute)(template, 'name');
137
157
  top_1 = template.ownerDocument.documentElement;
138
158
  paramContext = context.clone();
139
- this.xsltWithParam(paramContext, template, _parameters);
159
+ this.xsltWithParam(paramContext, template);
140
160
  for (var i = 0; i < top_1.childNodes.length; ++i) {
141
161
  var c = top_1.childNodes[i];
142
162
  if (c.nodeType == constants_1.DOM_ELEMENT_NODE &&
143
163
  this.isXsltElement(c, 'template') &&
144
164
  (0, dom_1.domGetAttributeValue)(c, 'name') == name_1) {
145
- this.xsltChildNodes(paramContext, c, output, _parameters);
165
+ this.xsltChildNodes(paramContext, c, output);
146
166
  break;
147
167
  }
148
168
  }
149
169
  break;
150
170
  case 'choose':
151
- this.xsltChoose(context, template, output, _parameters);
171
+ this.xsltChoose(context, template, output);
152
172
  break;
153
173
  case 'comment':
154
- node = (0, dom_1.domCreateDocumentFragment)(outputDocument);
155
- this.xsltChildNodes(context, template, node, _parameters);
174
+ node = (0, dom_1.domCreateDocumentFragment)(this.outputDocument);
175
+ this.xsltChildNodes(context, template, node);
156
176
  commentData = (0, dom_1.xmlValue)(node);
157
- commentNode = (0, dom_1.domCreateComment)(outputDocument, commentData);
177
+ commentNode = (0, dom_1.domCreateComment)(this.outputDocument, commentData);
158
178
  output.appendChild(commentNode);
159
179
  break;
160
180
  case 'copy':
161
- node = this.xsltCopy(output, context.nodelist[context.position], outputDocument);
181
+ node = this.xsltCopy(output, context.nodeList[context.position], this.outputDocument);
162
182
  if (node) {
163
- this.xsltChildNodes(context, template, node, _parameters);
183
+ this.xsltChildNodes(context, template, node);
164
184
  }
165
185
  break;
166
186
  case 'copy-of':
@@ -169,80 +189,94 @@ var Xslt = /** @class */ (function () {
169
189
  if (value.type == 'node-set') {
170
190
  nodes = value.nodeSetValue();
171
191
  for (var i = 0; i < nodes.length; ++i) {
172
- this.xsltCopyOf(output, nodes[i], outputDocument);
192
+ this.xsltCopyOf(output, nodes[i], this.outputDocument);
173
193
  }
174
194
  }
175
195
  else {
176
- var node_1 = (0, dom_1.domCreateTextNode)(outputDocument, value.stringValue());
196
+ var node_1 = (0, dom_1.domCreateTextNode)(this.outputDocument, value.stringValue());
177
197
  (0, dom_1.domAppendChild)(output, node_1);
178
198
  }
179
199
  break;
180
200
  case 'decimal-format':
181
- throw "not implemented: ".concat(template.localName);
201
+ throw new Error("not implemented: ".concat(template.localName));
182
202
  case 'element':
183
203
  nameExpr = (0, dom_1.xmlGetAttribute)(template, 'name');
184
204
  name_1 = this.xsltAttributeValue(nameExpr, context);
185
- node = (0, dom_1.domCreateElement)(outputDocument, name_1);
186
- // Adds context children reference to this new node,
187
- // so then further transformations are also observed
188
- // by this new node.
189
- var contextNode = context.nodelist[context.position];
190
- node.childNodes = contextNode.childNodes;
205
+ node = (0, dom_1.domCreateElement)(this.outputDocument, name_1);
191
206
  node.transformedNodeName = name_1;
192
- (0, dom_1.domAppendTransformedChild)(output, node);
193
- this.xsltChildNodes(context, template, node, _parameters);
207
+ (0, dom_1.domAppendTransformedChild)(context.outputNodeList[context.outputPosition], node);
208
+ var clonedContext = context.clone(undefined, [node], undefined, 0);
209
+ this.xsltChildNodes(clonedContext, template, node);
194
210
  break;
195
211
  case 'fallback':
196
- throw "not implemented: ".concat(template.localName);
212
+ throw new Error("not implemented: ".concat(template.localName));
197
213
  case 'for-each':
198
- this.xsltForEach(context, template, output, _parameters);
214
+ this.xsltForEach(context, template, output);
199
215
  break;
200
216
  case 'if':
201
217
  test_1 = (0, dom_1.xmlGetAttribute)(template, 'test');
202
218
  if (this.xPath.xPathEval(test_1, context).booleanValue()) {
203
- this.xsltChildNodes(context, template, output, _parameters);
219
+ this.xsltChildNodes(context, template, output);
204
220
  }
205
221
  break;
206
222
  case 'import':
207
- throw "not implemented: ".concat(template.localName);
223
+ throw new Error("not implemented: ".concat(template.localName));
208
224
  case 'include':
209
- throw "not implemented: ".concat(template.localName);
225
+ throw new Error("not implemented: ".concat(template.localName));
210
226
  case 'key':
211
- throw "not implemented: ".concat(template.localName);
227
+ throw new Error("not implemented: ".concat(template.localName));
212
228
  case 'message':
213
- throw "not implemented: ".concat(template.localName);
229
+ throw new Error("not implemented: ".concat(template.localName));
214
230
  case 'namespace-alias':
215
- throw "not implemented: ".concat(template.localName);
231
+ throw new Error("not implemented: ".concat(template.localName));
216
232
  case 'number':
217
- throw "not implemented: ".concat(template.localName);
233
+ throw new Error("not implemented: ".concat(template.localName));
218
234
  case 'otherwise':
219
235
  throw "error if here: ".concat(template.localName);
220
236
  case 'output':
221
237
  this.outputMethod = (0, dom_1.xmlGetAttribute)(template, 'method');
222
238
  this.outputOmitXmlDeclaration = (0, dom_1.xmlGetAttribute)(template, 'omit-xml-declaration');
223
239
  break;
240
+ case 'param':
241
+ this.xsltVariable(context, template, false);
242
+ break;
224
243
  case 'preserve-space':
225
- throw "not implemented: ".concat(template.localName);
244
+ throw new Error("not implemented: ".concat(template.localName));
226
245
  case 'processing-instruction':
227
- throw "not implemented: ".concat(template.localName);
246
+ throw new Error("not implemented: ".concat(template.localName));
228
247
  case 'sort':
229
- // just ignore -- was handled by xsltSort()
248
+ this.xsltSort(context, template);
230
249
  break;
231
250
  case 'strip-space':
232
- throw "not implemented: ".concat(template.localName);
251
+ throw new Error("not implemented: ".concat(template.localName));
233
252
  case 'stylesheet':
234
253
  case 'transform':
235
- this.xsltChildNodes(context, template, output, _parameters);
254
+ this.xsltChildNodes(context, template, output);
236
255
  break;
237
256
  case 'template':
257
+ // If `<xsl:template>` is executed outside `<xsl:apply-templates>`,
258
+ // only one match is accepted per level (or per context here).
259
+ if (!context.inApplyTemplates && context.baseTemplateMatched) {
260
+ break;
261
+ }
238
262
  match = (0, dom_1.xmlGetAttribute)(template, 'match');
239
- if (match && this.xsltMatch(match, context)) {
240
- this.xsltChildNodes(context, template, output, _parameters);
263
+ if (!match)
264
+ break;
265
+ // XPath doesn't have an axis to select "self and siblings", and
266
+ // the default axis is "child", so to select the correct children
267
+ // in relative path, we force a 'self-and-siblings' axis.
268
+ // nodes = this.xsltMatch(match, context, context.inApplyTemplates ? 'self-and-siblings' : undefined);
269
+ nodes = this.xsltMatch(match, context, 'self-and-siblings');
270
+ if (nodes.length > 0) {
271
+ if (!context.inApplyTemplates) {
272
+ context.baseTemplateMatched = true;
273
+ }
274
+ this.xsltChildNodes(context, template, output);
241
275
  }
242
276
  break;
243
277
  case 'text':
244
278
  text = (0, dom_1.xmlValue)(template);
245
- node = (0, dom_1.domCreateTransformedTextNode)(outputDocument, text);
279
+ node = (0, dom_1.domCreateTransformedTextNode)(this.outputDocument, text);
246
280
  var disableOutputEscaping = template.attributes.filter(function (a) { return a.nodeName === 'disable-output-escaping'; });
247
281
  if (disableOutputEscaping.length > 0 && disableOutputEscaping[0].nodeValue === 'yes') {
248
282
  node.escape = false;
@@ -253,21 +287,19 @@ var Xslt = /** @class */ (function () {
253
287
  select = (0, dom_1.xmlGetAttribute)(template, 'select');
254
288
  var attribute = this.xPath.xPathEval(select, context);
255
289
  value = attribute.stringValue();
256
- node = (0, dom_1.domCreateTransformedTextNode)(outputDocument, value);
257
- context.nodelist[context.position].appendTransformedChild(node);
258
- break;
259
- case 'param':
260
- this.xsltVariable(context, template, false, _parameters);
290
+ node = (0, dom_1.domCreateTransformedTextNode)(this.outputDocument, value);
291
+ node.siblingPosition = context.nodeList[context.position].siblingPosition;
292
+ context.outputNodeList[context.outputPosition].appendTransformedChild(node);
261
293
  break;
262
294
  case 'variable':
263
- this.xsltVariable(context, template, true, _parameters);
295
+ this.xsltVariable(context, template, true);
264
296
  break;
265
297
  case 'when':
266
- throw "error if here: ".concat(template.localName);
298
+ throw new Error("error if here: ".concat(template.localName));
267
299
  case 'with-param':
268
- throw "error if here: ".concat(template.localName);
300
+ throw new Error("error if here: ".concat(template.localName));
269
301
  default:
270
- throw "error if here: ".concat(template.localName);
302
+ throw new Error("error if here: ".concat(template.localName));
271
303
  }
272
304
  }
273
305
  };
@@ -314,14 +346,14 @@ var Xslt = /** @class */ (function () {
314
346
  Xslt.prototype.xsltSort = function (context, template) {
315
347
  var sort = [];
316
348
  for (var _i = 0, _a = template.childNodes; _i < _a.length; _i++) {
317
- var c = _a[_i];
318
- if (c.nodeType == constants_1.DOM_ELEMENT_NODE && this.isXsltElement(c, 'sort')) {
319
- var select = (0, dom_1.xmlGetAttribute)(c, 'select');
320
- var expr = this.xPath.xPathParse(select);
321
- var type = (0, dom_1.xmlGetAttribute)(c, 'data-type') || 'text';
322
- var order = (0, dom_1.xmlGetAttribute)(c, 'order') || 'ascending';
349
+ var childNode = _a[_i];
350
+ if (childNode.nodeType == constants_1.DOM_ELEMENT_NODE && this.isXsltElement(childNode, 'sort')) {
351
+ var select = (0, dom_1.xmlGetAttribute)(childNode, 'select');
352
+ var expression = this.xPath.xPathParse(select);
353
+ var type = (0, dom_1.xmlGetAttribute)(childNode, 'data-type') || 'text';
354
+ var order = (0, dom_1.xmlGetAttribute)(childNode, 'order') || 'ascending';
323
355
  sort.push({
324
- expr: expr,
356
+ expr: expression,
325
357
  type: type,
326
358
  order: order
327
359
  });
@@ -340,13 +372,13 @@ var Xslt = /** @class */ (function () {
340
372
  * case. I.e. decides if this is a default value or a local
341
373
  * value. `xsl:variable` and `xsl:with-param` override; `xsl:param` doesn't.
342
374
  */
343
- Xslt.prototype.xsltVariable = function (input, template, override, _parameters) {
375
+ Xslt.prototype.xsltVariable = function (input, template, override) {
344
376
  var name = (0, dom_1.xmlGetAttribute)(template, 'name');
345
377
  var select = (0, dom_1.xmlGetAttribute)(template, 'select');
346
378
  var value;
347
379
  if (template.childNodes.length > 0) {
348
380
  var root = (0, dom_1.domCreateDocumentFragment)(template.ownerDocument);
349
- this.xsltChildNodes(input, template, root, _parameters);
381
+ this.xsltChildNodes(input, template, root);
350
382
  value = new values_1.NodeSetValue([root]);
351
383
  }
352
384
  else if (select) {
@@ -354,7 +386,7 @@ var Xslt = /** @class */ (function () {
354
386
  }
355
387
  else {
356
388
  var parameterValue = '';
357
- var filteredParameter = _parameters.filter(function (p) { return p.name === name; });
389
+ var filteredParameter = this.options.parameters.filter(function (p) { return p.name === name; });
358
390
  if (filteredParameter.length > 0) {
359
391
  parameterValue = filteredParameter[0].value;
360
392
  }
@@ -371,7 +403,7 @@ var Xslt = /** @class */ (function () {
371
403
  * @param template The template.
372
404
  * @param output The output.
373
405
  */
374
- Xslt.prototype.xsltChoose = function (input, template, output, _parameters) {
406
+ Xslt.prototype.xsltChoose = function (input, template, output) {
375
407
  for (var _i = 0, _a = template.childNodes; _i < _a.length; _i++) {
376
408
  var childNode = _a[_i];
377
409
  if (childNode.nodeType !== constants_1.DOM_ELEMENT_NODE) {
@@ -380,12 +412,12 @@ var Xslt = /** @class */ (function () {
380
412
  if (this.isXsltElement(childNode, 'when')) {
381
413
  var test_2 = (0, dom_1.xmlGetAttribute)(childNode, 'test');
382
414
  if (this.xPath.xPathEval(test_2, input).booleanValue()) {
383
- this.xsltChildNodes(input, childNode, output, _parameters);
415
+ this.xsltChildNodes(input, childNode, output);
384
416
  break;
385
417
  }
386
418
  }
387
419
  else if (this.isXsltElement(childNode, 'otherwise')) {
388
- this.xsltChildNodes(input, childNode, output, _parameters);
420
+ this.xsltChildNodes(input, childNode, output);
389
421
  break;
390
422
  }
391
423
  }
@@ -396,19 +428,19 @@ var Xslt = /** @class */ (function () {
396
428
  * @param template The template.
397
429
  * @param output The output.
398
430
  */
399
- Xslt.prototype.xsltForEach = function (context, template, output, _parameters) {
431
+ Xslt.prototype.xsltForEach = function (context, template, output) {
400
432
  var select = (0, dom_1.xmlGetAttribute)(template, 'select');
401
433
  var nodes = this.xPath.xPathEval(select, context).nodeSetValue();
402
- var sortContext = context.clone(nodes, 0);
434
+ var sortContext = context.clone(nodes);
403
435
  this.xsltSort(sortContext, template);
404
- var nodesWithParent = sortContext.nodelist.filter(function (n) { return n.parentNode !== null && n.parentNode !== undefined; });
436
+ var nodesWithParent = sortContext.nodeList.filter(function (n) { return n.parentNode !== null && n.parentNode !== undefined; });
405
437
  if (nodesWithParent.length <= 0) {
406
438
  throw new Error('Nodes with no parents defined.');
407
439
  }
408
440
  var parent = nodesWithParent[0].parentNode;
409
- parent.childNodes = sortContext.nodelist;
441
+ parent.childNodes = sortContext.nodeList;
410
442
  for (var i = 0; i < sortContext.contextSize(); ++i) {
411
- this.xsltChildNodes(sortContext.clone(sortContext.nodelist, i), template, output, _parameters);
443
+ this.xsltChildNodes(sortContext.clone(sortContext.nodeList, undefined, i), template, output);
412
444
  }
413
445
  // TODO: group nodes by parent node.
414
446
  // const nodeGroups = this.groupBy(nodes, 'parentNode');
@@ -417,7 +449,7 @@ var Xslt = /** @class */ (function () {
417
449
  this.xsltSort(sortContext, template);
418
450
 
419
451
  for (let i = 0; i < sortContext.contextSize(); ++i) {
420
- this.xsltChildNodes(sortContext.clone(sortContext.nodelist, i), template, output);
452
+ this.xsltChildNodes(sortContext.clone(sortContext.nodeList, i), template, output);
421
453
  }
422
454
  } */
423
455
  };
@@ -435,12 +467,12 @@ var Xslt = /** @class */ (function () {
435
467
  * @param template The XSL-T definition.
436
468
  * @param output The XML output.
437
469
  */
438
- Xslt.prototype.xsltChildNodes = function (context, template, output, _parameters) {
470
+ Xslt.prototype.xsltChildNodes = function (context, template, output) {
439
471
  // Clone input context to keep variables declared here local to the
440
472
  // siblings of the children.
441
473
  var contextClone = context.clone();
442
474
  for (var i = 0; i < template.childNodes.length; ++i) {
443
- this.xsltProcessContext(contextClone, template.childNodes[i], output, _parameters);
475
+ this.xsltProcessContext(contextClone, template.childNodes[i], output);
444
476
  }
445
477
  };
446
478
  /**
@@ -451,52 +483,65 @@ var Xslt = /** @class */ (function () {
451
483
  * @param context The Expression Context.
452
484
  * @param template The XSLT stylesheet or transformation.
453
485
  * @param output The output.
454
- * @param outputDocument The output document, if the case.
455
486
  */
456
- Xslt.prototype.xsltPassThrough = function (context, template, output, outputDocument, _parameters) {
487
+ Xslt.prototype.xsltPassThrough = function (context, template, output) {
457
488
  if (template.nodeType == constants_1.DOM_TEXT_NODE) {
458
489
  if (this.xsltPassText(template)) {
459
- var textNodeList = context.nodelist[context.position].transformedChildNodes.filter(function (n) { return n.nodeType === constants_1.DOM_TEXT_NODE; });
490
+ var textNodeList = context.outputNodeList[context.outputPosition].transformedChildNodes.filter(function (n) { return n.nodeType === constants_1.DOM_TEXT_NODE; });
460
491
  if (textNodeList.length > 0) {
461
492
  var node = textNodeList[0];
462
493
  node.transformedNodeValue = template.nodeValue;
463
494
  }
464
495
  else {
465
- var node = (0, dom_1.domCreateTransformedTextNode)(outputDocument, template.nodeValue);
466
- (0, dom_1.domAppendTransformedChild)(context.nodelist[context.position], node);
496
+ var node = (0, dom_1.domCreateTransformedTextNode)(this.outputDocument, template.nodeValue);
497
+ node.transformedParentNode = context.outputNodeList[context.outputPosition];
498
+ (0, dom_1.domAppendTransformedChild)(context.outputNodeList[context.outputPosition], node);
467
499
  }
468
500
  }
469
501
  }
470
502
  else if (template.nodeType == constants_1.DOM_ELEMENT_NODE) {
471
503
  var node = void 0;
504
+ // let node = domCreateElement(outputDocument, template.nodeName);
472
505
  var elementContext = context;
473
- if (context.nodelist[context.position].nodeName === '#document') {
474
- node = context.nodelist[context.position].firstChild;
475
- elementContext = context.clone([node], 0);
506
+ if (context.nodeList[context.position].nodeName === '#document') {
507
+ node = context.nodeList[context.position].firstChild;
508
+ elementContext = context.clone([node]);
509
+ }
510
+ else {
511
+ node = context.nodeList[context.position];
512
+ }
513
+ var newNode = void 0;
514
+ if (node.outputNode === undefined || node.outputNode === null || context.outputDepth > 0) {
515
+ newNode = (0, dom_1.domCreateElement)(this.outputDocument, template.nodeName);
516
+ newNode.siblingPosition = node.siblingPosition;
517
+ node.outputNode = newNode;
476
518
  }
477
519
  else {
478
- node = context.nodelist[context.position];
520
+ newNode = node.outputNode;
479
521
  }
480
- node.transformedNodeName = template.nodeName;
481
- node.transformedLocalName = template.localName;
522
+ newNode.transformedNodeName = template.nodeName;
523
+ newNode.transformedLocalName = template.localName;
482
524
  var templateAttributes = template.attributes.filter(function (a) { return a; });
483
525
  if (templateAttributes.length === 0) {
484
- node.transformedAttributes = [];
526
+ newNode.transformedAttributes = [];
485
527
  }
486
528
  else {
487
529
  for (var _i = 0, templateAttributes_1 = templateAttributes; _i < templateAttributes_1.length; _i++) {
488
530
  var attribute = templateAttributes_1[_i];
489
531
  var name_2 = attribute.nodeName;
490
532
  var value = this.xsltAttributeValue(attribute.nodeValue, elementContext);
491
- (0, dom_1.domSetTransformedAttribute)(node, name_2, value);
533
+ (0, dom_1.domSetTransformedAttribute)(newNode, name_2, value);
492
534
  }
493
535
  }
494
- this.xsltChildNodes(context, template, node, _parameters);
536
+ var outputNode = context.outputNodeList[context.outputPosition];
537
+ (0, dom_1.domAppendTransformedChild)(outputNode, newNode);
538
+ var clonedContext = elementContext.cloneByOutput(outputNode.transformedChildNodes, outputNode.transformedChildNodes.length - 1, ++elementContext.outputDepth);
539
+ this.xsltChildNodes(clonedContext, template, node);
495
540
  }
496
541
  else {
497
542
  // This applies also to the DOCUMENT_NODE of the XSL stylesheet,
498
543
  // so we don't have to treat it specially.
499
- this.xsltChildNodes(context, template, output, _parameters);
544
+ this.xsltChildNodes(context, template, output);
500
545
  }
501
546
  };
502
547
  /**
@@ -541,7 +586,7 @@ var Xslt = /** @class */ (function () {
541
586
  */
542
587
  Xslt.prototype.xsltAttributeValue = function (value, context) {
543
588
  var parts = value.split('{');
544
- if (parts.length == 1) {
589
+ if (parts.length === 1) {
545
590
  return value;
546
591
  }
547
592
  var ret = '';
@@ -590,39 +635,79 @@ var Xslt = /** @class */ (function () {
590
635
  * match.
591
636
  * @see [XSLT] section 5.2, paragraph 1
592
637
  * @param match TODO
593
- * @param context TODO
594
- * @returns TODO
638
+ * @param context The Expression Context.
639
+ * @param axis The XPath axis. Used when the match does not start with the parent.
640
+ * @returns {XNode[]} A list of the found nodes.
595
641
  */
596
- Xslt.prototype.xsltMatch = function (match, context) {
597
- var expr = this.xPath.xPathParse(match);
598
- if (expr instanceof expressions_1.LocationExpr) {
599
- return this.xsltLocationExpressionMatch(match, expr, context);
642
+ Xslt.prototype.xsltMatch = function (match, context, axis) {
643
+ var expression = this.xPath.xPathParse(match, axis);
644
+ if (expression instanceof expressions_1.LocationExpr) {
645
+ return this.xsltLocationExpressionMatch(expression, context);
646
+ }
647
+ if (expression instanceof expressions_1.UnionExpr) {
648
+ // TODO: What about if `expr1` and `expr2` are not `LocationExpr`?
649
+ return this.xsltLocationExpressionMatch(expression.expr1, context) ||
650
+ this.xsltLocationExpressionMatch(expression.expr2, context);
600
651
  }
601
652
  // TODO: Other expressions
602
- return true;
653
+ return [];
603
654
  };
604
- Xslt.prototype.xsltLocationExpressionMatch = function (match, expression, context) {
655
+ Xslt.prototype.xsltLocationExpressionMatch = function (expression, context) {
605
656
  if (expression === undefined || expression.steps === undefined || expression.steps.length <= 0) {
606
657
  throw new Error('Error resolving XSLT match: Location Expression should have steps.');
607
658
  }
608
- var firstStep = expression.steps[0];
609
- // Shortcut for the most common case.
610
- if (expression.steps &&
611
- !expression.absolute &&
612
- expression.steps.length == 1 &&
613
- firstStep.axis == 'child' &&
614
- firstStep.predicate.length === 0) {
615
- return firstStep.nodetest.evaluate(context).booleanValue();
616
- }
617
- if (expression.absolute && firstStep.axis !== 'self') {
618
- // TODO: `xPathCollectDescendants()`?
619
- var levels = match.split('/');
620
- if (levels.length > 1) {
621
- return this.absoluteXsltMatch(levels, expression, context);
622
- }
659
+ if (expression.absolute) {
660
+ return this.absoluteXsltMatch(expression, context);
623
661
  }
624
662
  return this.relativeXsltMatch(expression, context);
625
663
  };
664
+ /**
665
+ * Finds all the nodes through absolute xPath search.
666
+ * Returns only nodes that match either the context position node,
667
+ * or an ancestor.
668
+ * @param expression The Expression.
669
+ * @param context The Expression Context.
670
+ * @returns The list of found nodes.
671
+ */
672
+ Xslt.prototype.absoluteXsltMatch = function (expression, context) {
673
+ var clonedContext = context.clone([context.root], undefined, 0, undefined);
674
+ var matchedNodes = expression.evaluate(clonedContext).nodeSetValue();
675
+ var finalList = [];
676
+ for (var _i = 0, matchedNodes_1 = matchedNodes; _i < matchedNodes_1.length; _i++) {
677
+ var element = matchedNodes_1[_i];
678
+ if (element.id === context.nodeList[context.position].id) {
679
+ finalList.push(element);
680
+ continue;
681
+ }
682
+ if (element.getAncestorById(context.nodeList[context.position].id) !== undefined) {
683
+ finalList.push(element);
684
+ }
685
+ }
686
+ return finalList;
687
+ };
688
+ /**
689
+ * Tries to find relative nodes from the actual context position.
690
+ * If found nodes are already in the context, or if they are children of
691
+ * nodes in the context, they are returned.
692
+ * @param expression The expression used.
693
+ * @param context The Expression Context.
694
+ * @returns The list of found nodes.
695
+ */
696
+ Xslt.prototype.relativeXsltMatch = function (expression, context) {
697
+ // For some reason, XPath understands a default as 'child axis'.
698
+ // There's no "self + siblings" axis, so what is expected at this point
699
+ // is to have in the expression context the parent that should
700
+ // have the nodes we are interested in.
701
+ var clonedContext = context.clone();
702
+ var nodes = expression.evaluate(clonedContext).nodeSetValue();
703
+ if (nodes.length === 1 && nodes[0].nodeName === "#document") {
704
+ // As we don't work with the #document node directly, this part
705
+ // returns its first sibling.
706
+ // By the way, it should be *always* one sibling here.
707
+ return [nodes[0].childNodes[0]];
708
+ }
709
+ return nodes;
710
+ };
626
711
  /**
627
712
  * Sets parameters defined by xsl:with-param child nodes of the
628
713
  * current template node, in the current input context. This happens
@@ -631,44 +716,20 @@ var Xslt = /** @class */ (function () {
631
716
  * @param input TODO
632
717
  * @param template TODO
633
718
  */
634
- Xslt.prototype.xsltWithParam = function (input, template, _parameters) {
719
+ Xslt.prototype.xsltWithParam = function (input, template) {
635
720
  for (var _i = 0, _a = template.childNodes; _i < _a.length; _i++) {
636
721
  var c = _a[_i];
637
722
  if (c.nodeType === constants_1.DOM_ELEMENT_NODE && this.isXsltElement(c, 'with-param')) {
638
- this.xsltVariable(input, c, true, _parameters);
723
+ this.xsltVariable(input, c, true);
639
724
  }
640
725
  }
641
726
  };
642
- Xslt.prototype.absoluteXsltMatch = function (levels, expr, context) {
643
- var result = expr.evaluate(context.clone([context.nodelist[context.position]], 0)).nodeSetValue();
644
- if (result.length > 0) {
645
- context.nodelist = result;
646
- return true;
647
- }
648
- return false;
649
- };
650
- Xslt.prototype.relativeXsltMatch = function (expr, context) {
651
- var node = context.nodelist[context.position];
652
- while (node) {
653
- var result = expr.evaluate(context.clone([node], 0)).nodeSetValue();
654
- for (var i = 0; i < result.length; ++i) {
655
- if (result[i] == context.nodelist[context.position]) {
656
- /* if (context.node.nodeName === "#document") {
657
- context.node = con
658
- } */
659
- return true;
660
- }
661
- }
662
- node = node.parentNode;
663
- }
664
- return false;
665
- };
666
727
  // Test if the given element is an XSLT element, optionally the one with the given name
667
728
  Xslt.prototype.isXsltElement = function (element, opt_wantedName) {
668
729
  if (opt_wantedName && element.localName != opt_wantedName)
669
730
  return false;
670
- if (element.namespaceURI)
671
- return element.namespaceURI === 'http://www.w3.org/1999/XSL/Transform';
731
+ if (element.namespaceUri)
732
+ return element.namespaceUri === 'http://www.w3.org/1999/XSL/Transform';
672
733
  return element.prefix === 'xsl'; // backwards compatibility with earlier versions of xslt-processor
673
734
  };
674
735
  return Xslt;