fast-xml-parser 5.6.0 → 5.7.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/CHANGELOG.md +17 -0
- package/lib/fxbuilder.min.js +1 -1
- package/lib/fxbuilder.min.js.map +1 -1
- package/lib/fxp.cjs +1 -1
- package/lib/fxp.d.cts +17 -1
- package/lib/fxp.min.js +1 -1
- package/lib/fxp.min.js.map +1 -1
- package/lib/fxparser.min.js +1 -1
- package/lib/fxparser.min.js.map +1 -1
- package/package.json +3 -3
- package/src/fxp.d.ts +16 -0
- package/src/xmlparser/DocTypeReader.js +2 -5
- package/src/xmlparser/OptionsBuilder.js +11 -7
- package/src/xmlparser/OrderedObjParser.js +31 -17
- package/src/xmlparser/XMLParser.js +1 -1
- package/src/fast-xml-parser.zip +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fast-xml-parser",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.7.1",
|
|
4
4
|
"description": "Validate XML, Parse XML, Build XML without C/C++ based libraries",
|
|
5
5
|
"main": "./lib/fxp.cjs",
|
|
6
6
|
"type": "module",
|
|
@@ -87,8 +87,8 @@
|
|
|
87
87
|
}
|
|
88
88
|
],
|
|
89
89
|
"dependencies": {
|
|
90
|
-
"@nodable/entities": "^
|
|
91
|
-
"fast-xml-builder": "^1.1.
|
|
90
|
+
"@nodable/entities": "^2.1.0",
|
|
91
|
+
"fast-xml-builder": "^1.1.5",
|
|
92
92
|
"path-expression-matcher": "^1.5.0",
|
|
93
93
|
"strnum": "^2.2.3"
|
|
94
94
|
}
|
package/src/fxp.d.ts
CHANGED
|
@@ -211,6 +211,14 @@ export type ProcessEntitiesOptions = {
|
|
|
211
211
|
tagFilter?: ((tagName: string, jPathOrMatcher: JPathOrMatcher) => boolean) | null;
|
|
212
212
|
};
|
|
213
213
|
|
|
214
|
+
export type EntityDecoderOptions = {
|
|
215
|
+
setExternalEntities: (entities: Record<string, string>) => void;
|
|
216
|
+
addInputEntities: (entities: Record<string, string>) => void;
|
|
217
|
+
reset: () => void;
|
|
218
|
+
decode: (text: string) => string;
|
|
219
|
+
setXmlVersion: (version: string) => void;
|
|
220
|
+
}
|
|
221
|
+
|
|
214
222
|
export type X2jOptions = {
|
|
215
223
|
/**
|
|
216
224
|
* Preserve the order of tags in resulting JS object
|
|
@@ -397,9 +405,14 @@ export type X2jOptions = {
|
|
|
397
405
|
* Whether to process HTML entities
|
|
398
406
|
*
|
|
399
407
|
* Defaults to `false`
|
|
408
|
+
* @deprecated Use `entityDecoder` instead
|
|
400
409
|
*/
|
|
401
410
|
htmlEntities?: boolean;
|
|
402
411
|
|
|
412
|
+
/**
|
|
413
|
+
* Custom entity decoder
|
|
414
|
+
*/
|
|
415
|
+
entityDecoder?: EntityDecoderOptions;
|
|
403
416
|
/**
|
|
404
417
|
* Whether to ignore the declaration tag from output
|
|
405
418
|
*
|
|
@@ -707,6 +720,9 @@ export class XMLParser {
|
|
|
707
720
|
export class XMLValidator {
|
|
708
721
|
static validate(xmlData: string, options?: validationOptions): true | ValidationError;
|
|
709
722
|
}
|
|
723
|
+
/**
|
|
724
|
+
* @deprecated Use npm package 'fast-xml-builder' instead
|
|
725
|
+
*/
|
|
710
726
|
export class XMLBuilder {
|
|
711
727
|
constructor(options?: XmlBuilderOptions);
|
|
712
728
|
build(jObj: any): string;
|
|
@@ -35,11 +35,8 @@ export default class DocTypeReader {
|
|
|
35
35
|
);
|
|
36
36
|
}
|
|
37
37
|
//const escaped = entityName.replace(/[.\-+*:]/g, '\\.');
|
|
38
|
-
const escaped = entityName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
39
|
-
entities[entityName] =
|
|
40
|
-
regx: RegExp(`&${escaped};`, "g"),
|
|
41
|
-
val: val
|
|
42
|
-
};
|
|
38
|
+
//const escaped = entityName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
39
|
+
entities[entityName] = val;
|
|
43
40
|
entityCount++;
|
|
44
41
|
}
|
|
45
42
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { DANGEROUS_PROPERTY_NAMES, criticalProperties } from "../util.js";
|
|
2
|
+
import { COMMON_HTML, CURRENCY } from '@nodable/entities';
|
|
2
3
|
|
|
3
4
|
const defaultOnDangerousProperty = (name) => {
|
|
4
5
|
if (DANGEROUS_PROPERTY_NAMES.includes(name)) {
|
|
@@ -39,6 +40,7 @@ export const defaultOptions = {
|
|
|
39
40
|
unpairedTags: [],
|
|
40
41
|
processEntities: true,
|
|
41
42
|
htmlEntities: false,
|
|
43
|
+
entityDecoder: null,
|
|
42
44
|
ignoreDeclaration: false,
|
|
43
45
|
ignorePiTags: false,
|
|
44
46
|
transformTagName: false,
|
|
@@ -85,18 +87,19 @@ function validatePropertyName(propertyName, optionName) {
|
|
|
85
87
|
* @param {boolean|object} value
|
|
86
88
|
* @returns {object} Always returns normalized object
|
|
87
89
|
*/
|
|
88
|
-
function normalizeProcessEntities(value) {
|
|
90
|
+
function normalizeProcessEntities(value, htmlEntities) {
|
|
89
91
|
// Boolean backward compatibility
|
|
90
92
|
if (typeof value === 'boolean') {
|
|
91
93
|
return {
|
|
92
94
|
enabled: value, // true or false
|
|
93
95
|
maxEntitySize: 10000,
|
|
94
|
-
maxExpansionDepth:
|
|
95
|
-
maxTotalExpansions:
|
|
96
|
+
maxExpansionDepth: 10000,
|
|
97
|
+
maxTotalExpansions: Infinity,
|
|
96
98
|
maxExpandedLength: 100000,
|
|
97
|
-
maxEntityCount:
|
|
99
|
+
maxEntityCount: 1000,
|
|
98
100
|
allowedTags: null,
|
|
99
|
-
tagFilter: null
|
|
101
|
+
tagFilter: null,
|
|
102
|
+
appliesTo: "all",
|
|
100
103
|
};
|
|
101
104
|
}
|
|
102
105
|
|
|
@@ -110,7 +113,8 @@ function normalizeProcessEntities(value) {
|
|
|
110
113
|
maxExpandedLength: Math.max(1, value.maxExpandedLength ?? 100000),
|
|
111
114
|
maxEntityCount: Math.max(1, value.maxEntityCount ?? 1000),
|
|
112
115
|
allowedTags: value.allowedTags ?? null,
|
|
113
|
-
tagFilter: value.tagFilter ?? null
|
|
116
|
+
tagFilter: value.tagFilter ?? null,
|
|
117
|
+
appliesTo: value.appliesTo ?? "all",
|
|
114
118
|
};
|
|
115
119
|
}
|
|
116
120
|
|
|
@@ -141,7 +145,7 @@ export const buildOptions = function (options) {
|
|
|
141
145
|
}
|
|
142
146
|
|
|
143
147
|
// Always normalize processEntities for backward compatibility and validation
|
|
144
|
-
built.processEntities = normalizeProcessEntities(built.processEntities);
|
|
148
|
+
built.processEntities = normalizeProcessEntities(built.processEntities, built.htmlEntities);
|
|
145
149
|
built.unpairedTagsSet = new Set(built.unpairedTags);
|
|
146
150
|
// Convert old-style stopNodes for backward compatibility
|
|
147
151
|
if (built.stopNodes && Array.isArray(built.stopNodes)) {
|
|
@@ -8,7 +8,7 @@ import toNumber from "strnum";
|
|
|
8
8
|
import getIgnoreAttributesFn from "../ignoreAttributes.js";
|
|
9
9
|
import { Expression, Matcher } from 'path-expression-matcher';
|
|
10
10
|
import { ExpressionSet } from 'path-expression-matcher';
|
|
11
|
-
import
|
|
11
|
+
import { EntityDecoder, XML, CURRENCY, COMMON_HTML } from '@nodable/entities';
|
|
12
12
|
|
|
13
13
|
// const regx =
|
|
14
14
|
// '<((!\\[CDATA\\[([\\s\\S]*?)(]]>))|((NAME:)?(NAME))([^>]*)>|((\\/)(NAME)\\s*>))([^<]*)'
|
|
@@ -85,16 +85,23 @@ export default class OrderedObjParser {
|
|
|
85
85
|
this.ignoreAttributesFn = getIgnoreAttributesFn(this.options.ignoreAttributes)
|
|
86
86
|
this.entityExpansionCount = 0;
|
|
87
87
|
this.currentExpandedLength = 0;
|
|
88
|
-
|
|
89
|
-
this.
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
88
|
+
let namedEntities = { ...XML };
|
|
89
|
+
if (this.options.entityDecoder) {
|
|
90
|
+
this.entityDecoder = this.options.entityDecoder
|
|
91
|
+
} else {
|
|
92
|
+
if (typeof this.options.htmlEntities === "object") namedEntities = this.options.htmlEntities;
|
|
93
|
+
else if (this.options.htmlEntities === true) namedEntities = { ...COMMON_HTML, ...CURRENCY };
|
|
94
|
+
this.entityDecoder = new EntityDecoder({
|
|
95
|
+
namedEntities: namedEntities,
|
|
96
|
+
numericAllowed: this.options.htmlEntities,
|
|
97
|
+
limit: {
|
|
98
|
+
maxTotalExpansions: this.options.processEntities.maxTotalExpansions,
|
|
99
|
+
maxExpandedLength: this.options.processEntities.maxExpandedLength,
|
|
100
|
+
applyLimitsTo: this.options.processEntities.appliesTo,
|
|
101
|
+
}
|
|
102
|
+
//postCheck: resolved => resolved
|
|
103
|
+
});
|
|
104
|
+
}
|
|
98
105
|
|
|
99
106
|
// Initialize path matcher for path-expression-matcher
|
|
100
107
|
this.matcher = new Matcher();
|
|
@@ -186,9 +193,9 @@ function resolveNameSpace(tagname) {
|
|
|
186
193
|
//const attrsRegx = new RegExp("([\\w\\-\\.\\:]+)\\s*=\\s*(['\"])((.|\n)*?)\\2","gm");
|
|
187
194
|
const attrsRegx = new RegExp('([^\\s=]+)\\s*(=\\s*([\'"])([\\s\\S]*?)\\3)?', 'gm');
|
|
188
195
|
|
|
189
|
-
function buildAttributesMap(attrStr, jPath, tagName) {
|
|
196
|
+
function buildAttributesMap(attrStr, jPath, tagName, force = false) {
|
|
190
197
|
const options = this.options;
|
|
191
|
-
if (options.ignoreAttributes !== true && typeof attrStr === 'string') {
|
|
198
|
+
if (force === true || (options.ignoreAttributes !== true && typeof attrStr === 'string')) {
|
|
192
199
|
// attrStr = attrStr.replace(/\r?\n/g, ' ');
|
|
193
200
|
//attrStr = attrStr || attrStr.trim();
|
|
194
201
|
|
|
@@ -278,6 +285,7 @@ const parseXml = function (xmlData) {
|
|
|
278
285
|
|
|
279
286
|
// Reset matcher for new document
|
|
280
287
|
this.matcher.reset();
|
|
288
|
+
this.entityDecoder.reset();
|
|
281
289
|
|
|
282
290
|
// Reset entity expansion counters for this document
|
|
283
291
|
this.entityExpansionCount = 0;
|
|
@@ -331,6 +339,11 @@ const parseXml = function (xmlData) {
|
|
|
331
339
|
if (!tagData) throw new Error("Pi Tag is not closed.");
|
|
332
340
|
|
|
333
341
|
textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);
|
|
342
|
+
const attsMap = this.buildAttributesMap(tagData.tagExp, this.matcher, tagData.tagName, true);
|
|
343
|
+
if (attsMap) {
|
|
344
|
+
const ver = attsMap[this.options.attributeNamePrefix + "version"];
|
|
345
|
+
this.entityDecoder.setXmlVersion(Number(ver) || 1.0);
|
|
346
|
+
}
|
|
334
347
|
if ((options.ignoreDeclaration && tagData.tagName === "?xml") || options.ignorePiTags) {
|
|
335
348
|
//do nothing
|
|
336
349
|
} else {
|
|
@@ -338,8 +351,8 @@ const parseXml = function (xmlData) {
|
|
|
338
351
|
const childNode = new xmlNode(tagData.tagName);
|
|
339
352
|
childNode.add(options.textNodeName, "");
|
|
340
353
|
|
|
341
|
-
if (tagData.tagName !== tagData.tagExp && tagData.attrExpPresent) {
|
|
342
|
-
childNode[":@"] =
|
|
354
|
+
if (tagData.tagName !== tagData.tagExp && tagData.attrExpPresent && options.ignoreAttributes !== true) {
|
|
355
|
+
childNode[":@"] = attsMap
|
|
343
356
|
}
|
|
344
357
|
this.addChild(currentNode, childNode, this.readonlyMatcher, i);
|
|
345
358
|
}
|
|
@@ -361,7 +374,7 @@ const parseXml = function (xmlData) {
|
|
|
361
374
|
} else if (c1 === 33
|
|
362
375
|
&& xmlData.charCodeAt(i + 2) === 68) { //'!D'
|
|
363
376
|
const result = docTypeReader.readDocType(xmlData, i);
|
|
364
|
-
this.
|
|
377
|
+
this.entityDecoder.addInputEntities(result.entities);
|
|
365
378
|
i = result.i;
|
|
366
379
|
} else if (c1 === 33
|
|
367
380
|
&& xmlData.charCodeAt(i + 2) === 91) { // '!['
|
|
@@ -460,6 +473,7 @@ const parseXml = function (xmlData) {
|
|
|
460
473
|
|
|
461
474
|
if (prefixedAttrs) {
|
|
462
475
|
// Extract raw attributes (without prefix) for our use
|
|
476
|
+
//TODO: seems a performance overhead
|
|
463
477
|
rawAttrs = extractRawAttributes(prefixedAttrs, options);
|
|
464
478
|
}
|
|
465
479
|
}
|
|
@@ -602,7 +616,7 @@ function replaceEntitiesValue(val, tagName, jPath) {
|
|
|
602
616
|
}
|
|
603
617
|
}
|
|
604
618
|
|
|
605
|
-
return this.
|
|
619
|
+
return this.entityDecoder.decode(val);
|
|
606
620
|
}
|
|
607
621
|
|
|
608
622
|
|
|
@@ -32,7 +32,7 @@ export default class XMLParser {
|
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
const orderedObjParser = new OrderedObjParser(this.options);
|
|
35
|
-
orderedObjParser.
|
|
35
|
+
orderedObjParser.entityDecoder.setExternalEntities(this.externalEntities);
|
|
36
36
|
const orderedResult = orderedObjParser.parseXml(xmlData);
|
|
37
37
|
if (this.options.preserveOrder || orderedResult === undefined) return orderedResult;
|
|
38
38
|
else return prettify(orderedResult, this.options, orderedObjParser.matcher, orderedObjParser.readonlyMatcher);
|
package/src/fast-xml-parser.zip
DELETED
|
Binary file
|