xslt-processor 4.7.0 → 4.8.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/index.d.mts CHANGED
@@ -278,6 +278,14 @@ declare class ExprContext {
278
278
  * Contains the key value of the current group being processed.
279
279
  */
280
280
  currentGroupingKey?: any;
281
+ /**
282
+ * User-defined XSLT functions from xsl:function declarations.
283
+ * Maps QName (namespace:localname) to function definition info.
284
+ */
285
+ userDefinedFunctions?: Map<string, {
286
+ functionDef: XNode;
287
+ executor: (context: ExprContext, functionDef: XNode, args: any[]) => any;
288
+ }>;
281
289
  /**
282
290
  * Constructor -- gets the node, its position, the node set it
283
291
  * belongs to, and a parent context as arguments. The parent context
@@ -790,6 +798,16 @@ declare class Xslt {
790
798
  * Keys are attribute set names, values are arrays of xsl:attribute nodes.
791
799
  */
792
800
  attributeSets: Map<string, XNode[]>;
801
+ /**
802
+ * Map of user-defined functions from xsl:function declarations.
803
+ * Keys are QNames (namespace:localname), values are the function definition nodes.
804
+ */
805
+ userDefinedFunctions: Map<string, XNode>;
806
+ /**
807
+ * Result documents created by xsl:result-document.
808
+ * Keys are the href URIs, values are the serialized output strings.
809
+ */
810
+ resultDocuments: Map<string, string>;
793
811
  /**
794
812
  * Stack of stylesheet metadata for tracking import hierarchy.
795
813
  * Used by apply-imports to find templates from imported stylesheets.
@@ -1343,6 +1361,74 @@ declare class Xslt {
1343
1361
  * Sets up the context with the current text and regex groups.
1344
1362
  */
1345
1363
  private processAnalyzeStringContent;
1364
+ /**
1365
+ * Implements `xsl:function` (XSLT 2.0).
1366
+ *
1367
+ * Declares a stylesheet function that can be called from XPath expressions.
1368
+ * Functions are collected during stylesheet initialization and made available
1369
+ * to the XPath evaluator.
1370
+ *
1371
+ * @param context The expression context.
1372
+ * @param template The xsl:function element.
1373
+ */
1374
+ protected xsltFunction(context: ExprContext, template: XNode): void;
1375
+ /**
1376
+ * Execute a user-defined xsl:function.
1377
+ * Called when a function from userDefinedFunctions is invoked from XPath.
1378
+ *
1379
+ * @param context The expression context.
1380
+ * @param functionDef The xsl:function node.
1381
+ * @param args The evaluated arguments passed to the function.
1382
+ * @returns The result of the function execution.
1383
+ */
1384
+ protected executeUserDefinedFunction(context: ExprContext, functionDef: XNode, args: any[]): Promise<any>;
1385
+ /**
1386
+ * Synchronously execute a user-defined xsl:function.
1387
+ * This is used when functions are called from XPath expressions.
1388
+ * Limited to functions that don't require async operations in their body.
1389
+ *
1390
+ * @param context The expression context.
1391
+ * @param functionDef The xsl:function node.
1392
+ * @param args The evaluated arguments passed to the function.
1393
+ * @returns The result of the function execution.
1394
+ */
1395
+ executeUserDefinedFunctionSync(context: ExprContext, functionDef: XNode, args: any[]): any;
1396
+ /**
1397
+ * Implements `xsl:result-document` (XSLT 2.0).
1398
+ *
1399
+ * Creates a secondary output document. The output is stored in the
1400
+ * resultDocuments map, accessible via getResultDocuments().
1401
+ *
1402
+ * @param context The expression context.
1403
+ * @param template The xsl:result-document element.
1404
+ */
1405
+ protected xsltResultDocument(context: ExprContext, template: XNode): Promise<void>;
1406
+ /**
1407
+ * Get all result documents created by xsl:result-document.
1408
+ * @returns A map of href URIs to serialized output strings.
1409
+ */
1410
+ getResultDocuments(): Map<string, string>;
1411
+ /**
1412
+ * Implements `xsl:perform-sort` (XSLT 2.0).
1413
+ *
1414
+ * Sorts a sequence of items without iteration. The sorted sequence
1415
+ * is available via xsl:sequence or other sequence-consuming instructions.
1416
+ *
1417
+ * @param context The expression context.
1418
+ * @param template The xsl:perform-sort element.
1419
+ * @param output The output node.
1420
+ */
1421
+ protected xsltPerformSort(context: ExprContext, template: XNode, output?: XNode): Promise<void>;
1422
+ /**
1423
+ * Implements `xsl:namespace` (XSLT 2.0).
1424
+ *
1425
+ * Creates a namespace node in the result tree.
1426
+ *
1427
+ * @param context The expression context.
1428
+ * @param template The xsl:namespace element.
1429
+ * @param output The output node.
1430
+ */
1431
+ protected xsltNamespace(context: ExprContext, template: XNode, output?: XNode): Promise<void>;
1346
1432
  /**
1347
1433
  * Evaluates a variable or parameter and set it in the current input
1348
1434
  * context. Implements `xsl:variable`, `xsl:param`, and `xsl:with-param`.
@@ -1454,6 +1540,19 @@ declare class Xslt {
1454
1540
  * @param stylesheetElement The stylesheet or transform element.
1455
1541
  */
1456
1542
  private collectAttributeSets;
1543
+ /**
1544
+ * Collect all user-defined function definitions from the stylesheet.
1545
+ * Called at stylesheet initialization time.
1546
+ * @param stylesheetElement The stylesheet or transform element.
1547
+ * @param context The expression context.
1548
+ */
1549
+ private collectUserDefinedFunctions;
1550
+ /**
1551
+ * Register user-defined functions in the expression context.
1552
+ * This makes them available to XPath expressions.
1553
+ * @param context The expression context.
1554
+ */
1555
+ private registerUserDefinedFunctionsInContext;
1457
1556
  /**
1458
1557
  * Apply one or more attribute sets to an element.
1459
1558
  * Parses space-separated attribute set names and applies them.
package/index.d.ts CHANGED
@@ -278,6 +278,14 @@ declare class ExprContext {
278
278
  * Contains the key value of the current group being processed.
279
279
  */
280
280
  currentGroupingKey?: any;
281
+ /**
282
+ * User-defined XSLT functions from xsl:function declarations.
283
+ * Maps QName (namespace:localname) to function definition info.
284
+ */
285
+ userDefinedFunctions?: Map<string, {
286
+ functionDef: XNode;
287
+ executor: (context: ExprContext, functionDef: XNode, args: any[]) => any;
288
+ }>;
281
289
  /**
282
290
  * Constructor -- gets the node, its position, the node set it
283
291
  * belongs to, and a parent context as arguments. The parent context
@@ -790,6 +798,16 @@ declare class Xslt {
790
798
  * Keys are attribute set names, values are arrays of xsl:attribute nodes.
791
799
  */
792
800
  attributeSets: Map<string, XNode[]>;
801
+ /**
802
+ * Map of user-defined functions from xsl:function declarations.
803
+ * Keys are QNames (namespace:localname), values are the function definition nodes.
804
+ */
805
+ userDefinedFunctions: Map<string, XNode>;
806
+ /**
807
+ * Result documents created by xsl:result-document.
808
+ * Keys are the href URIs, values are the serialized output strings.
809
+ */
810
+ resultDocuments: Map<string, string>;
793
811
  /**
794
812
  * Stack of stylesheet metadata for tracking import hierarchy.
795
813
  * Used by apply-imports to find templates from imported stylesheets.
@@ -1343,6 +1361,74 @@ declare class Xslt {
1343
1361
  * Sets up the context with the current text and regex groups.
1344
1362
  */
1345
1363
  private processAnalyzeStringContent;
1364
+ /**
1365
+ * Implements `xsl:function` (XSLT 2.0).
1366
+ *
1367
+ * Declares a stylesheet function that can be called from XPath expressions.
1368
+ * Functions are collected during stylesheet initialization and made available
1369
+ * to the XPath evaluator.
1370
+ *
1371
+ * @param context The expression context.
1372
+ * @param template The xsl:function element.
1373
+ */
1374
+ protected xsltFunction(context: ExprContext, template: XNode): void;
1375
+ /**
1376
+ * Execute a user-defined xsl:function.
1377
+ * Called when a function from userDefinedFunctions is invoked from XPath.
1378
+ *
1379
+ * @param context The expression context.
1380
+ * @param functionDef The xsl:function node.
1381
+ * @param args The evaluated arguments passed to the function.
1382
+ * @returns The result of the function execution.
1383
+ */
1384
+ protected executeUserDefinedFunction(context: ExprContext, functionDef: XNode, args: any[]): Promise<any>;
1385
+ /**
1386
+ * Synchronously execute a user-defined xsl:function.
1387
+ * This is used when functions are called from XPath expressions.
1388
+ * Limited to functions that don't require async operations in their body.
1389
+ *
1390
+ * @param context The expression context.
1391
+ * @param functionDef The xsl:function node.
1392
+ * @param args The evaluated arguments passed to the function.
1393
+ * @returns The result of the function execution.
1394
+ */
1395
+ executeUserDefinedFunctionSync(context: ExprContext, functionDef: XNode, args: any[]): any;
1396
+ /**
1397
+ * Implements `xsl:result-document` (XSLT 2.0).
1398
+ *
1399
+ * Creates a secondary output document. The output is stored in the
1400
+ * resultDocuments map, accessible via getResultDocuments().
1401
+ *
1402
+ * @param context The expression context.
1403
+ * @param template The xsl:result-document element.
1404
+ */
1405
+ protected xsltResultDocument(context: ExprContext, template: XNode): Promise<void>;
1406
+ /**
1407
+ * Get all result documents created by xsl:result-document.
1408
+ * @returns A map of href URIs to serialized output strings.
1409
+ */
1410
+ getResultDocuments(): Map<string, string>;
1411
+ /**
1412
+ * Implements `xsl:perform-sort` (XSLT 2.0).
1413
+ *
1414
+ * Sorts a sequence of items without iteration. The sorted sequence
1415
+ * is available via xsl:sequence or other sequence-consuming instructions.
1416
+ *
1417
+ * @param context The expression context.
1418
+ * @param template The xsl:perform-sort element.
1419
+ * @param output The output node.
1420
+ */
1421
+ protected xsltPerformSort(context: ExprContext, template: XNode, output?: XNode): Promise<void>;
1422
+ /**
1423
+ * Implements `xsl:namespace` (XSLT 2.0).
1424
+ *
1425
+ * Creates a namespace node in the result tree.
1426
+ *
1427
+ * @param context The expression context.
1428
+ * @param template The xsl:namespace element.
1429
+ * @param output The output node.
1430
+ */
1431
+ protected xsltNamespace(context: ExprContext, template: XNode, output?: XNode): Promise<void>;
1346
1432
  /**
1347
1433
  * Evaluates a variable or parameter and set it in the current input
1348
1434
  * context. Implements `xsl:variable`, `xsl:param`, and `xsl:with-param`.
@@ -1454,6 +1540,19 @@ declare class Xslt {
1454
1540
  * @param stylesheetElement The stylesheet or transform element.
1455
1541
  */
1456
1542
  private collectAttributeSets;
1543
+ /**
1544
+ * Collect all user-defined function definitions from the stylesheet.
1545
+ * Called at stylesheet initialization time.
1546
+ * @param stylesheetElement The stylesheet or transform element.
1547
+ * @param context The expression context.
1548
+ */
1549
+ private collectUserDefinedFunctions;
1550
+ /**
1551
+ * Register user-defined functions in the expression context.
1552
+ * This makes them available to XPath expressions.
1553
+ * @param context The expression context.
1554
+ */
1555
+ private registerUserDefinedFunctionsInContext;
1457
1556
  /**
1458
1557
  * Apply one or more attribute sets to an element.
1459
1558
  * Parses space-separated attribute set names and applies them.
package/index.js CHANGED
@@ -6402,10 +6402,13 @@ var init_function_call_expression = __esm({
6402
6402
  if (!this.name.includes(":")) {
6403
6403
  return void 0;
6404
6404
  }
6405
- const [, localName] = this.name.split(":");
6405
+ const [prefix, localName] = this.name.split(":");
6406
6406
  if (!localName) {
6407
6407
  return void 0;
6408
6408
  }
6409
+ if (prefix !== "xs") {
6410
+ return void 0;
6411
+ }
6409
6412
  return getAtomicType(localName);
6410
6413
  }
6411
6414
  castConstructorValue(constructorType, value) {
@@ -9211,9 +9214,18 @@ var XPath20Parser = class extends XPathBaseParser {
9211
9214
  return left;
9212
9215
  }
9213
9216
  parsePrimaryExpr() {
9217
+ var _a, _b;
9214
9218
  if (this.check("RESERVED_WORD") && this.peek().lexeme === "if") {
9215
9219
  return this.parseIfExpr();
9216
9220
  }
9221
+ if (this.check("DOLLAR")) {
9222
+ this.advance();
9223
+ if (!this.isNameToken()) {
9224
+ throw new Error(`Expected variable name after $. Got: ${(_b = (_a = this.peek()) == null ? void 0 : _a.lexeme) != null ? _b : "EOF"}`);
9225
+ }
9226
+ const name = this.advance().lexeme;
9227
+ return new XPathVariableReference(name);
9228
+ }
9217
9229
  return super.parsePrimaryExpr();
9218
9230
  }
9219
9231
  parseInstanceOfExpr() {
@@ -11935,6 +11947,20 @@ var NodeConverter = class {
11935
11947
  }
11936
11948
  return "";
11937
11949
  };
11950
+ let ctx = exprContext;
11951
+ while (ctx) {
11952
+ if (ctx.userDefinedFunctions) {
11953
+ ctx.userDefinedFunctions.forEach((funcInfo, funcName) => {
11954
+ if (!functions[funcName]) {
11955
+ functions[funcName] = (_context, ...args) => {
11956
+ return funcInfo.executor(exprContext, funcInfo.functionDef, args);
11957
+ };
11958
+ }
11959
+ });
11960
+ break;
11961
+ }
11962
+ ctx = ctx.parent;
11963
+ }
11938
11964
  return functions;
11939
11965
  }
11940
11966
  /**
@@ -13702,6 +13728,8 @@ var Xslt = class {
13702
13728
  this.namespaceAliases = /* @__PURE__ */ new Map();
13703
13729
  this.supportedExtensions = /* @__PURE__ */ new Set(["http://www.w3.org/1999/XSL/Transform"]);
13704
13730
  this.attributeSets = /* @__PURE__ */ new Map();
13731
+ this.userDefinedFunctions = /* @__PURE__ */ new Map();
13732
+ this.resultDocuments = /* @__PURE__ */ new Map();
13705
13733
  this.decimalFormatSettings = {
13706
13734
  decimalSeparator: ".",
13707
13735
  groupingSeparator: ",",
@@ -13856,6 +13884,9 @@ var Xslt = class {
13856
13884
  case "for-each-group":
13857
13885
  yield this.xsltForEachGroup(context, template, output);
13858
13886
  break;
13887
+ case "function":
13888
+ this.xsltFunction(context, template);
13889
+ break;
13859
13890
  case "iterate":
13860
13891
  yield this.xsltIterate(context, template, output);
13861
13892
  break;
@@ -13879,6 +13910,9 @@ var Xslt = class {
13879
13910
  case "message":
13880
13911
  yield this.xsltMessage(context, template);
13881
13912
  break;
13913
+ case "namespace":
13914
+ yield this.xsltNamespace(context, template, output);
13915
+ break;
13882
13916
  case "namespace-alias":
13883
13917
  this.xsltNamespaceAlias(template);
13884
13918
  break;
@@ -13917,9 +13951,15 @@ var Xslt = class {
13917
13951
  case "preserve-space":
13918
13952
  this.xsltPreserveSpace(template);
13919
13953
  break;
13954
+ case "perform-sort":
13955
+ yield this.xsltPerformSort(context, template, output);
13956
+ break;
13920
13957
  case "processing-instruction":
13921
13958
  yield this.xsltProcessingInstruction(context, template, output);
13922
13959
  break;
13960
+ case "result-document":
13961
+ yield this.xsltResultDocument(context, template);
13962
+ break;
13923
13963
  case "sequence":
13924
13964
  yield this.xsltSequence(context, template, output);
13925
13965
  break;
@@ -15993,6 +16033,8 @@ var Xslt = class {
15993
16033
  };
15994
16034
  this.mapTemplatesFromStylesheet(template, mainStylesheetMetadata);
15995
16035
  this.collectAttributeSets(template);
16036
+ this.collectUserDefinedFunctions(template, context);
16037
+ this.registerUserDefinedFunctionsInContext(context);
15996
16038
  this.validateStylesheetAttributes(template, context);
15997
16039
  let importsDone = false;
15998
16040
  for (const child of template.childNodes) {
@@ -16296,6 +16338,237 @@ var Xslt = class {
16296
16338
  yield this.xsltChildNodes(childContext, template, output);
16297
16339
  });
16298
16340
  }
16341
+ /**
16342
+ * Implements `xsl:function` (XSLT 2.0).
16343
+ *
16344
+ * Declares a stylesheet function that can be called from XPath expressions.
16345
+ * Functions are collected during stylesheet initialization and made available
16346
+ * to the XPath evaluator.
16347
+ *
16348
+ * @param context The expression context.
16349
+ * @param template The xsl:function element.
16350
+ */
16351
+ xsltFunction(context, template) {
16352
+ const name = xmlGetAttribute(template, "name");
16353
+ const asAttr = xmlGetAttribute(template, "as");
16354
+ const overrideAttr = xmlGetAttribute(template, "override");
16355
+ if (!name) {
16356
+ throw new Error('<xsl:function> requires a "name" attribute.');
16357
+ }
16358
+ if (!name.includes(":")) {
16359
+ throw new Error(`<xsl:function> name "${name}" must be in a namespace (use a prefixed name like "my:functionName").`);
16360
+ }
16361
+ const override = overrideAttr === "yes" || overrideAttr === "true";
16362
+ if (this.userDefinedFunctions.has(name) && !override) {
16363
+ return;
16364
+ }
16365
+ this.userDefinedFunctions.set(name, template);
16366
+ }
16367
+ /**
16368
+ * Execute a user-defined xsl:function.
16369
+ * Called when a function from userDefinedFunctions is invoked from XPath.
16370
+ *
16371
+ * @param context The expression context.
16372
+ * @param functionDef The xsl:function node.
16373
+ * @param args The evaluated arguments passed to the function.
16374
+ * @returns The result of the function execution.
16375
+ */
16376
+ executeUserDefinedFunction(context, functionDef, args) {
16377
+ return __async(this, null, function* () {
16378
+ return this.executeUserDefinedFunctionSync(context, functionDef, args);
16379
+ });
16380
+ }
16381
+ /**
16382
+ * Synchronously execute a user-defined xsl:function.
16383
+ * This is used when functions are called from XPath expressions.
16384
+ * Limited to functions that don't require async operations in their body.
16385
+ *
16386
+ * @param context The expression context.
16387
+ * @param functionDef The xsl:function node.
16388
+ * @param args The evaluated arguments passed to the function.
16389
+ * @returns The result of the function execution.
16390
+ */
16391
+ executeUserDefinedFunctionSync(context, functionDef, args) {
16392
+ const functionContext = context.clone();
16393
+ functionContext.variables = __spreadValues({}, context.variables);
16394
+ const params = [];
16395
+ for (const child of functionDef.childNodes) {
16396
+ if (child.nodeType === DOM_ELEMENT_NODE && this.isXsltElement(child, "param")) {
16397
+ params.push(child);
16398
+ }
16399
+ }
16400
+ for (let i = 0; i < params.length; i++) {
16401
+ const paramName = xmlGetAttribute(params[i], "name");
16402
+ if (paramName) {
16403
+ if (i < args.length) {
16404
+ const argValue = args[i];
16405
+ if (argValue && typeof argValue === "object" && "stringValue" in argValue) {
16406
+ functionContext.setVariable(paramName, argValue);
16407
+ } else if (Array.isArray(argValue)) {
16408
+ functionContext.setVariable(paramName, new NodeSetValue(argValue));
16409
+ } else if (typeof argValue === "number") {
16410
+ functionContext.setVariable(paramName, new NumberValue(argValue));
16411
+ } else if (typeof argValue === "boolean") {
16412
+ functionContext.setVariable(paramName, new BooleanValue(argValue));
16413
+ } else {
16414
+ functionContext.setVariable(paramName, new StringValue(String(argValue != null ? argValue : "")));
16415
+ }
16416
+ } else {
16417
+ const selectExpr = xmlGetAttribute(params[i], "select");
16418
+ if (selectExpr) {
16419
+ const defaultValue = this.xPath.xPathEval(selectExpr, functionContext);
16420
+ functionContext.setVariable(paramName, defaultValue);
16421
+ } else {
16422
+ functionContext.setVariable(paramName, new StringValue(""));
16423
+ }
16424
+ }
16425
+ }
16426
+ }
16427
+ for (const child of functionDef.childNodes) {
16428
+ if (child.nodeType === DOM_ELEMENT_NODE) {
16429
+ if (this.isXsltElement(child, "sequence")) {
16430
+ const select = xmlGetAttribute(child, "select");
16431
+ if (select) {
16432
+ const result = this.xPath.xPathEval(select, functionContext);
16433
+ if (result.type === "number") {
16434
+ return result.numberValue();
16435
+ } else if (result.type === "boolean") {
16436
+ return result.booleanValue();
16437
+ } else if (result.type === "node-set") {
16438
+ return result.nodeSetValue();
16439
+ } else {
16440
+ return result.stringValue();
16441
+ }
16442
+ }
16443
+ } else if (this.isXsltElement(child, "value-of")) {
16444
+ const select = xmlGetAttribute(child, "select");
16445
+ if (select) {
16446
+ return this.xPath.xPathEval(select, functionContext).stringValue();
16447
+ }
16448
+ }
16449
+ }
16450
+ }
16451
+ return "";
16452
+ }
16453
+ /**
16454
+ * Implements `xsl:result-document` (XSLT 2.0).
16455
+ *
16456
+ * Creates a secondary output document. The output is stored in the
16457
+ * resultDocuments map, accessible via getResultDocuments().
16458
+ *
16459
+ * @param context The expression context.
16460
+ * @param template The xsl:result-document element.
16461
+ */
16462
+ xsltResultDocument(context, template) {
16463
+ return __async(this, null, function* () {
16464
+ const hrefExpr = xmlGetAttribute(template, "href") || "";
16465
+ const methodAttr = xmlGetAttribute(template, "method") || this.outputMethod || "xml";
16466
+ const omitXmlDeclaration = xmlGetAttribute(template, "omit-xml-declaration") || this.outputOmitXmlDeclaration;
16467
+ const href = this.xsltAttributeValue(hrefExpr, context);
16468
+ if (!href) {
16469
+ throw new Error('<xsl:result-document> requires a non-empty "href" attribute.');
16470
+ }
16471
+ if (this.resultDocuments.has(href)) {
16472
+ throw new Error(`<xsl:result-document>: A document has already been created with href="${href}".`);
16473
+ }
16474
+ const resultDocument = new XDocument();
16475
+ yield this.xsltChildNodes(context, template, resultDocument);
16476
+ const serialized = xmlTransformedText(resultDocument, {
16477
+ cData: this.options.cData,
16478
+ escape: this.options.escape,
16479
+ selfClosingTags: this.options.selfClosingTags,
16480
+ outputMethod: methodAttr,
16481
+ outputVersion: this.outputVersion,
16482
+ itemSeparator: this.itemSeparator
16483
+ });
16484
+ this.resultDocuments.set(href, serialized);
16485
+ });
16486
+ }
16487
+ /**
16488
+ * Get all result documents created by xsl:result-document.
16489
+ * @returns A map of href URIs to serialized output strings.
16490
+ */
16491
+ getResultDocuments() {
16492
+ return this.resultDocuments;
16493
+ }
16494
+ /**
16495
+ * Implements `xsl:perform-sort` (XSLT 2.0).
16496
+ *
16497
+ * Sorts a sequence of items without iteration. The sorted sequence
16498
+ * is available via xsl:sequence or other sequence-consuming instructions.
16499
+ *
16500
+ * @param context The expression context.
16501
+ * @param template The xsl:perform-sort element.
16502
+ * @param output The output node.
16503
+ */
16504
+ xsltPerformSort(context, template, output) {
16505
+ return __async(this, null, function* () {
16506
+ const select = xmlGetAttribute(template, "select");
16507
+ let items;
16508
+ if (select) {
16509
+ items = this.xPath.xPathEval(select, context).nodeSetValue();
16510
+ } else {
16511
+ const sequenceChildren = [];
16512
+ for (const child of template.childNodes) {
16513
+ if (child.nodeType === DOM_ELEMENT_NODE && !this.isXsltElement(child, "sort")) {
16514
+ sequenceChildren.push(child);
16515
+ }
16516
+ }
16517
+ const fragment = domCreateDocumentFragment(this.outputDocument);
16518
+ for (const child of sequenceChildren) {
16519
+ yield this.xsltProcessContext(context, child, fragment);
16520
+ }
16521
+ items = Array.from(fragment.childNodes);
16522
+ }
16523
+ if (items.length === 0) {
16524
+ return;
16525
+ }
16526
+ const sortContext = context.clone(items);
16527
+ this.xsltSort(sortContext, template);
16528
+ const destinationNode = output || this.outputDocument;
16529
+ for (const node of sortContext.nodeList) {
16530
+ this.xsltCopyOf(destinationNode, node);
16531
+ }
16532
+ });
16533
+ }
16534
+ /**
16535
+ * Implements `xsl:namespace` (XSLT 2.0).
16536
+ *
16537
+ * Creates a namespace node in the result tree.
16538
+ *
16539
+ * @param context The expression context.
16540
+ * @param template The xsl:namespace element.
16541
+ * @param output The output node.
16542
+ */
16543
+ xsltNamespace(context, template, output) {
16544
+ return __async(this, null, function* () {
16545
+ const nameExpr = xmlGetAttribute(template, "name");
16546
+ const selectExpr = xmlGetAttribute(template, "select");
16547
+ if (!nameExpr && nameExpr !== "") {
16548
+ throw new Error('<xsl:namespace> requires a "name" attribute.');
16549
+ }
16550
+ const prefix = this.xsltAttributeValue(nameExpr, context);
16551
+ let namespaceUri;
16552
+ if (selectExpr) {
16553
+ namespaceUri = this.xPath.xPathEval(selectExpr, context).stringValue();
16554
+ } else {
16555
+ const fragment = domCreateDocumentFragment(this.outputDocument);
16556
+ yield this.xsltChildNodes(context, template, fragment);
16557
+ namespaceUri = xmlValue(fragment);
16558
+ }
16559
+ if (!namespaceUri) {
16560
+ throw new Error("<xsl:namespace> requires a non-empty namespace URI.");
16561
+ }
16562
+ const destinationNode = output || this.outputDocument;
16563
+ if (destinationNode.nodeType === DOM_ELEMENT_NODE) {
16564
+ if (prefix) {
16565
+ domSetAttribute(destinationNode, `xmlns:${prefix}`, namespaceUri);
16566
+ } else {
16567
+ domSetAttribute(destinationNode, "xmlns", namespaceUri);
16568
+ }
16569
+ }
16570
+ });
16571
+ }
16299
16572
  /**
16300
16573
  * Evaluates a variable or parameter and set it in the current input
16301
16574
  * context. Implements `xsl:variable`, `xsl:param`, and `xsl:with-param`.
@@ -16652,6 +16925,39 @@ var Xslt = class {
16652
16925
  }
16653
16926
  }
16654
16927
  }
16928
+ /**
16929
+ * Collect all user-defined function definitions from the stylesheet.
16930
+ * Called at stylesheet initialization time.
16931
+ * @param stylesheetElement The stylesheet or transform element.
16932
+ * @param context The expression context.
16933
+ */
16934
+ collectUserDefinedFunctions(stylesheetElement, context) {
16935
+ for (const child of stylesheetElement.childNodes) {
16936
+ if (child.nodeType === DOM_ELEMENT_NODE && this.isXsltElement(child, "function")) {
16937
+ this.xsltFunction(context, child);
16938
+ }
16939
+ }
16940
+ }
16941
+ /**
16942
+ * Register user-defined functions in the expression context.
16943
+ * This makes them available to XPath expressions.
16944
+ * @param context The expression context.
16945
+ */
16946
+ registerUserDefinedFunctionsInContext(context) {
16947
+ if (this.userDefinedFunctions.size === 0) {
16948
+ return;
16949
+ }
16950
+ const functionsMap = /* @__PURE__ */ new Map();
16951
+ this.userDefinedFunctions.forEach((functionDef, name) => {
16952
+ functionsMap.set(name, {
16953
+ functionDef,
16954
+ executor: (ctx, funcDef, args) => {
16955
+ return this.executeUserDefinedFunctionSync(ctx, funcDef, args);
16956
+ }
16957
+ });
16958
+ });
16959
+ context.userDefinedFunctions = functionsMap;
16960
+ }
16655
16961
  /**
16656
16962
  * Apply one or more attribute sets to an element.
16657
16963
  * Parses space-separated attribute set names and applies them.