xslt-processor 4.8.5 → 5.0.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/README.md CHANGED
@@ -4,7 +4,7 @@ _A JavaScript XSLT processor without native library dependencies._
4
4
 
5
5
  <p align="center">
6
6
  <a href="https://github.com/DesignLiquido/xslt-processor/issues" target="_blank">
7
- <img src="https://img.shields.io/github/issues/Designliquido/xslt-processor" />
7
+ <img src="https://img.shields.io/github/issues/DesignLiquido/xslt-processor" />
8
8
  </a>
9
9
  <img src="https://img.shields.io/github/stars/Designliquido/xslt-processor" />
10
10
  <img src="https://img.shields.io/github/forks/Designliquido/xslt-processor" />
@@ -37,7 +37,7 @@ ohpm install xslt-processor
37
37
  yarn add xslt-processor
38
38
  ```
39
39
 
40
- Within your ES2015+ code, import the `Xslt` class, the `XmlParser` class and use this way:
40
+ Within your ES2015+ code, import the `Xslt` class, the `XmlParser` class and use it this way:
41
41
 
42
42
  ```js
43
43
  import { Xslt, XmlParser } from 'xslt-processor'
@@ -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:
@@ -80,11 +115,44 @@ const xslt = new Xslt(options);
80
115
  - `cData` (`boolean`, default `true`): resolves CDATA elements in the output. Content under CDATA is resolved as text. This overrides `escape` for CDATA content.
