xslt-processor 4.9.0 → 5.0.1

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/README.md CHANGED
@@ -63,6 +63,41 @@ xslt.xsltProcess(
63
63
 
64
64
  If you write pre-2015 JS code, make adjustments as needed.
65
65
 
66
+ ### Working with browser DOM and XDocument output
67
+
68
+ Feature available in v5 (next major) of this library.
69
+
70
+ If you already have a browser DOM `Document` or `Node`, convert it to an `XDocument` without re-parsing XML strings:
71
+
72
+ ```js
73
+ import { domDocumentToXDocument } from 'xslt-processor'
74
+
75
+ const parser = new DOMParser();
76
+ const nativeDoc = parser.parseFromString('<root>hello</root>', 'text/xml');
77
+ const xDoc = domDocumentToXDocument(nativeDoc);
78
+ ```
79
+
80
+ You can also run XSLT and get the output as an `XDocument` tree instead of a serialized string:
81
+
82
+ ```js
83
+ import { Xslt, XmlParser } from 'xslt-processor'
84
+
85
+ const xmlParser = new XmlParser();
86
+ const xslt = new Xslt();
87
+
88
+ const xmlDoc = xmlParser.xmlParse('<root><item>hello</item></root>');
89
+ const styleDoc = xmlParser.xmlParse(
90
+ '<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">' +
91
+ ' <xsl:template match="/">' +
92
+ ' <output><xsl:value-of select="/root/item"/></output>' +
93
+ ' </xsl:template>' +
94
+ '</xsl:stylesheet>'
95
+ );
96
+
97
+ const outDoc = await xslt.xsltProcessToDocument(xmlDoc, styleDoc);
98
+ // outDoc is an XDocument you can traverse or serialize with xmlTransformedText.
99
+ ```
100
+
66
101
  ### `Xslt` class options
67
102
 
68
103
  You can pass an `options` object to `Xslt` class:
@@ -84,7 +119,47 @@ const xslt = new Xslt(options);
84
119
  - `parameters` (`array`, default `[]`): external parameters that you want to use.
85
120
  - `name`: the parameter name;
86
121
  - `namespaceUri` (optional): the namespace;
87
- - `value`: the value.
122
+ - `value`: the value. The type is preserved automatically:
123
+ - **string** values become `StringValue`;
124
+ - **number** values become `NumberValue` (usable in XPath arithmetic);
125
+ - **boolean** values become `BooleanValue` (usable in `xsl:if`/`xsl:when` tests);
126
+ - Note: in XPath/XSLT, any non-empty string is truthy, so the string "false" still behaves as true in tests;
127
+ - **`NodeSetValue`** instances are kept as-is (useful for passing additional documents);
128
+ - DOM nodes (objects with `nodeType`) are wrapped in a `NodeSetValue`;
129
+ - arrays of nodes are wrapped in a `NodeSetValue`.
130
+
131
+ **`parameters` examples:**
132
+
133
+ ```js
134
+ import { Xslt, XmlParser } from 'xslt-processor'
135
+
136
+ // String parameter (default behavior)
137
+ const xslt = new Xslt({ parameters: [
138
+ { name: 'title', value: 'Hello' }
139
+ ] });
140
+
141
+ // Number parameter — works in XPath arithmetic ($count + 1 = 43)
142
+ const xslt = new Xslt({ parameters: [
143
+ { name: 'count', value: 42 }
144
+ ] });
145
+
146
+ // Boolean parameter — works in xsl:if / xsl:when tests
147
+ const xslt = new Xslt({ parameters: [
148
+ { name: 'debug', value: true }
149
+ ] });
150
+
151
+ // Node-set parameter — pass an additional document for cross-document lookups
152
+ import { NodeSetValue } from 'xslt-processor/xpath/values'
153
+
154
+ const xmlParser = new XmlParser();
155
+ const lookupDoc = xmlParser.xmlParse('<lookup><entry key="a">Alpha</entry></lookup>');
156
+
157
+ const xslt = new Xslt({ parameters: [
158
+ { name: 'lookup', value: new NodeSetValue([lookupDoc]) }
159
+ ] });
160
+ // In XSLT: <xsl:value-of select="$lookup/lookup/entry[@key='a']"/>
161
+ ```
162
+
88
163
  - `fetchFunction` (`(uri: string) => Promise<string>`, optional): a custom function for loading external resources referenced by `<xsl:import>` and `<xsl:include>`. Receives the URI and must return the fetched content as a string. Defaults to the global `fetch` API. This is useful for:
89
164
  - Denying external loading entirely;
90
165
  - Loading from the local filesystem or other non-HTTP sources;
package/index.d.mts CHANGED
@@ -76,6 +76,16 @@ declare class XDocument extends XNode {
76
76
  createProcessingInstruction(target: string, data: any): XNode;
77
77
  }
78
78
 
79
+ /**
80
+ * Converts a native browser DOM Document or Node into an XDocument/XNode tree
81
+ * compatible with the XSLT processor. This allows browser users who already
82
+ * have a parsed DOM to skip the string-based xmlParse() step.
83
+ *
84
+ * @param nativeNode A browser DOM Document, Element, or other Node.
85
+ * @returns An XDocument representing the same tree structure.
86
+ */
87
+ declare function domDocumentToXDocument(nativeNode: Document | Node): XDocument;
88
+
79
89
  /**
80
90
  * Escape XML special markup characters: tag delimiter <, >, and entity
81
91
  * reference start delimiter &. The escaped string can be used in XML
@@ -878,6 +888,18 @@ declare class Xslt {
878
888
  * @returns the processed document, as XML text in a string, JSON string if outputMethod is 'json', or text if outputMethod is 'text' or 'adaptive' (with text content).
879
889
  */
880
890
  xsltProcess(xmlDoc: XDocument, stylesheet: XDocument): Promise<string>;
891
+ /**
892
+ * Processes the XSLT transformation and returns the output as an XDocument
893
+ * instead of a serialized string. This is useful for:
894
+ * - Working with the result tree programmatically
895
+ * - Converting to a different DOM representation (e.g., React elements)
896
+ * - Using browser-native serialization (XMLSerializer) if desired
897
+ *
898
+ * @param xmlDoc The input document root, as DOM node.
899
+ * @param stylesheet The stylesheet document root, as DOM node.
900
+ * @returns The processed document as an XDocument tree.
901
+ */
902
+ xsltProcessToDocument(xmlDoc: XDocument, stylesheet: XDocument): Promise<XDocument>;
881
903
  /**
882
904
  * The main entry point of the XSL-T processor, as explained on the top of the file.
883
905
  * @param context The input document root, as XPath `ExprContext`.
@@ -1471,6 +1493,15 @@ declare class Xslt {
1471
1493
  * @returns The coerced value.
1472
1494
  */
1473
1495
  protected coerceToType(value: NodeValue, type: string): NodeValue;
1496
+ /**
1497
+ * Converts a raw JavaScript value to the appropriate NodeValue type.
1498
+ * Detects NodeValue instances, DOM nodes, arrays, numbers, booleans,
1499
+ * and falls back to StringValue.
1500
+ *
1501
+ * @param value The raw value to convert.
1502
+ * @returns The wrapped NodeValue.
1503
+ */
1504
+ protected toNodeValue(value: any): NodeValue;
1474
1505
  /**
1475
1506
  * Execute a user-defined xsl:function.
1476
1507
  * Called when a function from userDefinedFunctions is invoked from XPath.
@@ -1733,4 +1764,4 @@ declare class Xslt {
1733
1764
  protected isXsltElement(element: XNode, opt_wantedName?: string): boolean;
1734
1765
  }
1735
1766
 
1736
- export { ExprContext, XPath, XmlParser, Xslt, type XsltOptions, xmlEscapeText };
1767
+ export { ExprContext, XDocument, XNode, XPath, XmlParser, Xslt, type XsltOptions, domDocumentToXDocument, xmlEscapeText };
package/index.d.ts CHANGED
@@ -76,6 +76,16 @@ declare class XDocument extends XNode {
76
76
  createProcessingInstruction(target: string, data: any): XNode;
77
77
  }
78
78
 
79
+ /**
80
+ * Converts a native browser DOM Document or Node into an XDocument/XNode tree
81
+ * compatible with the XSLT processor. This allows browser users who already
82
+ * have a parsed DOM to skip the string-based xmlParse() step.
83
+ *
84
+ * @param nativeNode A browser DOM Document, Element, or other Node.
85
+ * @returns An XDocument representing the same tree structure.
86
+ */
87
+ declare function domDocumentToXDocument(nativeNode: Document | Node): XDocument;
88
+
79
89
  /**
80
90
  * Escape XML special markup characters: tag delimiter <, >, and entity
81
91
  * reference start delimiter &. The escaped string can be used in XML
@@ -878,6 +888,18 @@ declare class Xslt {
878
888
  * @returns the processed document, as XML text in a string, JSON string if outputMethod is 'json', or text if outputMethod is 'text' or 'adaptive' (with text content).
879
889
  */
880
890
  xsltProcess(xmlDoc: XDocument, stylesheet: XDocument): Promise<string>;
891
+ /**
892
+ * Processes the XSLT transformation and returns the output as an XDocument
893
+ * instead of a serialized string. This is useful for:
894
+ * - Working with the result tree programmatically
895
+ * - Converting to a different DOM representation (e.g., React elements)
896
+ * - Using browser-native serialization (XMLSerializer) if desired
897
+ *
898
+ * @param xmlDoc The input document root, as DOM node.
899
+ * @param stylesheet The stylesheet document root, as DOM node.
900
+ * @returns The processed document as an XDocument tree.
901
+ */
902
+ xsltProcessToDocument(xmlDoc: XDocument, stylesheet: XDocument): Promise<XDocument>;
881
903
  /**
882
904
  * The main entry point of the XSL-T processor, as explained on the top of the file.
883
905
  * @param context The input document root, as XPath `ExprContext`.
@@ -1471,6 +1493,15 @@ declare class Xslt {
1471
1493
  * @returns The coerced value.
1472
1494
  */
1473
1495
  protected coerceToType(value: NodeValue, type: string): NodeValue;
1496
+ /**
1497
+ * Converts a raw JavaScript value to the appropriate NodeValue type.
1498
+ * Detects NodeValue instances, DOM nodes, arrays, numbers, booleans,
1499
+ * and falls back to StringValue.
1500
+ *
1501
+ * @param value The raw value to convert.
1502
+ * @returns The wrapped NodeValue.
1503
+ */
1504
+ protected toNodeValue(value: any): NodeValue;
1474
1505
  /**
1475
1506
  * Execute a user-defined xsl:function.
1476
1507
  * Called when a function from userDefinedFunctions is invoked from XPath.
@@ -1733,4 +1764,4 @@ declare class Xslt {
1733
1764
  protected isXsltElement(element: XNode, opt_wantedName?: string): boolean;
1734
1765
  }
1735
1766
 
1736
- export { ExprContext, XPath, XmlParser, Xslt, type XsltOptions, xmlEscapeText };
1767
+ export { ExprContext, XDocument, XNode, XPath, XmlParser, Xslt, type XsltOptions, domDocumentToXDocument, xmlEscapeText };
package/index.js CHANGED
@@ -7800,9 +7800,12 @@ var init_expressions = __esm({
7800
7800
  var index_exports = {};
7801
7801
  __export(index_exports, {
7802
7802
  ExprContext: () => ExprContext,
7803
+ XDocument: () => XDocument,
7804
+ XNode: () => XNode,
7803
7805
  XPath: () => XPath,
7804
7806
  XmlParser: () => XmlParser,
7805
7807
  Xslt: () => Xslt,
7808
+ domDocumentToXDocument: () => domDocumentToXDocument,
7806
7809
  xmlEscapeText: () => xmlEscapeText
7807
7810
  });
7808
7811
  module.exports = __toCommonJS(index_exports);
@@ -10279,38 +10282,6 @@ function createXPathParser(version = DEFAULT_XPATH_VERSION, options) {
10279
10282
  // src/xpath/xpath.ts
10280
10283
  init_expressions();
10281
10284
 
10282
- // src/dom/functions.ts
10283
- function domGetAttributeValue(node, name) {
10284
- return node.getAttributeValue(name);
10285
- }
10286
- function domSetAttribute(node, name, value) {
10287
- return node.setAttribute(name, value);
10288
- }
10289
- function domAppendChild(node, child) {
10290
- return node.appendChild(child);
10291
- }
10292
- function domCreateTextNode(node, text) {
10293
- return node.createTextNode(text);
10294
- }
10295
- function domCreateElement(doc, name) {
10296
- return doc.createElement(name);
10297
- }
10298
- function domCreateCDATASection(doc, data2) {
10299
- return doc.createCDATASection(data2);
10300
- }
10301
- function domCreateComment(doc, text) {
10302
- return doc.createComment(text);
10303
- }
10304
- function domCreateDocumentFragment(doc) {
10305
- return doc.createDocumentFragment();
10306
- }
10307
- function domCreateDTDSection(doc, data2) {
10308
- return doc.createDTDSection(data2);
10309
- }
10310
- function domCreateProcessingInstruction(doc, target, data2) {
10311
- return doc.createProcessingInstruction(target, data2);
10312
- }
10313
-
10314
10285
  // src/constants.ts
10315
10286
  var DOM_ELEMENT_NODE = 1;
10316
10287
  var DOM_ATTRIBUTE_NODE = 2;
@@ -10735,7 +10706,9 @@ var XDocument = class extends XNode {
10735
10706
  }
10736
10707
  appendChild(node) {
10737
10708
  super.appendChild(node);
10738
- this.documentElement = this.childNodes[0];
10709
+ if (node.nodeType === DOM_ELEMENT_NODE && !this.documentElement) {
10710
+ this.documentElement = node;
10711
+ }
10739
10712
  }
10740
10713
  createElement(name) {
10741
10714
  return XNode.create(DOM_ELEMENT_NODE, name, null, this);
@@ -10769,6 +10742,130 @@ var XDocument = class extends XNode {
10769
10742
  }
10770
10743
  };
10771
10744
 
10745
+ // src/dom/dom-to-xdocument.ts
10746
+ function domDocumentToXDocument(nativeNode) {
10747
+ if (nativeNode.nodeType === DOM_DOCUMENT_NODE) {
10748
+ const xDoc2 = new XDocument();
10749
+ const childNodes = nativeNode.childNodes;
10750
+ for (let i = 0; i < childNodes.length; i++) {
10751
+ const converted2 = convertNode(childNodes[i], xDoc2);
10752
+ if (converted2) {
10753
+ converted2.siblingPosition = xDoc2.childNodes.length;
10754
+ xDoc2.appendChild(converted2);
10755
+ }
10756
+ }
10757
+ return xDoc2;
10758
+ }
10759
+ const xDoc = new XDocument();
10760
+ const converted = convertNode(nativeNode, xDoc);
10761
+ if (converted) {
10762
+ converted.siblingPosition = 0;
10763
+ xDoc.appendChild(converted);
10764
+ }
10765
+ return xDoc;
10766
+ }
10767
+ function convertNode(nativeNode, ownerDoc) {
10768
+ switch (nativeNode.nodeType) {
10769
+ case DOM_ELEMENT_NODE: {
10770
+ const element = nativeNode;
10771
+ const xNode = XNode.create(
10772
+ DOM_ELEMENT_NODE,
10773
+ element.nodeName,
10774
+ null,
10775
+ ownerDoc,
10776
+ element.namespaceURI
10777
+ );
10778
+ xNode.prefix = element.prefix || null;
10779
+ xNode.localName = element.localName || element.nodeName;
10780
+ const attrs = element.attributes;
10781
+ for (let i = 0; i < attrs.length; i++) {
10782
+ const attr = attrs[i];
10783
+ const attrNode = XNode.create(
10784
+ DOM_ATTRIBUTE_NODE,
10785
+ attr.name,
10786
+ attr.value,
10787
+ xNode,
10788
+ attr.namespaceURI
10789
+ );
10790
+ attrNode.prefix = attr.prefix || null;
10791
+ attrNode.localName = attr.localName || attr.name;
10792
+ attrNode.parentNode = xNode;
10793
+ attrNode.siblingPosition = xNode.childNodes.length;
10794
+ xNode.appendChild(attrNode);
10795
+ }
10796
+ const childNodes = nativeNode.childNodes;
10797
+ for (let i = 0; i < childNodes.length; i++) {
10798
+ const converted = convertNode(childNodes[i], ownerDoc);
10799
+ if (converted) {
10800
+ converted.siblingPosition = xNode.childNodes.length;
10801
+ xNode.appendChild(converted);
10802
+ }
10803
+ }
10804
+ return xNode;
10805
+ }
10806
+ case DOM_TEXT_NODE:
10807
+ return XNode.create(DOM_TEXT_NODE, "#text", nativeNode.nodeValue || "", ownerDoc);
10808
+ case DOM_CDATA_SECTION_NODE:
10809
+ return XNode.create(DOM_CDATA_SECTION_NODE, "#cdata-section", nativeNode.nodeValue || "", ownerDoc);
10810
+ case DOM_COMMENT_NODE:
10811
+ return XNode.create(DOM_COMMENT_NODE, "#comment", nativeNode.nodeValue || "", ownerDoc);
10812
+ case DOM_PROCESSING_INSTRUCTION_NODE: {
10813
+ const pi2 = nativeNode;
10814
+ return XNode.create(DOM_PROCESSING_INSTRUCTION_NODE, pi2.target, pi2.data, ownerDoc);
10815
+ }
10816
+ case DOM_DOCUMENT_TYPE_NODE: {
10817
+ const dt = nativeNode;
10818
+ return XNode.create(DOM_DOCUMENT_TYPE_NODE, "#dtd-section", dt.name, ownerDoc);
10819
+ }
10820
+ case DOM_DOCUMENT_FRAGMENT_NODE: {
10821
+ const fragment = XNode.create(DOM_DOCUMENT_FRAGMENT_NODE, "#document-fragment", null, ownerDoc);
10822
+ const childNodes = nativeNode.childNodes;
10823
+ for (let i = 0; i < childNodes.length; i++) {
10824
+ const converted = convertNode(childNodes[i], ownerDoc);
10825
+ if (converted) {
10826
+ converted.siblingPosition = fragment.childNodes.length;
10827
+ fragment.appendChild(converted);
10828
+ }
10829
+ }
10830
+ return fragment;
10831
+ }
10832
+ default:
10833
+ return null;
10834
+ }
10835
+ }
10836
+
10837
+ // src/dom/functions.ts
10838
+ function domGetAttributeValue(node, name) {
10839
+ return node.getAttributeValue(name);
10840
+ }
10841
+ function domSetAttribute(node, name, value) {
10842
+ return node.setAttribute(name, value);
10843
+ }
10844
+ function domAppendChild(node, child) {
10845
+ return node.appendChild(child);
10846
+ }
10847
+ function domCreateTextNode(node, text) {
10848
+ return node.createTextNode(text);
10849
+ }
10850
+ function domCreateElement(doc, name) {
10851
+ return doc.createElement(name);
10852
+ }
10853
+ function domCreateCDATASection(doc, data2) {
10854
+ return doc.createCDATASection(data2);
10855
+ }
10856
+ function domCreateComment(doc, text) {
10857
+ return doc.createComment(text);
10858
+ }
10859
+ function domCreateDocumentFragment(doc) {
10860
+ return doc.createDocumentFragment();
10861
+ }
10862
+ function domCreateDTDSection(doc, data2) {
10863
+ return doc.createDTDSection(data2);
10864
+ }
10865
+ function domCreateProcessingInstruction(doc, target, data2) {
10866
+ return doc.createProcessingInstruction(target, data2);
10867
+ }
10868
+
10772
10869
  // src/dom/html-entity-decoder.ts
10773
10870
  var NAMED_ENTITIES = {
10774
10871
  "amp": "&",
@@ -11770,28 +11867,37 @@ var NodeConverter = class {
11770
11867
  */
11771
11868
  convertVariables(exprContext) {
11772
11869
  const variables = {};
11773
- for (const [name, value] of Object.entries(exprContext.variables || {})) {
11774
- if (value && typeof value === "object" && "stringValue" in value) {
11775
- const nodeValue = value;
11776
- if (nodeValue.type === "node-set") {
11777
- variables[name] = value.nodeSetValue().map((n) => this.adaptXNode(n));
11778
- } else if (nodeValue.type === "string") {
11779
- variables[name] = value.stringValue();
11780
- } else if (nodeValue.type === "number") {
11781
- variables[name] = value.numberValue();
11782
- } else if (nodeValue.type === "boolean") {
11783
- variables[name] = value.booleanValue();
11784
- } else if (nodeValue.type === "map") {
11785
- variables[name] = nodeValue.value;
11786
- } else if (nodeValue.type === "array") {
11787
- variables[name] = nodeValue.value;
11788
- } else if (nodeValue.type === "function") {
11789
- variables[name] = nodeValue.value;
11870
+ const contexts = [];
11871
+ let ctx = exprContext;
11872
+ while (ctx) {
11873
+ contexts.push(ctx);
11874
+ ctx = ctx.parent;
11875
+ }
11876
+ for (let i = contexts.length - 1; i >= 0; i--) {
11877
+ const current = contexts[i];
11878
+ for (const [name, value] of Object.entries(current.variables || {})) {
11879
+ if (value && typeof value === "object" && "stringValue" in value) {
11880
+ const nodeValue = value;
11881
+ if (nodeValue.type === "node-set") {
11882
+ variables[name] = value.nodeSetValue().map((n) => this.adaptXNode(n));
11883
+ } else if (nodeValue.type === "string") {
11884
+ variables[name] = value.stringValue();
11885
+ } else if (nodeValue.type === "number") {
11886
+ variables[name] = value.numberValue();
11887
+ } else if (nodeValue.type === "boolean") {
11888
+ variables[name] = value.booleanValue();
11889
+ } else if (nodeValue.type === "map") {
11890
+ variables[name] = nodeValue.value;
11891
+ } else if (nodeValue.type === "array") {
11892
+ variables[name] = nodeValue.value;
11893
+ } else if (nodeValue.type === "function") {
11894
+ variables[name] = nodeValue.value;
11895
+ } else {
11896
+ variables[name] = value.stringValue();
11897
+ }
11790
11898
  } else {
11791
- variables[name] = value.stringValue();
11899
+ variables[name] = value;
11792
11900
  }
11793
- } else {
11794
- variables[name] = value;
11795
11901
  }
11796
11902
  }
11797
11903
  return variables;
@@ -12384,7 +12490,7 @@ var ExprContext = class _ExprContext {
12384
12490
  this.xsltVersion,
12385
12491
  typeof opt_position !== "undefined" ? opt_position : this.position,
12386
12492
  this.decimalFormatSettings,
12387
- this.variables,
12493
+ Object.create(this.variables || {}),
12388
12494
  this.knownNamespaces,
12389
12495
  this,
12390
12496
  this.caseInsensitive,
@@ -13931,16 +14037,7 @@ var Xslt = class {
13931
14037
  */
13932
14038
  xsltProcess(xmlDoc, stylesheet) {
13933
14039
  return __async(this, null, function* () {
13934
- const outputDocument = new XDocument();
13935
- this.outputDocument = outputDocument;
13936
- const expressionContext = new ExprContext([xmlDoc]);
13937
- expressionContext.warningsCallback = this.warningsCallback;
13938
- if (this.options.parameters.length > 0) {
13939
- for (const parameter of this.options.parameters) {
13940
- expressionContext.setVariable(parameter.name, new StringValue(parameter.value));
13941
- }
13942
- }
13943
- yield this.xsltProcessContext(expressionContext, stylesheet, this.outputDocument);
14040
+ const outputDocument = yield this.xsltProcessToDocument(xmlDoc, stylesheet);
13944
14041
  if (this.outputMethod === "json") {
13945
14042
  return xmlToJson(outputDocument);
13946
14043
  }
@@ -13963,6 +14060,32 @@ var Xslt = class {
13963
14060
  return transformedOutputXml;
13964
14061
  });
13965
14062
  }
14063
+ /**
14064
+ * Processes the XSLT transformation and returns the output as an XDocument
14065
+ * instead of a serialized string. This is useful for:
14066
+ * - Working with the result tree programmatically
14067
+ * - Converting to a different DOM representation (e.g., React elements)
14068
+ * - Using browser-native serialization (XMLSerializer) if desired
14069
+ *
14070
+ * @param xmlDoc The input document root, as DOM node.
14071
+ * @param stylesheet The stylesheet document root, as DOM node.
14072
+ * @returns The processed document as an XDocument tree.
14073
+ */
14074
+ xsltProcessToDocument(xmlDoc, stylesheet) {
14075
+ return __async(this, null, function* () {
14076
+ const outputDocument = new XDocument();
14077
+ this.outputDocument = outputDocument;
14078
+ const expressionContext = new ExprContext([xmlDoc]);
14079
+ expressionContext.warningsCallback = this.warningsCallback;
14080
+ if (this.options.parameters.length > 0) {
14081
+ for (const parameter of this.options.parameters) {
14082
+ expressionContext.setVariable(parameter.name, this.toNodeValue(parameter.value));
14083
+ }
14084
+ }
14085
+ yield this.xsltProcessContext(expressionContext, stylesheet, this.outputDocument);
14086
+ return outputDocument;
14087
+ });
14088
+ }
13966
14089
  /**
13967
14090
  * The main entry point of the XSL-T processor, as explained on the top of the file.
13968
14091
  * @param context The input document root, as XPath `ExprContext`.
@@ -17189,6 +17312,29 @@ var Xslt = class {
17189
17312
  return value;
17190
17313
  }
17191
17314
  }
17315
+ /**
17316
+ * Converts a raw JavaScript value to the appropriate NodeValue type.
17317
+ * Detects NodeValue instances, DOM nodes, arrays, numbers, booleans,
17318
+ * and falls back to StringValue.
17319
+ *
17320
+ * @param value The raw value to convert.
17321
+ * @returns The wrapped NodeValue.
17322
+ */
17323
+ toNodeValue(value) {
17324
+ if (value && typeof value === "object" && "stringValue" in value) {
17325
+ return value;
17326
+ } else if (value && typeof value === "object" && "nodeType" in value) {
17327
+ return new NodeSetValue([value]);
17328
+ } else if (Array.isArray(value)) {
17329
+ return new NodeSetValue(value);
17330
+ } else if (typeof value === "number") {
17331
+ return new NumberValue(value);
17332
+ } else if (typeof value === "boolean") {
17333
+ return new BooleanValue(value);
17334
+ } else {
17335
+ return new StringValue(String(value != null ? value : ""));
17336
+ }
17337
+ }
17192
17338
  /**
17193
17339
  * Execute a user-defined xsl:function.
17194
17340
  * Called when a function from userDefinedFunctions is invoked from XPath.
@@ -17226,30 +17372,10 @@ var Xslt = class {
17226
17372
  const paramName = xmlGetAttribute(params[i], "name");
17227
17373
  if (paramName) {
17228
17374
  if (i < args.length) {
17229
- let argValue = args[i];
17230
17375
  const paramType = xmlGetAttribute(params[i], "as");
17231
- let paramValue;
17232
- if (argValue && typeof argValue === "object" && "stringValue" in argValue) {
17233
- paramValue = argValue;
17234
- if (paramType) {
17235
- paramValue = this.coerceToType(paramValue, paramType);
17236
- }
17237
- } else if (argValue && typeof argValue === "object" && "nodeType" in argValue) {
17238
- paramValue = new NodeSetValue([argValue]);
17239
- if (paramType) {
17240
- paramValue = this.coerceToType(paramValue, paramType);
17241
- }
17242
- } else if (Array.isArray(argValue)) {
17243
- paramValue = new NodeSetValue(argValue);
17244
- if (paramType) {
17245
- paramValue = this.coerceToType(paramValue, paramType);
17246
- }
17247
- } else if (typeof argValue === "number") {
17248
- paramValue = new NumberValue(argValue);
17249
- } else if (typeof argValue === "boolean") {
17250
- paramValue = new BooleanValue(argValue);
17251
- } else {
17252
- paramValue = new StringValue(String(argValue != null ? argValue : ""));
17376
+ let paramValue = this.toNodeValue(args[i]);
17377
+ if (paramType) {
17378
+ paramValue = this.coerceToType(paramValue, paramType);
17253
17379
  }
17254
17380
  functionContext.setVariable(paramName, paramValue);
17255
17381
  } else {
@@ -17456,12 +17582,12 @@ var Xslt = class {
17456
17582
  } else if (select) {
17457
17583
  value = this.xPath.xPathEval(select, context);
17458
17584
  } else {
17459
- let parameterValue = "";
17460
17585
  const filteredParameter = this.options.parameters.filter((p) => p.name === name);
17461
17586
  if (filteredParameter.length > 0) {
17462
- parameterValue = filteredParameter[0].value;
17587
+ value = this.toNodeValue(filteredParameter[0].value);
17588
+ } else {
17589
+ value = new StringValue("");
17463
17590
  }
17464
- value = new StringValue(parameterValue);
17465
17591
  }
17466
17592
  if (override || !context.getVariable(name)) {
17467
17593
  context.setVariable(name, value);
@@ -18036,9 +18162,12 @@ var Xslt = class {
18036
18162
  // Annotate the CommonJS export names for ESM import in node:
18037
18163
  0 && (module.exports = {
18038
18164
  ExprContext,
18165
+ XDocument,
18166
+ XNode,
18039
18167
  XPath,
18040
18168
  XmlParser,
18041
18169
  Xslt,
18170
+ domDocumentToXDocument,
18042
18171
  xmlEscapeText
18043
18172
  });
18044
18173
  //# sourceMappingURL=index.js.map