xslt-processor 3.0.2 → 3.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.
package/xslt/xslt.js CHANGED
@@ -4,9 +4,6 @@
4
4
  // Copyright 2005 Google Inc.
5
5
  // All Rights Reserved
6
6
  //
7
- // TODO(mesch): add jsdoc comments. Use more coherent naming. Finish
8
- // remaining XSLT features.
9
- //
10
7
  // Original author: Steffen Meschkat <mesch@google.com>
11
8
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
12
9
  if (k2 === undefined) k2 = k;
@@ -88,7 +85,7 @@ var match_resolver_1 = require("../xpath/match-resolver");
88
85
  * <http://www.ecma-international.org/publications/standards/Ecma-262.htm>.
89
86
  *
90
87
  * The XSL processor API has one entry point, the function
91
- * xsltProcessContext(). It receives as arguments the starting point in the
88
+ * `xsltProcess()`. It receives as arguments the starting point in the
92
89
  * input document as an XPath expression context, the DOM root node of
93
90
  * the XSL-T stylesheet, and a DOM node that receives the output.
94
91
  *
@@ -130,6 +127,7 @@ var Xslt = /** @class */ (function () {
130
127
  digit: '#',
131
128
  patternSeparator: ';'
132
129
  };
130
+ this.firstTemplateRan = false;
133
131
  }