81
116
  - `escape` (`boolean`, default `true`): replaces symbols like `<`, `>`, `&` and `"` by the corresponding [HTML/XML entities](https://www.tutorialspoint.com/xml/xml_character_entities.htm). Can be overridden by `disable-output-escaping`, that also does the opposite, unescaping `&gt;` and `&lt;` by `<` and `>`, respectively.
82
117
  - `selfClosingTags` (`boolean`, default `true`): Self-closes tags that don't have inner elements, if `true`. For instance, `<test></test>` becomes `<test />`.
83
- - `outputMethod` (`string`, default `xml`): Specifies the default output method. if `<xsl:output>` is declared in your XSLT file, this will be overridden. Valid values: `xml`, `html`, `text`, `name`, `xhtml`, `json`, `adaptive`.
118
+ - `outputMethod` (`string`, default `xml`): Specifies the default output method. If `<xsl:output>` is declared in your XSLT file, this will be overridden. Valid values: `xml`, `html`, `text`, `xhtml`, `json`, `adaptive`.
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
122
  - `value`: the value.
123
+ - `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:
124
+ - Denying external loading entirely;
125
+ - Loading from the local filesystem or other non-HTTP sources;
126
+ - Transforming or remapping URIs before fetching.
127
+
128
+ **`fetchFunction` examples:**
129
+
130
+ ```js
131
+ import { readFileSync } from 'fs';
132
+
133
+ // Deny all external loading
134
+ const xslt = new Xslt({
135
+ fetchFunction: async (uri) => {
136
+ throw new Error(`External loading is not allowed: ${uri}`);
137
+ }
138
+ });
139
+
140
+ // Load from local filesystem
141
+ const xslt = new Xslt({
142
+ fetchFunction: async (uri) => {
143
+ return readFileSync(uri, 'utf-8');
144
+ }
145
+ });
146
+
147
+ // Remap URIs before fetching
148
+ const xslt = new Xslt({
149
+ fetchFunction: async (uri) => {
150
+ const remapped = uri.replace('https://example.com/', '/local/stylesheets/');
151
+ const response = await fetch(remapped);
152
+ return response.text();
153
+ }
154
+ });
155
+ ```
88
156
 
89
157
  #### JSON Output Format
90
158
 
@@ -182,10 +250,10 @@ console.log(result2); // "<users><user>John</user></users>" (XML)
182
250
  You can simply add a tag like this:
183
251
 
184
252
  ```html
185
- <script type="application/javascript" src="https://www.unpkg.com/xslt-processor@latest/umd/xslt-processor.global.js"></script>
253
+ <script type="application/javascript" src="https://unpkg.com/xslt-processor@latest/umd/xslt-processor.global.js"></script>
186
254
  ```
187
255
 
188
- All the exports will live under `globalThis.XsltProcessor` and `window.XsltProcessor`. [See a usage example here](https://github.com/DesignLiquido/xslt-processor/blob/main/interactive-tests/xslt.html).
256
+ All the exports will live under `globalThis.XsltProcessor` and `window.XsltProcessor`. [See a usage example here](https://github.com/DesignLiquido/xslt-processor/blob/main/interactive-tests/xslt.html).
189
257
 
190
258
  ## XPath Parser
191
259
 
@@ -204,7 +272,7 @@ import { XPath } from 'xslt-processor'
204
272
  const xPath = new XPath();
205
273
  ```
206
274
 
207
- `XPath` class is an external dependency, [living in its own repository](https://github.com/DesignLiquido/xpath).
275
+ `XPath` class is an external dependency, [living in its own repository](https://github.com/DesignLiquido/xpath).
208
276
 
209
277
  ## Introduction
210
278
 
@@ -215,13 +283,40 @@ XSLT-processor builds on Google's [AJAXSLT](https://github.com/4031651/ajaxslt)
215
283
 
216
284
  This implementation of XSLT operates at the DOM level on its input documents. It internally uses a DOM implementation to create the output document, but usually returns the output document as text stream. The DOM to construct the output document can be supplied by the application, or else an internal minimal DOM implementation is used. This DOM comes with a minimal XML parser that can be used to generate a suitable DOM representation of the input documents if they are present as text.
217
285
 
286
+ ## Building from source
287
+
288
+ The XPath engine lives in a Git submodule at `src/xpath/lib`. A regular `git clone` does **not** fetch it automatically, so the build will fail unless the submodule is initialised.
289
+
290
+ ### Fresh clone
291
+
292
+ ```sh
293
+ git clone --recurse-submodules https://github.com/DesignLiquido/xslt-processor.git
294
+ cd xslt-processor
295
+ yarn install
296
+ yarn build
297
+ ```
298
+
299
+ ### Already cloned without submodules
300
+
301
+ ```sh
302
+ git submodule update --init --recursive
303
+ yarn install
304
+ yarn build
305
+ ```
306
+
307
+ ### Updating the submodule to the latest commit
308
+
309
+ ```sh
310
+ git submodule update --remote src/xpath/lib
311
+ ```
312
+
218
313
  ## Tests and usage examples
219
314
 
220
- New tests are written in Jest an can be run by calling: `yarn test`.
315
+ New tests are written in Jest and can be run by calling: `yarn test`.
221
316
 
222
317
  The files `xslt.html` and `xpath.html` in the directory `interactive-tests` are interactive tests. They can be run directly from the file system; no HTTP server is needed.
223
318
 
224
- Both interactive tests and automatic tests demonstrate the use of the library functions.
319
+ Both interactive tests and automatic tests demonstrate the use of the library functions.
225
320
 
226
321
  ## Conformance
227
322
 
@@ -233,9 +328,9 @@ So far, we have implemented XQuery functions for versions 1.0 and 2.0, but this
233
328
 
234
329
  The DOM implementation is minimal so as to support the XSLT processing, and not intended to be complete.
235
330
 
236
- The implementation is all agnostic about namespaces. It just expects XSLT elements to have tags that carry the `xsl:` prefix, but we disregard all namespace declaration for them.
331
+ The implementation is all agnostic about namespaces. It just expects XSLT elements to have tags that carry the `xsl:` prefix, but we disregard all namespace declarations for them.
237
332
 
238
- [There are a few nonstandard XPath functions](https://github.com/search?q=repo%3ADesignLiquido%2Fxslt-processor%20ext-&type=code).
333
+ [There are a few nonstandard XPath functions](https://github.com/search?q=repo%3ADesignLiquido%2Fxslt-processor%20ext-&type=code).
239
334
 
240
335
  ### HTML Conformance
241
336
 
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
@@ -172,6 +182,7 @@ type XsltOptions = {
172
182
  selfClosingTags: boolean;
173
183
  outputMethod?: 'xml' | 'html' | 'text' | 'xhtml' | 'json' | 'adaptive';
174
184
  parameters?: XsltParameter[];
185
+ fetchFunction?: (uri: string) => Promise<string>;
175
186
  };
176
187
 
177
188
  interface NodeValue {
@@ -760,6 +771,12 @@ declare class Xslt {
760
771
  options: XsltOptions;
761
772
  decimalFormatSettings: XsltDecimalFormatSettings;
762
773
  warningsCallback: (...args: any[]) => void;
774
+ /**
775
+ * Custom fetch function for loading external resources (e.g. xsl:import, xsl:include).
776
+ * Takes a URI and returns the fetched content as a string.
777
+ * Defaults to using the global `fetch` API.
778
+ */
779
+ fetchFunction: (uri: string) => Promise<string>;
763
780
  outputDocument: XDocument;
764
781
  outputMethod: 'xml' | 'html' | 'text' | 'name' | 'xhtml' | 'json' | 'adaptive';
765
782
  outputOmitXmlDeclaration: string;
@@ -871,6 +888,18 @@ declare class Xslt {
871
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).
872
889
  */
873
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>;
874
903
  /**
875
904
  * The main entry point of the XSL-T processor, as explained on the top of the file.
876
905
  * @param context The input document root, as XPath `ExprContext`.
@@ -1464,6 +1493,15 @@ declare class Xslt {
1464
1493
  * @returns The coerced value.
1465
1494
  */
1466
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;
1467
1505
  /**
1468
1506
  * Execute a user-defined xsl:function.
1469
1507
  * Called when a function from userDefinedFunctions is invoked from XPath.
@@ -1726,4 +1764,4 @@ declare class Xslt {
1726
1764
  protected isXsltElement(element: XNode, opt_wantedName?: string): boolean;
1727
1765
  }
1728
1766
 
1729
- 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
@@ -172,6 +182,7 @@ type XsltOptions = {
172
182
  selfClosingTags: boolean;
173
183
  outputMethod?: 'xml' | 'html' | 'text' | 'xhtml' | 'json' | 'adaptive';
174
184
  parameters?: XsltParameter[];
185
+ fetchFunction?: (uri: string) => Promise<string>;
175
186
  };
176
187
 
177
188
  interface NodeValue {
@@ -760,6 +771,12 @@ declare class Xslt {
760
771
  options: XsltOptions;
761
772
  decimalFormatSettings: XsltDecimalFormatSettings;
762
773
  warningsCallback: (...args: any[]) => void;
774
+ /**
775
+ * Custom fetch function for loading external resources (e.g. xsl:import, xsl:include).
776
+ * Takes a URI and returns the fetched content as a string.
777
+ * Defaults to using the global `fetch` API.
778
+ */
779
+ fetchFunction: (uri: string) => Promise<string>;
763
780
  outputDocument: XDocument;
764
781
  outputMethod: 'xml' | 'html' | 'text' | 'name' | 'xhtml' | 'json' | 'adaptive';
765
782
  outputOmitXmlDeclaration: string;
@@ -871,6 +888,18 @@ declare class Xslt {
871
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).
872
889
  */
873
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>;
874
903
  /**
875
904
  * The main entry point of the XSL-T processor, as explained on the top of the file.
876
905
  * @param context The input document root, as XPath `ExprContext`.
@@ -1464,6 +1493,15 @@ declare class Xslt {
1464
1493
  * @returns The coerced value.
1465
1494
  */
1466
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;
1467
1505
  /**
1468
1506
  * Execute a user-defined xsl:function.
1469
1507
  * Called when a function from userDefinedFunctions is invoked from XPath.
@@ -1726,4 +1764,4 @@ declare class Xslt {
1726
1764
  protected isXsltElement(element: XNode, opt_wantedName?: string): boolean;
1727
1765
  }
1728
1766
 
1729
- export { ExprContext, XPath, XmlParser, Xslt, type XsltOptions, xmlEscapeText };
1767
+ export { ExprContext, XDocument, XNode, XPath, XmlParser, Xslt, type XsltOptions, domDocumentToXDocument, xmlEscapeText };