xslt-processor 4.2.1 → 4.3.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 +46 -1
- package/index.d.mts +3 -2
- package/index.d.ts +3 -2
- package/index.js +122 -2
- package/index.js.map +1 -1
- package/index.mjs +122 -2
- package/index.mjs.map +1 -1
- package/package.json +1 -1
- package/umd/xslt-processor.global.js +3 -3
- package/umd/xslt-processor.global.js.map +1 -1
package/README.md
CHANGED
|
@@ -89,12 +89,57 @@ const xslt = new Xslt(options);
|
|
|
89
89
|
- `cData` (`boolean`, default `true`): resolves CDATA elements in the output. Content under CDATA is resolved as text. This overrides `escape` for CDATA content.
|
|
90
90
|
- `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 `>` and `<` by `<` and `>`, respectively.
|
|
91
91
|
- `selfClosingTags` (`boolean`, default `true`): Self-closes tags that don't have inner elements, if `true`. For instance, `<test></test>` becomes `<test />`.
|
|
92
|
-
- `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`.
|
|
92
|
+
- `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`.
|
|
93
93
|
- `parameters` (`array`, default `[]`): external parameters that you want to use.
|
|
94
94
|
- `name`: the parameter name;
|
|
95
95
|
- `namespaceUri` (optional): the namespace;
|
|
96
96
|
- `value`: the value.
|
|
97
97
|
|
|
98
|
+
#### JSON Output Format
|
|
99
|
+
|
|
100
|
+
When using `outputMethod: 'json'`, the XSLT processor will convert the resulting XML document to JSON format. This is useful for APIs and modern JavaScript applications.
|
|
101
|
+
|
|
102
|
+
**Example:**
|
|
103
|
+
|
|
104
|
+
```js
|
|
105
|
+
const xslt = new Xslt({ outputMethod: 'json' });
|
|
106
|
+
const xmlParser = new XmlParser();
|
|
107
|
+
|
|
108
|
+
const xmlString = `<root>
|
|
109
|
+
<users>
|
|
110
|
+
<user>Alice</user>
|
|
111
|
+
<user>Bob</user>
|
|
112
|
+
</users>
|
|
113
|
+
</root>`;
|
|
114
|
+
|
|
115
|
+
const xsltString = `<?xml version="1.0"?>
|
|
116
|
+
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
117
|
+
<xsl:template match="/">
|
|
118
|
+
<xsl:copy-of select="root"/>
|
|
119
|
+
</xsl:template>
|
|
120
|
+
</xsl:stylesheet>`;
|
|
121
|
+
|
|
122
|
+
const result = await xslt.xsltProcess(
|
|
123
|
+
xmlParser.xmlParse(xmlString),
|
|
124
|
+
xmlParser.xmlParse(xsltString)
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
// result will be a JSON string:
|
|
128
|
+
// {"root":{"users":{"user":["Alice","Bob"]}}}
|
|
129
|
+
|
|
130
|
+
const parsed = JSON.parse(result);
|
|
131
|
+
console.log(parsed.root.users.user); // ["Alice", "Bob"]
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**JSON Structure Rules:**
|
|
135
|
+
|
|
136
|
+
- Each element becomes a property in a JSON object
|
|
137
|
+
- Text-only elements become string values
|
|
138
|
+
- Elements with multiple children of the same name become arrays
|
|
139
|
+
- Empty elements are omitted from the output
|
|
140
|
+
- Attributes are prefixed with `@` (when present in the output)
|
|
141
|
+
- Mixed text and element content uses the `#text` property for text nodes
|
|
142
|
+
|
|
98
143
|
### Direct use in browsers
|
|
99
144
|
|
|
100
145
|
You can simply add a tag like this:
|
package/index.d.mts
CHANGED
|
@@ -532,6 +532,7 @@ type XsltOptions = {
|
|
|
532
532
|
cData: boolean;
|
|
533
533
|
escape: boolean;
|
|
534
534
|
selfClosingTags: boolean;
|
|
535
|
+
outputMethod?: 'xml' | 'html' | 'text' | 'xhtml' | 'json';
|
|
535
536
|
parameters?: XsltParameter[];
|
|
536
537
|
};
|
|
537
538
|
|
|
@@ -566,7 +567,7 @@ declare class Xslt {
|
|
|
566
567
|
options: XsltOptions;
|
|
567
568
|
decimalFormatSettings: XsltDecimalFormatSettings;
|
|
568
569
|
outputDocument: XDocument;
|
|
569
|
-
outputMethod: 'xml' | 'html' | 'text' | 'name' | 'xhtml';
|
|
570
|
+
outputMethod: 'xml' | 'html' | 'text' | 'name' | 'xhtml' | 'json';
|
|
570
571
|
outputOmitXmlDeclaration: string;
|
|
571
572
|
version: string;
|
|
572
573
|
firstTemplateRan: boolean;
|
|
@@ -591,7 +592,7 @@ declare class Xslt {
|
|
|
591
592
|
* The exported entry point of the XSL-T processor.
|
|
592
593
|
* @param xmlDoc The input document root, as DOM node.
|
|
593
594
|
* @param stylesheet The stylesheet document root, as DOM node.
|
|
594
|
-
* @returns the processed document, as XML text in a string.
|
|
595
|
+
* @returns the processed document, as XML text in a string, or JSON string if outputMethod is 'json'.
|
|
595
596
|
*/
|
|
596
597
|
xsltProcess(xmlDoc: XDocument, stylesheet: XDocument): Promise<string>;
|
|
597
598
|
/**
|
package/index.d.ts
CHANGED
|
@@ -532,6 +532,7 @@ type XsltOptions = {
|
|
|
532
532
|
cData: boolean;
|
|
533
533
|
escape: boolean;
|
|
534
534
|
selfClosingTags: boolean;
|
|
535
|
+
outputMethod?: 'xml' | 'html' | 'text' | 'xhtml' | 'json';
|
|
535
536
|
parameters?: XsltParameter[];
|
|
536
537
|
};
|
|
537
538
|
|
|
@@ -566,7 +567,7 @@ declare class Xslt {
|
|
|
566
567
|
options: XsltOptions;
|
|
567
568
|
decimalFormatSettings: XsltDecimalFormatSettings;
|
|
568
569
|
outputDocument: XDocument;
|
|
569
|
-
outputMethod: 'xml' | 'html' | 'text' | 'name' | 'xhtml';
|
|
570
|
+
outputMethod: 'xml' | 'html' | 'text' | 'name' | 'xhtml' | 'json';
|
|
570
571
|
outputOmitXmlDeclaration: string;
|
|
571
572
|
version: string;
|
|
572
573
|
firstTemplateRan: boolean;
|
|
@@ -591,7 +592,7 @@ declare class Xslt {
|
|
|
591
592
|
* The exported entry point of the XSL-T processor.
|
|
592
593
|
* @param xmlDoc The input document root, as DOM node.
|
|
593
594
|
* @param stylesheet The stylesheet document root, as DOM node.
|
|
594
|
-
* @returns the processed document, as XML text in a string.
|
|
595
|
+
* @returns the processed document, as XML text in a string, or JSON string if outputMethod is 'json'.
|
|
595
596
|
*/
|
|
596
597
|
xsltProcess(xmlDoc: XDocument, stylesheet: XDocument): Promise<string>;
|
|
597
598
|
/**
|
package/index.js
CHANGED
|
@@ -2213,6 +2213,122 @@ function xmlGetAttribute(node, name) {
|
|
|
2213
2213
|
}
|
|
2214
2214
|
return value;
|
|
2215
2215
|
}
|
|
2216
|
+
function nodeToJsonObject(node) {
|
|
2217
|
+
if (!node) {
|
|
2218
|
+
return null;
|
|
2219
|
+
}
|
|
2220
|
+
const nodeType = node.nodeType;
|
|
2221
|
+
if (nodeType === DOM_TEXT_NODE || nodeType === DOM_CDATA_SECTION_NODE) {
|
|
2222
|
+
const text = node.nodeValue ? node.nodeValue.trim() : "";
|
|
2223
|
+
return text.length > 0 ? text : null;
|
|
2224
|
+
}
|
|
2225
|
+
if (nodeType === DOM_COMMENT_NODE) {
|
|
2226
|
+
return null;
|
|
2227
|
+
}
|
|
2228
|
+
if (nodeType === DOM_DOCUMENT_NODE || nodeType === DOM_DOCUMENT_FRAGMENT_NODE) {
|
|
2229
|
+
const children = node.childNodes || [];
|
|
2230
|
+
const childObjects = [];
|
|
2231
|
+
for (let i = 0; i < children.length; i++) {
|
|
2232
|
+
const child = children[i];
|
|
2233
|
+
const childObj = nodeToJsonObject(child);
|
|
2234
|
+
if (childObj !== null) {
|
|
2235
|
+
childObjects.push(childObj);
|
|
2236
|
+
}
|
|
2237
|
+
}
|
|
2238
|
+
if (childObjects.length === 0) {
|
|
2239
|
+
return null;
|
|
2240
|
+
} else if (childObjects.length === 1) {
|
|
2241
|
+
return childObjects[0];
|
|
2242
|
+
} else {
|
|
2243
|
+
return childObjects;
|
|
2244
|
+
}
|
|
2245
|
+
}
|
|
2246
|
+
if (nodeType === DOM_ELEMENT_NODE) {
|
|
2247
|
+
const obj = {};
|
|
2248
|
+
const element = node;
|
|
2249
|
+
const hasAttributes = element.attributes && element.attributes.length > 0;
|
|
2250
|
+
if (hasAttributes) {
|
|
2251
|
+
for (let i = 0; i < element.attributes.length; i++) {
|
|
2252
|
+
const attr = element.attributes[i];
|
|
2253
|
+
obj["@" + attr.nodeName] = attr.nodeValue;
|
|
2254
|
+
}
|
|
2255
|
+
}
|
|
2256
|
+
const children = element.childNodes || [];
|
|
2257
|
+
let textContent = "";
|
|
2258
|
+
let hasElementChildren = false;
|
|
2259
|
+
const childElements = {};
|
|
2260
|
+
for (let i = 0; i < children.length; i++) {
|
|
2261
|
+
const child = children[i];
|
|
2262
|
+
const childType = child.nodeType;
|
|
2263
|
+
if (childType === DOM_TEXT_NODE || childType === DOM_CDATA_SECTION_NODE) {
|
|
2264
|
+
const text = child.nodeValue ? child.nodeValue.trim() : "";
|
|
2265
|
+
if (text.length > 0) {
|
|
2266
|
+
textContent += text;
|
|
2267
|
+
}
|
|
2268
|
+
} else if (childType === DOM_ELEMENT_NODE) {
|
|
2269
|
+
hasElementChildren = true;
|
|
2270
|
+
const childElement = child;
|
|
2271
|
+
const childName = childElement.localName || childElement.nodeName;
|
|
2272
|
+
const childObj = nodeToJsonObject(child);
|
|
2273
|
+
if (childObj !== null) {
|
|
2274
|
+
if (childElements[childName]) {
|
|
2275
|
+
if (!Array.isArray(childElements[childName])) {
|
|
2276
|
+
childElements[childName] = [childElements[childName]];
|
|
2277
|
+
}
|
|
2278
|
+
childElements[childName].push(childObj);
|
|
2279
|
+
} else {
|
|
2280
|
+
childElements[childName] = childObj;
|
|
2281
|
+
}
|
|
2282
|
+
}
|
|
2283
|
+
}
|
|
2284
|
+
}
|
|
2285
|
+
Object.assign(obj, childElements);
|
|
2286
|
+
if (!hasElementChildren && textContent.length > 0) {
|
|
2287
|
+
if (!hasAttributes && Object.keys(childElements).length === 0) {
|
|
2288
|
+
return textContent;
|
|
2289
|
+
} else {
|
|
2290
|
+
obj["#text"] = textContent;
|
|
2291
|
+
}
|
|
2292
|
+
}
|
|
2293
|
+
if (Object.keys(obj).length === 0) {
|
|
2294
|
+
return null;
|
|
2295
|
+
}
|
|
2296
|
+
return obj;
|
|
2297
|
+
}
|
|
2298
|
+
return null;
|
|
2299
|
+
}
|
|
2300
|
+
function xmlToJson(node) {
|
|
2301
|
+
if (!node) {
|
|
2302
|
+
return "{}";
|
|
2303
|
+
}
|
|
2304
|
+
let rootElement = node;
|
|
2305
|
+
if (node.nodeType === DOM_DOCUMENT_NODE || node.nodeType === DOM_DOCUMENT_FRAGMENT_NODE) {
|
|
2306
|
+
const children = node.childNodes || [];
|
|
2307
|
+
for (let i = 0; i < children.length; i++) {
|
|
2308
|
+
if (children[i].nodeType === DOM_ELEMENT_NODE) {
|
|
2309
|
+
rootElement = children[i];
|
|
2310
|
+
break;
|
|
2311
|
+
}
|
|
2312
|
+
}
|
|
2313
|
+
}
|
|
2314
|
+
const element = rootElement;
|
|
2315
|
+
const rootName = element.localName || element.nodeName;
|
|
2316
|
+
const jsonObj = {};
|
|
2317
|
+
const elementContent = nodeToJsonObject(rootElement);
|
|
2318
|
+
if (elementContent === null) {
|
|
2319
|
+
jsonObj[rootName] = {};
|
|
2320
|
+
} else if (typeof elementContent === "object" && !Array.isArray(elementContent)) {
|
|
2321
|
+
jsonObj[rootName] = elementContent;
|
|
2322
|
+
} else {
|
|
2323
|
+
jsonObj[rootName] = elementContent;
|
|
2324
|
+
}
|
|
2325
|
+
try {
|
|
2326
|
+
const cleaned = JSON.parse(JSON.stringify(jsonObj));
|
|
2327
|
+
return JSON.stringify(cleaned);
|
|
2328
|
+
} catch (error) {
|
|
2329
|
+
return JSON.stringify(jsonObj);
|
|
2330
|
+
}
|
|
2331
|
+
}
|
|
2216
2332
|
|
|
2217
2333
|
// src/dom/xml-parser.ts
|
|
2218
2334
|
var import_he2 = __toESM(require("he"));
|
|
@@ -3551,9 +3667,10 @@ var Xslt = class {
|
|
|
3551
3667
|
cData: options.cData === true,
|
|
3552
3668
|
escape: options.escape === true,
|
|
3553
3669
|
selfClosingTags: options.selfClosingTags === true,
|
|
3670
|
+
outputMethod: options.outputMethod,
|
|
3554
3671
|
parameters: options.parameters || []
|
|
3555
3672
|
};
|
|
3556
|
-
this.outputMethod = "xml";
|
|
3673
|
+
this.outputMethod = options.outputMethod || "xml";
|
|
3557
3674
|
this.outputOmitXmlDeclaration = "no";
|
|
3558
3675
|
this.stripSpacePatterns = [];
|
|
3559
3676
|
this.preserveSpacePatterns = [];
|
|
@@ -3576,7 +3693,7 @@ var Xslt = class {
|
|
|
3576
3693
|
* The exported entry point of the XSL-T processor.
|
|
3577
3694
|
* @param xmlDoc The input document root, as DOM node.
|
|
3578
3695
|
* @param stylesheet The stylesheet document root, as DOM node.
|
|
3579
|
-
* @returns the processed document, as XML text in a string.
|
|
3696
|
+
* @returns the processed document, as XML text in a string, or JSON string if outputMethod is 'json'.
|
|
3580
3697
|
*/
|
|
3581
3698
|
xsltProcess(xmlDoc, stylesheet) {
|
|
3582
3699
|
return __async(this, null, function* () {
|
|
@@ -3589,6 +3706,9 @@ var Xslt = class {
|
|
|
3589
3706
|
}
|
|
3590
3707
|
}
|
|
3591
3708
|
yield this.xsltProcessContext(expressionContext, stylesheet, this.outputDocument);
|
|
3709
|
+
if (this.outputMethod === "json") {
|
|
3710
|
+
return xmlToJson(outputDocument);
|
|
3711
|
+
}
|
|
3592
3712
|
const transformedOutputXml = xmlTransformedText(outputDocument, {
|
|
3593
3713
|
cData: this.options.cData,
|
|
3594
3714
|
escape: this.options.escape,
|