134
132
  /**
135
133
  * The exported entry point of the XSL-T processor.
@@ -174,7 +172,7 @@ var Xslt = /** @class */ (function () {
174
172
  */
175
173
  Xslt.prototype.xsltProcessContext = function (context, template, output) {
176
174
  return __awaiter(this, void 0, void 0, function () {
177
- var name_1, top_1, nameExpr, node, select, value, nodes, paramContext, commentData, commentNode, test_1, match, text, _a, i, childNode, destinationCopyNode, destinationNode, i, node_1, decimalSeparator, groupingSeparator, infinity, minusSign, naN, percent, perMille, zeroDigit, digit, patternSeparator, clonedContext, templateContext, disableOutputEscaping, destinationTextNode, attribute;
175
+ var node, select, value, nodes, _a, destinationCopyNode, destinationNode, i, node_1;
178
176
  return __generator(this, function (_b) {
179
177
  switch (_b.label) {
180
178
  case 0:
@@ -182,9 +180,9 @@ var Xslt = /** @class */ (function () {
182
180
  return [4 /*yield*/, this.xsltPassThrough(context, template, output)];
183
181
  case 1:
184
182
  _b.sent();
185
- return [3 /*break*/, 59];
183
+ return [3 /*break*/, 54];
186
184
  case 2:
187
- nameExpr = void 0, node = void 0, select = void 0, value = void 0, nodes = void 0, paramContext = void 0, commentData = void 0, commentNode = void 0, match = void 0, text = void 0;
185
+ node = void 0, select = void 0, value = void 0, nodes = void 0;
188
186
  _a = template.localName;
189
187
  switch (_a) {
190
188
  case 'apply-imports': return [3 /*break*/, 3];
@@ -192,94 +190,70 @@ var Xslt = /** @class */ (function () {
192
190
  case 'attribute': return [3 /*break*/, 6];
193
191
  case 'attribute-set': return [3 /*break*/, 8];
194
192
  case 'call-template': return [3 /*break*/, 9];
195
- case 'choose': return [3 /*break*/, 15];
196
- case 'comment': return [3 /*break*/, 17];
197
- case 'copy': return [3 /*break*/, 19];
198
- case 'copy-of': return [3 /*break*/, 22];
199
- case 'decimal-format': return [3 /*break*/, 23];
200
- case 'element': return [3 /*break*/, 24];
201
- case 'fallback': return [3 /*break*/, 26];
202
- case 'for-each': return [3 /*break*/, 27];
203
- case 'if': return [3 /*break*/, 29];
204
- case 'import': return [3 /*break*/, 32];
205
- case 'include': return [3 /*break*/, 33];
206
- case 'key': return [3 /*break*/, 35];
207
- case 'message': return [3 /*break*/, 36];
208
- case 'namespace-alias': return [3 /*break*/, 37];
209
- case 'number': return [3 /*break*/, 38];
210
- case 'otherwise': return [3 /*break*/, 39];
211
- case 'output': return [3 /*break*/, 40];
212
- case 'param': return [3 /*break*/, 41];
213
- case 'preserve-space': return [3 /*break*/, 43];
214
- case 'processing-instruction': return [3 /*break*/, 44];
215
- case 'sort': return [3 /*break*/, 45];
216
- case 'strip-space': return [3 /*break*/, 46];
217
- case 'stylesheet': return [3 /*break*/, 47];
218
- case 'transform': return [3 /*break*/, 47];
219
- case 'template': return [3 /*break*/, 49];
220
- case 'text': return [3 /*break*/, 52];
221
- case 'value-of': return [3 /*break*/, 53];
222
- case 'variable': return [3 /*break*/, 54];
223
- case 'when': return [3 /*break*/, 56];
224
- case 'with-param': return [3 /*break*/, 57];
193
+ case 'choose': return [3 /*break*/, 11];
194
+ case 'comment': return [3 /*break*/, 13];
195
+ case 'copy': return [3 /*break*/, 15];
196
+ case 'copy-of': return [3 /*break*/, 18];
197
+ case 'decimal-format': return [3 /*break*/, 19];
198
+ case 'element': return [3 /*break*/, 20];
199
+ case 'fallback': return [3 /*break*/, 22];
200
+ case 'for-each': return [3 /*break*/, 23];
201
+ case 'if': return [3 /*break*/, 25];
202
+ case 'import': return [3 /*break*/, 27];
203
+ case 'include': return [3 /*break*/, 29];
204
+ case 'key': return [3 /*break*/, 31];
205
+ case 'message': return [3 /*break*/, 32];
206
+ case 'namespace-alias': return [3 /*break*/, 33];
207
+ case 'number': return [3 /*break*/, 34];
208
+ case 'otherwise': return [3 /*break*/, 35];
209
+ case 'output': return [3 /*break*/, 36];
210
+ case 'param': return [3 /*break*/, 37];
211
+ case 'preserve-space': return [3 /*break*/, 39];
212
+ case 'processing-instruction': return [3 /*break*/, 40];
213
+ case 'sort': return [3 /*break*/, 41];
214
+ case 'strip-space': return [3 /*break*/, 42];
215
+ case 'stylesheet': return [3 /*break*/, 43];
216
+ case 'transform': return [3 /*break*/, 43];
217
+ case 'template': return [3 /*break*/, 45];
218
+ case 'text': return [3 /*break*/, 47];
219
+ case 'value-of': return [3 /*break*/, 48];
220
+ case 'variable': return [3 /*break*/, 49];
221
+ case 'when': return [3 /*break*/, 51];
222
+ case 'with-param': return [3 /*break*/, 52];
225
223
  }
226
- return [3 /*break*/, 58];
224
+ return [3 /*break*/, 53];
227
225
  case 3: throw new Error("not implemented: ".concat(template.localName));
228
226
  case 4: return [4 /*yield*/, this.xsltApplyTemplates(context, template, output)];
229
227
  case 5:
230
228
  _b.sent();
231
- return [3 /*break*/, 59];
229
+ return [3 /*break*/, 54];
232
230
  case 6: return [4 /*yield*/, this.xsltAttribute(context, template, output)];
233
231
  case 7:
234
232
  _b.sent();
235
- return [3 /*break*/, 59];
233
+ return [3 /*break*/, 54];
236
234
  case 8: throw new Error("not implemented: ".concat(template.localName));
237
- case 9:
238
- name_1 = (0, dom_1.xmlGetAttribute)(template, 'name');
239
- top_1 = template.ownerDocument.documentElement;
240
- paramContext = context.clone();
241
- return [4 /*yield*/, this.xsltWithParam(paramContext, template)];
235
+ case 9: return [4 /*yield*/, this.xsltCallTemplate(context, template, output)];
242
236
  case 10:
243
237
  _b.sent();
244
- i = 0;
245
- _b.label = 11;
246
- case 11:
247
- if (!(i < top_1.childNodes.length)) return [3 /*break*/, 14];
248
- childNode = top_1.childNodes[i];
249
- if (!(childNode.nodeType === constants_1.DOM_ELEMENT_NODE &&
250
- this.isXsltElement(childNode, 'template') &&
251
- (0, dom_1.domGetAttributeValue)(childNode, 'name') == name_1)) return [3 /*break*/, 13];
252
- return [4 /*yield*/, this.xsltChildNodes(paramContext, childNode, output)];
238
+ return [3 /*break*/, 54];
239
+ case 11: return [4 /*yield*/, this.xsltChoose(context, template, output)];
253
240
  case 12:
254
241
  _b.sent();
255
- return [3 /*break*/, 14];
256
- case 13:
257
- ++i;
258
- return [3 /*break*/, 11];
259
- case 14: return [3 /*break*/, 59];
260
- case 15: return [4 /*yield*/, this.xsltChoose(context, template, output)];
261
- case 16:
242
+ return [3 /*break*/, 54];
243
+ case 13: return [4 /*yield*/, this.xsltComment(context, template, output)];
244
+ case 14:
262
245
  _b.sent();
263
- return [3 /*break*/, 59];
264
- case 17:
265
- node = (0, dom_1.domCreateDocumentFragment)(this.outputDocument);
266
- return [4 /*yield*/, this.xsltChildNodes(context, template, node)];
267
- case 18:
268
- _b.sent();
269
- commentData = (0, dom_1.xmlValue)(node);
270
- commentNode = (0, dom_1.domCreateComment)(this.outputDocument, commentData);
271
- output.appendChild(commentNode);
272
- return [3 /*break*/, 59];
273
- case 19:
246
+ return [3 /*break*/, 54];
247
+ case 15:
274
248
  destinationCopyNode = output || context.outputNodeList[context.outputPosition];
275
249
  node = this.xsltCopy(destinationCopyNode, context.nodeList[context.position]);
276
- if (!node) return [3 /*break*/, 21];
250
+ if (!node) return [3 /*break*/, 17];
277
251
  return [4 /*yield*/, this.xsltChildNodes(context, template, node)];
278
- case 20:
252
+ case 16:
279
253
  _b.sent();
280
- _b.label = 21;
281
- case 21: return [3 /*break*/, 59];
282
- case 22:
254
+ _b.label = 17;
255
+ case 17: return [3 /*break*/, 54];
256
+ case 18:
283
257
  select = (0, dom_1.xmlGetAttribute)(template, 'select');
284
258
  value = this.xPath.xPathEval(select, context);
285
259
  destinationNode = context.outputNodeList[context.outputPosition] || output;
@@ -293,142 +267,74 @@ var Xslt = /** @class */ (function () {
293
267
  node_1 = (0, dom_1.domCreateTextNode)(this.outputDocument, value.stringValue());
294
268
  (0, dom_1.domAppendChild)(destinationNode, node_1);
295
269
  }
296
- return [3 /*break*/, 59];
297
- case 23:
298
- name_1 = (0, dom_1.xmlGetAttribute)(template, 'name');
299
- decimalSeparator = (0, dom_1.xmlGetAttribute)(template, 'decimal-separator');
300
- groupingSeparator = (0, dom_1.xmlGetAttribute)(template, 'grouping-separator');
301
- infinity = (0, dom_1.xmlGetAttribute)(template, 'infinity');
302
- minusSign = (0, dom_1.xmlGetAttribute)(template, 'minus-sign');
303
- naN = (0, dom_1.xmlGetAttribute)(template, 'NaN');
304
- percent = (0, dom_1.xmlGetAttribute)(template, 'percent');
305
- perMille = (0, dom_1.xmlGetAttribute)(template, 'per-mille');
306
- zeroDigit = (0, dom_1.xmlGetAttribute)(template, 'zero-digit');
307
- digit = (0, dom_1.xmlGetAttribute)(template, 'digit');
308
- patternSeparator = (0, dom_1.xmlGetAttribute)(template, 'pattern-separator');
309
- this.decimalFormatSettings = {
310
- name: name_1 || this.decimalFormatSettings.name,
311
- decimalSeparator: decimalSeparator || this.decimalFormatSettings.decimalSeparator,
312
- groupingSeparator: groupingSeparator || this.decimalFormatSettings.groupingSeparator,
313
- infinity: infinity || this.decimalFormatSettings.infinity,
314
- minusSign: minusSign || this.decimalFormatSettings.minusSign,
315
- naN: naN || this.decimalFormatSettings.naN,
316
- percent: percent || this.decimalFormatSettings.percent,
317
- perMille: perMille || this.decimalFormatSettings.perMille,
318
- zeroDigit: zeroDigit || this.decimalFormatSettings.zeroDigit,
319
- digit: digit || this.decimalFormatSettings.digit,
320
- patternSeparator: patternSeparator || this.decimalFormatSettings.patternSeparator
321
- };
322
- context.decimalFormatSettings = this.decimalFormatSettings;
323
- return [3 /*break*/, 59];
270
+ return [3 /*break*/, 54];
271
+ case 19:
272
+ this.xsltDecimalFormat(context, template);
273
+ return [3 /*break*/, 54];
274
+ case 20: return [4 /*yield*/, this.xsltElement(context, template)];
275
+ case 21:
276
+ _b.sent();
277
+ return [3 /*break*/, 54];
278
+ case 22: throw new Error("not implemented: ".concat(template.localName));
279
+ case 23: return [4 /*yield*/, this.xsltForEach(context, template, output)];
324
280
  case 24:
325
- nameExpr = (0, dom_1.xmlGetAttribute)(template, 'name');
326
- name_1 = this.xsltAttributeValue(nameExpr, context);
327
- node = (0, dom_1.domCreateElement)(this.outputDocument, name_1);
328
- node.transformedNodeName = name_1;
329
- (0, dom_1.domAppendTransformedChild)(context.outputNodeList[context.outputPosition], node);
330
- // The element becomes the output node of the source node.
331
- context.nodeList[context.position].outputNode = node;
332
- clonedContext = context.clone(undefined, [node], undefined, 0);
333
- return [4 /*yield*/, this.xsltChildNodes(clonedContext, template)];
334
- case 25:
335
281
  _b.sent();
336
- return [3 /*break*/, 59];
337
- case 26: throw new Error("not implemented: ".concat(template.localName));
338
- case 27: return [4 /*yield*/, this.xsltForEach(context, template, output)];
282
+ return [3 /*break*/, 54];
283
+ case 25: return [4 /*yield*/, this.xsltIf(context, template, output)];
284
+ case 26:
285
+ _b.sent();
286
+ return [3 /*break*/, 54];
287
+ case 27: return [4 /*yield*/, this.xsltImport(context, template, output)];
339
288
  case 28:
340
289
  _b.sent();
341
- return [3 /*break*/, 59];
342
- case 29:
343
- test_1 = (0, dom_1.xmlGetAttribute)(template, 'test');
344
- if (!this.xPath.xPathEval(test_1, context).booleanValue()) return [3 /*break*/, 31];
345
- return [4 /*yield*/, this.xsltChildNodes(context, template, output)];
290
+ return [3 /*break*/, 54];
291
+ case 29: return [4 /*yield*/, this.xsltInclude(context, template, output)];
346
292
  case 30:
347
293
  _b.sent();
348
- _b.label = 31;
349
- case 31: return [3 /*break*/, 59];
294
+ return [3 /*break*/, 54];
295
+ case 31:
296
+ this.xsltKey(context, template);
297
+ return [3 /*break*/, 54];
350
298
  case 32: throw new Error("not implemented: ".concat(template.localName));
351
- case 33: return [4 /*yield*/, this.xsltInclude(context, template, output)];
352
- case 34:
353
- _b.sent();
354
- return [3 /*break*/, 59];
355
- case 35: throw new Error("not implemented: ".concat(template.localName));
356
- case 36: throw new Error("not implemented: ".concat(template.localName));
357
- case 37: throw new Error("not implemented: ".concat(template.localName));
358
- case 38: throw new Error("not implemented: ".concat(template.localName));
359
- case 39: throw "error if here: ".concat(template.localName);
360
- case 40:
299
+ case 33: throw new Error("not implemented: ".concat(template.localName));
300
+ case 34: throw new Error("not implemented: ".concat(template.localName));
301
+ case 35: throw new Error("xsl:otherwise can't be used outside of xsl:choose.");
302
+ case 36:
361
303
  this.outputMethod = (0, dom_1.xmlGetAttribute)(template, 'method');
362
304
  this.outputOmitXmlDeclaration = (0, dom_1.xmlGetAttribute)(template, 'omit-xml-declaration');
363
- return [3 /*break*/, 59];
364
- case 41: return [4 /*yield*/, this.xsltVariable(context, template, false)];
365
- case 42:
305
+ return [3 /*break*/, 54];
306
+ case 37: return [4 /*yield*/, this.xsltVariable(context, template, false)];
307
+ case 38:
366
308
  _b.sent();
367
- return [3 /*break*/, 59];
368
- case 43: throw new Error("not implemented: ".concat(template.localName));
369
- case 44: throw new Error("not implemented: ".concat(template.localName));
370
- case 45:
309
+ return [3 /*break*/, 54];
310
+ case 39: throw new Error("not implemented: ".concat(template.localName));
311
+ case 40: throw new Error("not implemented: ".concat(template.localName));
312
+ case 41:
371
313
  this.xsltSort(context, template);
372
- return [3 /*break*/, 59];
373
- case 46: throw new Error("not implemented: ".concat(template.localName));
374
- case 47: return [4 /*yield*/, this.xsltTransformOrStylesheet(template, context, output)];
375
- case 48:
314
+ return [3 /*break*/, 54];
315
+ case 42: throw new Error("not implemented: ".concat(template.localName));
316
+ case 43: return [4 /*yield*/, this.xsltTransformOrStylesheet(context, template, output)];
317
+ case 44:
376
318
  _b.sent();
377
- return [3 /*break*/, 59];
378
- case 49:
379
- // If `<xsl:template>` is executed outside `<xsl:apply-templates>`,
380
- // only one match is accepted per level (or per context here).
381
- if (!context.inApplyTemplates && context.baseTemplateMatched) {
382
- return [3 /*break*/, 59];
383
- }
384
- match = (0, dom_1.xmlGetAttribute)(template, 'match');
385
- if (!match)
386
- return [3 /*break*/, 59];
387
- // XPath doesn't have an axis to select "self and siblings", and
388
- // the default axis is "child", so to select the correct children
389
- // in relative path, we force a 'self-and-siblings' axis.
390
- nodes = this.xsltMatch(match, context, 'self-and-siblings');
391
- if (!(nodes.length > 0)) return [3 /*break*/, 51];
392
- if (!context.inApplyTemplates) {
393
- context.baseTemplateMatched = true;
394
- }
395
- templateContext = context.clone(nodes, undefined, 0);
396
- return [4 /*yield*/, this.xsltChildNodes(templateContext, template, output)];
397
- case 50:
319
+ return [3 /*break*/, 54];
320
+ case 45: return [4 /*yield*/, this.xsltTemplate(context, template, output)];
321
+ case 46:
398
322
  _b.sent();
399
- _b.label = 51;
400
- case 51: return [3 /*break*/, 59];
401
- case 52:
402
- text = (0, dom_1.xmlValue)(template);
403
- node = (0, dom_1.domCreateTransformedTextNode)(this.outputDocument, text);
404
- disableOutputEscaping = template.childNodes.filter(function (a) { return a.nodeType === constants_1.DOM_ATTRIBUTE_NODE && a.nodeName === 'disable-output-escaping'; });
405
- if (disableOutputEscaping.length > 0 && disableOutputEscaping[0].nodeValue === 'yes') {
406
- node.escape = false;
407
- }
408
- destinationTextNode = output || context.outputNodeList[context.outputPosition];
409
- destinationTextNode.appendTransformedChild(node);
410
- return [3 /*break*/, 59];
411
- case 53:
412
- select = (0, dom_1.xmlGetAttribute)(template, 'select');
413
- attribute = this.xPath.xPathEval(select, context);
414
- value = attribute.stringValue();
415
- node = (0, dom_1.domCreateTransformedTextNode)(this.outputDocument, value);
416
- node.siblingPosition = context.nodeList[context.position].siblingPosition;
417
- if (output && output.nodeType === constants_1.DOM_DOCUMENT_FRAGMENT_NODE) {
418
- output.appendTransformedChild(node);
419
- }
420
- else {
421
- context.outputNodeList[context.outputPosition].appendTransformedChild(node);
422
- }
423
- return [3 /*break*/, 59];
424
- case 54: return [4 /*yield*/, this.xsltVariable(context, template, true)];
425
- case 55:
323
+ return [3 /*break*/, 54];
324
+ case 47:
325
+ this.xsltText(context, template, output);
326
+ return [3 /*break*/, 54];
327
+ case 48:
328
+ this.xsltValueOf(context, template, output);
329
+ return [3 /*break*/, 54];
330
+ case 49: return [4 /*yield*/, this.xsltVariable(context, template, true)];
331
+ case 50:
426
332
  _b.sent();
427
- return [3 /*break*/, 59];
428
- case 56: throw new Error("error if here: ".concat(template.localName));
429
- case 57: throw new Error("error if here: ".concat(template.localName));
430
- case 58: throw new Error("error if here: ".concat(template.localName));
431
- case 59: return [2 /*return*/];
333
+ return [3 /*break*/, 54];
334
+ case 51: throw new Error("xsl:when can't be used outside of xsl:choose.");
335
+ case 52: throw new Error("error if here: ".concat(template.localName));
336
+ case 53: throw new Error("error if here: ".concat(template.localName));
337
+ case 54: return [2 /*return*/];
432
338
  }
433
339
  });
434
340
  });
@@ -581,6 +487,44 @@ var Xslt = /** @class */ (function () {
581
487
  });
582
488
  });
583
489
  };
490
+ /**
491
+ * Implements `xsl:call-template`.
492
+ * @param context The Expression Context.
493
+ * @param template The template.
494
+ * @param output The output, used when a fragment is passed by a previous step.
495
+ */
496
+ Xslt.prototype.xsltCallTemplate = function (context, template, output) {
497
+ return __awaiter(this, void 0, void 0, function () {
498
+ var name, top, paramContext, i, childNode;
499
+ return __generator(this, function (_a) {
500
+ switch (_a.label) {
501
+ case 0:
502
+ name = (0, dom_1.xmlGetAttribute)(template, 'name');
503
+ top = template.ownerDocument.documentElement;
504
+ paramContext = context.clone();
505
+ return [4 /*yield*/, this.xsltWithParam(paramContext, template)];
506
+ case 1:
507
+ _a.sent();
508
+ i = 0;
509
+ _a.label = 2;
510
+ case 2:
511
+ if (!(i < top.childNodes.length)) return [3 /*break*/, 5];
512
+ childNode = top.childNodes[i];
513
+ if (!(childNode.nodeType === constants_1.DOM_ELEMENT_NODE &&
514
+ this.isXsltElement(childNode, 'template') &&
515
+ (0, dom_1.domGetAttributeValue)(childNode, 'name') === name)) return [3 /*break*/, 4];
516
+ return [4 /*yield*/, this.xsltChildNodes(paramContext, childNode, output)];
517
+ case 3:
518
+ _a.sent();
519
+ return [3 /*break*/, 5];
520
+ case 4:
521
+ ++i;
522
+ return [3 /*break*/, 2];
523
+ case 5: return [2 /*return*/];
524
+ }
525
+ });
526
+ });
527
+ };
584
528
  /**
585
529
  * Implements `xsl:choose`, its child nodes `xsl:when`, and
586
530
  * `xsl:otherwise`.
@@ -590,7 +534,7 @@ var Xslt = /** @class */ (function () {
590
534
  */
591
535
  Xslt.prototype.xsltChoose = function (context, template, output) {
592
536
  return __awaiter(this, void 0, void 0, function () {
593
- var _i, _a, childNode, test_2;
537
+ var _i, _a, childNode, test_1;
594
538
  return __generator(this, function (_b) {
595
539
  switch (_b.label) {
596
540
  case 0:
@@ -603,8 +547,8 @@ var Xslt = /** @class */ (function () {
603
547
  return [3 /*break*/, 6];
604
548
  }
605
549
  if (!this.isXsltElement(childNode, 'when')) return [3 /*break*/, 4];
606
- test_2 = (0, dom_1.xmlGetAttribute)(childNode, 'test');
607
- if (!this.xPath.xPathEval(test_2, context).booleanValue()) return [3 /*break*/, 3];
550
+ test_1 = (0, dom_1.xmlGetAttribute)(childNode, 'test');
551
+ if (!this.xPath.xPathEval(test_1, context).booleanValue()) return [3 /*break*/, 3];
608
552
  return [4 /*yield*/, this.xsltChildNodes(context, childNode, output)];
609
553
  case 2:
610
554
  _b.sent();
@@ -657,6 +601,31 @@ var Xslt = /** @class */ (function () {
657
601
  }
658
602
  return null;
659
603
  };
604
+ /**
605
+ * Implements `xsl:comment`.
606
+ * @param context The Expression Context.
607
+ * @param template The template.
608
+ * @param output The output. Only used if there's no corresponding output node already defined.
609
+ */
610
+ Xslt.prototype.xsltComment = function (context, template, output) {
611
+ return __awaiter(this, void 0, void 0, function () {
612
+ var node, commentData, commentNode, resolvedOutput;
613
+ return __generator(this, function (_a) {
614
+ switch (_a.label) {
615
+ case 0:
616
+ node = (0, dom_1.domCreateDocumentFragment)(this.outputDocument);
617
+ return [4 /*yield*/, this.xsltChildNodes(context, template, node)];
618
+ case 1:
619
+ _a.sent();
620
+ commentData = (0, dom_1.xmlValue)(node);
621
+ commentNode = (0, dom_1.domCreateComment)(this.outputDocument, commentData);
622
+ resolvedOutput = output || context.outputNodeList[context.outputPosition];
623
+ resolvedOutput.appendChild(commentNode);
624
+ return [2 /*return*/];
625
+ }
626
+ });
627
+ });
628
+ };
660
629
  /**
661
630
  * Implements `xsl:copy-of` for node-set values of the select
662
631
  * expression. Recurses down the source node tree, which is part of
@@ -679,6 +648,66 @@ var Xslt = /** @class */ (function () {
679
648
  }
680
649
  }
681
650
  };
651
+ /**
652
+ * Implements `xsl:decimal-format`, registering the settings in this instance
653
+ * and the current context.
654
+ * @param context The Expression Context.
655
+ * @param template The template.
656
+ */
657
+ Xslt.prototype.xsltDecimalFormat = function (context, template) {
658
+ var name = (0, dom_1.xmlGetAttribute)(template, 'name');
659
+ var decimalSeparator = (0, dom_1.xmlGetAttribute)(template, 'decimal-separator');
660
+ var groupingSeparator = (0, dom_1.xmlGetAttribute)(template, 'grouping-separator');
661
+ var infinity = (0, dom_1.xmlGetAttribute)(template, 'infinity');
662
+ var minusSign = (0, dom_1.xmlGetAttribute)(template, 'minus-sign');
663
+ var naN = (0, dom_1.xmlGetAttribute)(template, 'NaN');
664
+ var percent = (0, dom_1.xmlGetAttribute)(template, 'percent');
665
+ var perMille = (0, dom_1.xmlGetAttribute)(template, 'per-mille');
666
+ var zeroDigit = (0, dom_1.xmlGetAttribute)(template, 'zero-digit');
667
+ var digit = (0, dom_1.xmlGetAttribute)(template, 'digit');
668
+ var patternSeparator = (0, dom_1.xmlGetAttribute)(template, 'pattern-separator');
669
+ this.decimalFormatSettings = {
670
+ name: name || this.decimalFormatSettings.name,
671
+ decimalSeparator: decimalSeparator || this.decimalFormatSettings.decimalSeparator,
672
+ groupingSeparator: groupingSeparator || this.decimalFormatSettings.groupingSeparator,
673
+ infinity: infinity || this.decimalFormatSettings.infinity,
674
+ minusSign: minusSign || this.decimalFormatSettings.minusSign,
675
+ naN: naN || this.decimalFormatSettings.naN,
676
+ percent: percent || this.decimalFormatSettings.percent,
677
+ perMille: perMille || this.decimalFormatSettings.perMille,
678
+ zeroDigit: zeroDigit || this.decimalFormatSettings.zeroDigit,
679
+ digit: digit || this.decimalFormatSettings.digit,
680
+ patternSeparator: patternSeparator || this.decimalFormatSettings.patternSeparator
681
+ };
682
+ context.decimalFormatSettings = this.decimalFormatSettings;
683
+ };
684
+ /**
685
+ * Implements `xsl:element`.
686
+ * @param context The Expression Context.
687
+ * @param template The template.
688
+ */
689
+ Xslt.prototype.xsltElement = function (context, template) {
690
+ return __awaiter(this, void 0, void 0, function () {
691
+ var nameExpr, name, node, clonedContext;
692
+ return __generator(this, function (_a) {
693
+ switch (_a.label) {
694
+ case 0:
695
+ nameExpr = (0, dom_1.xmlGetAttribute)(template, 'name');
696
+ name = this.xsltAttributeValue(nameExpr, context);
697
+ node = (0, dom_1.domCreateElement)(this.outputDocument, name);
698
+ node.transformedNodeName = name;
699
+ (0, dom_1.domAppendTransformedChild)(context.outputNodeList[context.outputPosition], node);
700
+ // The element becomes the output node of the source node.
701
+ context.nodeList[context.position].outputNode = node;
702
+ clonedContext = context.clone(undefined, [node], undefined, 0);
703
+ return [4 /*yield*/, this.xsltChildNodes(clonedContext, template)];
704
+ case 1:
705
+ _a.sent();
706
+ return [2 /*return*/];
707
+ }
708
+ });
709
+ });
710
+ };
682
711
  /**
683
712
  * Implements `xsl:for-each`.
684
713
  * @param context The Expression Context.
@@ -718,6 +747,74 @@ var Xslt = /** @class */ (function () {
718
747
  });
719
748
  });
720
749
  };
750
+ /**
751
+ * Implements `xsl:if`.
752
+ * @param context The Expression Context.
753
+ * @param template The template.
754
+ * @param output The output.
755
+ */
756
+ Xslt.prototype.xsltIf = function (context, template, output) {
757
+ return __awaiter(this, void 0, void 0, function () {
758
+ var test;
759
+ return __generator(this, function (_a) {
760
+ switch (_a.label) {
761
+ case 0:
762
+ test = (0, dom_1.xmlGetAttribute)(template, 'test');
763
+ if (!this.xPath.xPathEval(test, context).booleanValue()) return [3 /*break*/, 2];
764
+ return [4 /*yield*/, this.xsltChildNodes(context, template, output)];
765
+ case 1:
766
+ _a.sent();
767
+ _a.label = 2;
768
+ case 2: return [2 /*return*/];
769
+ }
770
+ });
771
+ });
772
+ };
773
+ /**
774
+ * Implements `<xsl:import>`. For now the code is nearly identical to `<xsl:include>`, but there's
775
+ * no precedence evaluation implemented yet.
776
+ * @param context The Expression Context.
777
+ * @param template The template.
778
+ * @param output The output.
779
+ */
780
+ Xslt.prototype.xsltImport = function (context, template, output) {
781
+ return __awaiter(this, void 0, void 0, function () {
782
+ var hrefAttributeFind, hrefAttribute, fetchTest, fetchResponse, includedXslt;
783
+ return __generator(this, function (_a) {
784
+ switch (_a.label) {
785
+ case 0:
786
+ if (this.firstTemplateRan) {
787
+ throw new Error('<xsl:import> should be the first child node of <xsl:stylesheet> or <xsl:transform>.');
788
+ }
789
+ // We need to test here whether `window.fetch` is available or not.
790
+ // If it is a browser environemnt, it should be.
791
+ // Otherwise, we will need to import an equivalent library, like 'node-fetch'.
792
+ if (!global.globalThis.fetch) {
793
+ global.globalThis.fetch = node_fetch_1.default;
794
+ global.globalThis.Headers = node_fetch_1.Headers;
795
+ global.globalThis.Request = node_fetch_1.Request;
796
+ global.globalThis.Response = node_fetch_1.Response;
797
+ }
798
+ hrefAttributeFind = template.childNodes.filter(function (n) { return n.nodeName === 'href'; });
799
+ if (hrefAttributeFind.length <= 0) {
800
+ throw new Error('<xsl:import> with no href attribute defined.');
801
+ }
802
+ hrefAttribute = hrefAttributeFind[0];
803
+ return [4 /*yield*/, global.globalThis.fetch(hrefAttribute.nodeValue)];
804
+ case 1:
805
+ fetchTest = _a.sent();
806
+ return [4 /*yield*/, fetchTest.text()];
807
+ case 2:
808
+ fetchResponse = _a.sent();
809
+ includedXslt = this.xmlParser.xmlParse(fetchResponse);
810
+ return [4 /*yield*/, this.xsltChildNodes(context, includedXslt.childNodes[0], output)];
811
+ case 3:
812
+ _a.sent();
813
+ return [2 /*return*/];
814
+ }
815
+ });
816
+ });
817
+ };
721
818
  /**
722
819
  * Implements `xsl:include`.
723
820
  * @param context The Expression Context.
@@ -759,6 +856,49 @@ var Xslt = /** @class */ (function () {
759
856
  });
760
857
  });
761
858
  };
859
+ /**
860
+ * Implements `xsl:key`.
861
+ * @param context The Expression Context.
862
+ * @param template The template.
863
+ */
864
+ Xslt.prototype.xsltKey = function (context, template) {
865
+ // `name`, `match`, and `use` are required.
866
+ var name = (0, dom_1.xmlGetAttribute)(template, 'name');
867
+ var match = (0, dom_1.xmlGetAttribute)(template, 'match');
868
+ var use = (0, dom_1.xmlGetAttribute)(template, 'use');
869
+ if (!name || !match || !use) {
870
+ var errorMessage = '<xsl:key> missing required parameters: ';
871
+ if (!name) {
872
+ errorMessage += 'name, ';
873
+ }
874
+ if (!match) {
875
+ errorMessage += 'match, ';
876
+ }
877
+ if (!use) {
878
+ errorMessage += 'use, ';
879
+ }
880
+ errorMessage = errorMessage.slice(0, -2);
881
+ throw new Error(errorMessage);
882
+ }
883
+ var keyContext;
884
+ if (context.nodeList[context.position].nodeName === '#document') {
885
+ keyContext = context.clone(context.nodeList[context.position].childNodes);
886
+ }
887
+ else {
888
+ keyContext = context;
889
+ }
890
+ var nodes = this.xsltMatch(match, keyContext);
891
+ if (!(name in context.keys)) {
892
+ context.keys[name] = {};
893
+ }
894
+ for (var _i = 0, nodes_1 = nodes; _i < nodes_1.length; _i++) {
895
+ var node = nodes_1[_i];
896
+ var nodeContext = context.clone([node]);
897
+ var attribute = this.xPath.xPathEval(use, nodeContext);
898
+ var attributeValue = attribute.stringValue();
899
+ context.keys[name][attributeValue] = new values_1.NodeSetValue([node]);
900
+ }
901
+ };
762
902
  /**
763
903
  * Orders the current node list in the input context according to the
764
904
  * sort order specified by xsl:sort child nodes of the current
@@ -786,14 +926,62 @@ var Xslt = /** @class */ (function () {
786
926
  }
787
927
  this.xPath.xPathSort(context, sort);
788
928
  };
929
+ /**
930
+ * Implements `xsl:template`.
931
+ * @param context The Expression Context.
932
+ * @param template The `<xsl:template>` node.
933
+ * @param output The output. In general, a fragment that will be used by
934
+ * the caller.
935
+ */
936
+ Xslt.prototype.xsltTemplate = function (context, template, output) {
937
+ return __awaiter(this, void 0, void 0, function () {
938
+ var match, nodes, templateContext;
939
+ return __generator(this, function (_a) {
940
+ switch (_a.label) {
941
+ case 0:
942
+ // If `<xsl:template>` is executed outside `<xsl:apply-templates>`,
943
+ // only one match is accepted per level (or per context here).
944
+ if (!context.inApplyTemplates && context.baseTemplateMatched) {
945
+ return [2 /*return*/];
946
+ }
947
+ match = (0, dom_1.xmlGetAttribute)(template, 'match');
948
+ if (!match)
949
+ return [2 /*return*/];
950
+ nodes = this.xsltMatch(match, context, 'self-and-siblings');
951
+ if (!(nodes.length > 0)) return [3 /*break*/, 2];
952
+ this.firstTemplateRan = true;
953
+ if (!context.inApplyTemplates) {
954
+ context.baseTemplateMatched = true;
955
+ }
956
+ templateContext = context.clone(nodes, undefined, 0);
957
+ return [4 /*yield*/, this.xsltChildNodes(templateContext, template, output)];
958
+ case 1:
959
+ _a.sent();
960
+ _a.label = 2;
961
+ case 2: return [2 /*return*/];
962
+ }
963
+ });
964
+ });
965
+ };
966
+ Xslt.prototype.xsltText = function (context, template, output) {
967
+ var text = (0, dom_1.xmlValue)(template);
968
+ var node = (0, dom_1.domCreateTransformedTextNode)(this.outputDocument, text);
969
+ var disableOutputEscaping = template.childNodes.filter(function (a) { return a.nodeType === constants_1.DOM_ATTRIBUTE_NODE && a.nodeName === 'disable-output-escaping'; });
970
+ if (disableOutputEscaping.length > 0 && disableOutputEscaping[0].nodeValue === 'yes') {
971
+ node.escape = false;
972
+ }
973
+ var destinationTextNode = output || context.outputNodeList[context.outputPosition];
974
+ destinationTextNode.appendTransformedChild(node);
975
+ };
789
976
  /**
790
977
  * Implements `<xsl:stylesheet>` and `<xsl:transform>`, and its corresponding
791
978
  * validations.
792
- * @param template The `<xsl:stylesheet>` or `<xsl:transform>` node.
793
979
  * @param context The Expression Context.
794
- * @param output The output XML.
980
+ * @param template The `<xsl:stylesheet>` or `<xsl:transform>` node.
981
+ * @param output The output. In general, a fragment that will be used by
982
+ * the caller.
795
983
  */
796
- Xslt.prototype.xsltTransformOrStylesheet = function (template, context, output) {
984
+ Xslt.prototype.xsltTransformOrStylesheet = function (context, template, output) {
797
985
  return __awaiter(this, void 0, void 0, function () {
798
986
  var _i, _a, stylesheetAttribute;
799
987
  return __generator(this, function (_b) {
@@ -824,6 +1012,19 @@ var Xslt = /** @class */ (function () {
824
1012
  });
825
1013
  });
826
1014
  };
1015
+ Xslt.prototype.xsltValueOf = function (context, template, output) {
1016
+ var select = (0, dom_1.xmlGetAttribute)(template, 'select');
1017
+ var attribute = this.xPath.xPathEval(select, context);
1018
+ var value = attribute.stringValue();
1019
+ var node = (0, dom_1.domCreateTransformedTextNode)(this.outputDocument, value);
1020
+ node.siblingPosition = context.nodeList[context.position].siblingPosition;
1021
+ if (output && output.nodeType === constants_1.DOM_DOCUMENT_FRAGMENT_NODE) {
1022
+ output.appendTransformedChild(node);
1023
+ }
1024
+ else {
1025
+ context.outputNodeList[context.outputPosition].appendTransformedChild(node);
1026
+ }
1027
+ };
827
1028
  /**
828
1029
  * Evaluates a variable or parameter and set it in the current input
829
1030
  * context. Implements `xsl:variable`, `xsl:param`, and `xsl:with-param`.
@@ -908,6 +1109,8 @@ var Xslt = /** @class */ (function () {
908
1109
  * This logic is used in two different places:
909
1110
  * - `xsltPassThrough`, if the template asks this library to write a text node;
910
1111
  * - `xsltProcessContext`, `apply-templates` operation, when the current node is text.
1112
+ *
1113
+ * Text nodes always require a parent, and they never have children.
911
1114
  * @param context The Expression Context.
912
1115
  * @param template The template, that contains the node value to be written.
913
1116
  * @param output The output.
@@ -918,15 +1121,17 @@ var Xslt = /** @class */ (function () {
918
1121
  (0, dom_1.domAppendTransformedChild)(output, node);
919
1122
  }
920
1123
  else {
921
- var textNodeList = context.outputNodeList[context.outputPosition].transformedChildNodes.filter(function (n) { return n.nodeType === constants_1.DOM_TEXT_NODE; });
1124
+ var parentNode = context.outputNodeList[context.outputPosition];
1125
+ var textNodeList = parentNode.transformedChildNodes.filter(function (n) { return n.nodeType === constants_1.DOM_TEXT_NODE; });
922
1126
  if (textNodeList.length > 0) {
923
1127
  var node = textNodeList[0];
924
1128
  node.transformedNodeValue = template.nodeValue;
925
1129
  }
926
1130
  else {
927
1131
  var node = (0, dom_1.domCreateTransformedTextNode)(this.outputDocument, template.nodeValue);
928
- node.transformedParentNode = context.outputNodeList[context.outputPosition];
929
- (0, dom_1.domAppendTransformedChild)(context.outputNodeList[context.outputPosition], node);
1132
+ node.transformedParentNode = parentNode;
1133
+ // context.nodeList[context.position].outputNode = node;
1134
+ (0, dom_1.domAppendTransformedChild)(parentNode, node);
930
1135
  }
931
1136
  }
932
1137
  };
@@ -941,7 +1146,7 @@ var Xslt = /** @class */ (function () {
941
1146
  */
942
1147
  Xslt.prototype.xsltPassThrough = function (context, template, output) {
943
1148
  return __awaiter(this, void 0, void 0, function () {
944
- var node, elementContext, newNode, transformedChildNodes, _i, transformedChildNodes_1, previouslyTransformedAttribute, name_2, value, transformedAttributes, _a, transformedAttributes_1, previouslyTransformedAttribute, name_3, value, templateAttributes, _b, templateAttributes_1, attribute, name_4, value, outputNode, clonedContext;
1149
+ var node, elementContext, newNode, outputNode, clonedContext, transformedChildNodes, _i, transformedChildNodes_1, previouslyTransformedAttribute, name_1, value, transformedAttributes, _a, transformedAttributes_1, previouslyTransformedAttribute, name_2, value, templateAttributes, _b, templateAttributes_1, attribute, name_3, value;
945
1150
  return __generator(this, function (_c) {
946
1151
  switch (_c.label) {
947
1152
  case 0:
@@ -974,33 +1179,33 @@ var Xslt = /** @class */ (function () {
974
1179
  }
975
1180
  newNode.transformedNodeName = template.nodeName;
976
1181
  newNode.transformedLocalName = template.localName;
1182
+ outputNode = context.outputNodeList[context.outputPosition];
1183
+ (0, dom_1.domAppendTransformedChild)(outputNode, newNode);
1184
+ clonedContext = elementContext.cloneByOutput(outputNode.transformedChildNodes, outputNode.transformedChildNodes.length - 1, ++elementContext.outputDepth);
1185
+ return [4 /*yield*/, this.xsltChildNodes(clonedContext, template)];
1186
+ case 2:
1187
+ _c.sent();
977
1188
  transformedChildNodes = node.transformedChildNodes.filter(function (n) { return n.nodeType === constants_1.DOM_ATTRIBUTE_NODE; });
978
1189
  for (_i = 0, transformedChildNodes_1 = transformedChildNodes; _i < transformedChildNodes_1.length; _i++) {
979
1190
  previouslyTransformedAttribute = transformedChildNodes_1[_i];
980
- name_2 = previouslyTransformedAttribute.transformedNodeName;
1191
+ name_1 = previouslyTransformedAttribute.transformedNodeName;
981
1192
  value = previouslyTransformedAttribute.transformedNodeValue;
982
- (0, dom_1.domSetTransformedAttribute)(newNode, name_2, value);
1193
+ (0, dom_1.domSetTransformedAttribute)(newNode, name_1, value);
983
1194
  }
984
1195
  transformedAttributes = node.childNodes.filter(function (n) { return n.nodeType === constants_1.DOM_ATTRIBUTE_NODE && n.transformedNodeName; });
985
1196
  for (_a = 0, transformedAttributes_1 = transformedAttributes; _a < transformedAttributes_1.length; _a++) {
986
1197
  previouslyTransformedAttribute = transformedAttributes_1[_a];
987
- name_3 = previouslyTransformedAttribute.transformedNodeName;
1198
+ name_2 = previouslyTransformedAttribute.transformedNodeName;
988
1199
  value = previouslyTransformedAttribute.transformedNodeValue;
989
- (0, dom_1.domSetTransformedAttribute)(newNode, name_3, value);
1200
+ (0, dom_1.domSetTransformedAttribute)(newNode, name_2, value);
990
1201
  }
991
1202
  templateAttributes = template.childNodes.filter(function (a) { return (a === null || a === void 0 ? void 0 : a.nodeType) === constants_1.DOM_ATTRIBUTE_NODE; });
992
1203
  for (_b = 0, templateAttributes_1 = templateAttributes; _b < templateAttributes_1.length; _b++) {
993
1204
  attribute = templateAttributes_1[_b];
994
- name_4 = attribute.nodeName;
1205
+ name_3 = attribute.nodeName;
995
1206
  value = this.xsltAttributeValue(attribute.nodeValue, elementContext);
996
- (0, dom_1.domSetTransformedAttribute)(newNode, name_4, value);
1207
+ (0, dom_1.domSetTransformedAttribute)(newNode, name_3, value);
997
1208
  }
998
- outputNode = context.outputNodeList[context.outputPosition];
999
- (0, dom_1.domAppendTransformedChild)(outputNode, newNode);
1000
- clonedContext = elementContext.cloneByOutput(outputNode.transformedChildNodes, outputNode.transformedChildNodes.length - 1, ++elementContext.outputDepth);
1001
- return [4 /*yield*/, this.xsltChildNodes(clonedContext, template)];
1002
- case 2:
1003
- _c.sent();
1004
1209
  return [3 /*break*/, 5];
1005
1210
  case 3:
1006
1211
  // This applies also to the DOCUMENT_NODE of the XSL stylesheet,