fast-xml-parser 4.5.2 → 4.5.4
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/package.json +10 -9
- package/src/fxp.d.ts +102 -18
- package/src/xmlbuilder/orderedJs2Xml.js +14 -3
- package/src/xmlparser/DocTypeReader.js +377 -131
- package/src/xmlparser/OptionsBuilder.js +85 -41
- package/src/xmlparser/OrderedObjParser.js +313 -191
- package/test_output.txt +21 -0
- package/test_output_2.txt +21 -0
- package/test_output_3.txt +11 -0
- package/test_output_4.txt +26 -0
- package/test_output_5.txt +17 -0
- package/test_output_6.txt +98 -0
- package/test_output_7.txt +48 -0
- package/test_output_8.txt +30 -0
- package/test_output_9.txt +41 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
<small>Note: If you find missing information about particular minor version, that version must have been changed without any functional change in this library.</small>
|
|
2
2
|
|
|
3
|
+
**4.5.4 / 2026-02-26**
|
|
4
|
+
- support strictReservedNames
|
|
5
|
+
- support captureMetaData
|
|
6
|
+
- support maxNestedTags
|
|
7
|
+
- handle non-array input for XML builder when preserveOrder is true (By Angelo Coetzee)
|
|
8
|
+
- Improve security and performance of entity processing
|
|
9
|
+
- new options maxEntitySize, maxExpansionDepth, maxTotalExpansions, maxExpandedLength, allowedTags,tagFilter
|
|
10
|
+
- fast return when no edtity is present
|
|
11
|
+
- improvement replacement logic to reduce number of calls
|
|
12
|
+
- fix: Escape regex char in entity name
|
|
13
|
+
- fix: handle HTML numeric and hex entities when out of range
|
|
14
|
+
- fix #775: transformTagName with allowBooleanAttributes adds an unnecessary attribute
|
|
15
|
+
- Use Uint8Array in place of Buffer in Parser
|
|
16
|
+
- Support EMPTY and ANY with ELEMENT in DOCTYPE
|
|
17
|
+
- fix: support numeric entities with values over 0xFFFF (#726) (By Marc Durdin)
|
|
18
|
+
|
|
19
|
+
|
|
3
20
|
**4.5.2 / 2025-02-18**
|
|
4
21
|
- Fix null CDATA to comply with undefined behavior (#701) (By [Matthieu BOHEAS](https://github.com/Kelgors))
|
|
5
22
|
- Fix(performance): Update check for leaf node in saveTextToParentTag function in OrderedObjParser.js (#707) (By [...](https://github.com/tomingtoming))
|
package/package.json
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fast-xml-parser",
|
|
3
|
-
"version": "4.5.
|
|
3
|
+
"version": "4.5.4",
|
|
4
4
|
"description": "Validate XML, Parse XML, Build XML without C/C++ based libraries",
|
|
5
5
|
"main": "./src/fxp.js",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"test": "
|
|
7
|
+
"test": "c8 --reporter=lcov --reporter=text jasmine spec/*spec.js",
|
|
8
8
|
"test-types": "tsc --noEmit spec/typings/typings-test.ts",
|
|
9
9
|
"unit": "jasmine",
|
|
10
|
-
"coverage": "nyc report --reporter html --reporter text -t .nyc_output --report-dir .nyc_output/summary",
|
|
11
10
|
"perf": "node ./benchmark/perfTest3.js",
|
|
12
11
|
"lint": "eslint src/*.js spec/*.js",
|
|
13
12
|
"bundle": "webpack --config webpack-prod.config.js",
|
|
@@ -49,10 +48,10 @@
|
|
|
49
48
|
"@babel/register": "^7.13.8",
|
|
50
49
|
"@types/node": "20",
|
|
51
50
|
"babel-loader": "^8.2.2",
|
|
51
|
+
"c8": "^10.1.3",
|
|
52
52
|
"eslint": "^8.3.0",
|
|
53
53
|
"he": "^1.2.0",
|
|
54
54
|
"jasmine": "^3.6.4",
|
|
55
|
-
"nyc": "^15.1.0",
|
|
56
55
|
"prettier": "^1.19.1",
|
|
57
56
|
"publish-please": "^5.5.2",
|
|
58
57
|
"typescript": "5",
|
|
@@ -60,11 +59,13 @@
|
|
|
60
59
|
"webpack-cli": "^4.9.1"
|
|
61
60
|
},
|
|
62
61
|
"typings": "src/fxp.d.ts",
|
|
63
|
-
"funding": [
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
62
|
+
"funding": [
|
|
63
|
+
{
|
|
64
|
+
"type": "github",
|
|
65
|
+
"url": "https://github.com/sponsors/NaturalIntelligence"
|
|
66
|
+
}
|
|
67
|
+
],
|
|
67
68
|
"dependencies": {
|
|
68
69
|
"strnum": "^1.0.5"
|
|
69
70
|
}
|
|
70
|
-
}
|
|
71
|
+
}
|
package/src/fxp.d.ts
CHANGED
|
@@ -1,4 +1,60 @@
|
|
|
1
|
-
type
|
|
1
|
+
export type ProcessEntitiesOptions = {
|
|
2
|
+
/**
|
|
3
|
+
* Whether to enable entity processing
|
|
4
|
+
*
|
|
5
|
+
* Defaults to `true`
|
|
6
|
+
*/
|
|
7
|
+
enabled?: boolean;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Maximum size in characters for a single entity definition
|
|
11
|
+
*
|
|
12
|
+
* Defaults to `10000`
|
|
13
|
+
*/
|
|
14
|
+
maxEntitySize?: number;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Maximum depth for nested entity references (reserved for future use)
|
|
18
|
+
*
|
|
19
|
+
* Defaults to `10`
|
|
20
|
+
*/
|
|
21
|
+
maxExpansionDepth?: number;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Maximum total number of entity expansions allowed
|
|
25
|
+
*
|
|
26
|
+
* Defaults to `1000`
|
|
27
|
+
*/
|
|
28
|
+
maxTotalExpansions?: number;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Maximum total expanded content length in characters
|
|
32
|
+
*
|
|
33
|
+
* Defaults to `100000`
|
|
34
|
+
*/
|
|
35
|
+
maxExpandedLength?: number;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Array of tag names where entity replacement is allowed.
|
|
39
|
+
* If null, entities are replaced in all tags.
|
|
40
|
+
*
|
|
41
|
+
* Defaults to `null`
|
|
42
|
+
*/
|
|
43
|
+
allowedTags?: string[] | null;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Custom filter function to determine if entities should be replaced in a tag
|
|
47
|
+
*
|
|
48
|
+
* @param tagName - The name of the current tag
|
|
49
|
+
* @param jPath - The jPath of the current tag
|
|
50
|
+
* @returns `true` to allow entity replacement, `false` to skip
|
|
51
|
+
*
|
|
52
|
+
* Defaults to `null`
|
|
53
|
+
*/
|
|
54
|
+
tagFilter?: ((tagName: string, jPath: string) => boolean) | null;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export type X2jOptions = {
|
|
2
58
|
/**
|
|
3
59
|
* Preserve the order of tags in resulting JS object
|
|
4
60
|
*
|
|
@@ -10,7 +66,7 @@ type X2jOptions = {
|
|
|
10
66
|
* Give a prefix to the attribute name in the resulting JS object
|
|
11
67
|
*
|
|
12
68
|
* Defaults to '@_'
|
|
13
|
-
*/
|
|
69
|
+
*/
|
|
14
70
|
attributeNamePrefix?: string;
|
|
15
71
|
|
|
16
72
|
/**
|
|
@@ -64,7 +120,7 @@ type X2jOptions = {
|
|
|
64
120
|
parseTagValue?: boolean;
|
|
65
121
|
|
|
66
122
|
/**
|
|
67
|
-
* Whether to parse
|
|
123
|
+
* Whether to parse attribute value with `strnum` package
|
|
68
124
|
*
|
|
69
125
|
* Defaults to `false`
|
|
70
126
|
*/
|
|
@@ -161,9 +217,15 @@ type X2jOptions = {
|
|
|
161
217
|
/**
|
|
162
218
|
* Whether to process default and DOCTYPE entities
|
|
163
219
|
*
|
|
220
|
+
* When `true` - enables entity processing with default limits
|
|
221
|
+
*
|
|
222
|
+
* When `false` - disables all entity processing
|
|
223
|
+
*
|
|
224
|
+
* When `ProcessEntitiesOptions` - enables entity processing with custom configuration
|
|
225
|
+
*
|
|
164
226
|
* Defaults to `true`
|
|
165
227
|
*/
|
|
166
|
-
processEntities?: boolean;
|
|
228
|
+
processEntities?: boolean | ProcessEntitiesOptions;
|
|
167
229
|
|
|
168
230
|
/**
|
|
169
231
|
* Whether to process HTML entities
|
|
@@ -209,24 +271,46 @@ type X2jOptions = {
|
|
|
209
271
|
*
|
|
210
272
|
* Defaults to `(tagName, jPath, attrs) => tagName`
|
|
211
273
|
*/
|
|
212
|
-
updateTag?: (tagName: string, jPath: string, attrs: {[k: string]: string}) =>
|
|
274
|
+
updateTag?: (tagName: string, jPath: string, attrs: { [k: string]: string }) => string | boolean;
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* If true, adds a Symbol to all object nodes, accessible by {@link XMLParser.getMetaDataSymbol} with
|
|
278
|
+
* metadata about each the node in the XML file.
|
|
279
|
+
*/
|
|
280
|
+
captureMetaData?: boolean;
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Maximum number of nested tags
|
|
284
|
+
*
|
|
285
|
+
* Defaults to `100`
|
|
286
|
+
*/
|
|
287
|
+
maxNestedTags?: number;
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Whether to strictly validate tag names
|
|
291
|
+
*
|
|
292
|
+
* Defaults to `true`
|
|
293
|
+
*/
|
|
294
|
+
strictReservedNames?: boolean;
|
|
213
295
|
};
|
|
214
296
|
|
|
215
|
-
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
export type strnumOptions = {
|
|
216
300
|
hex: boolean;
|
|
217
301
|
leadingZeros: boolean,
|
|
218
302
|
skipLike?: RegExp,
|
|
219
303
|
eNotation?: boolean
|
|
220
304
|
}
|
|
221
305
|
|
|
222
|
-
type validationOptions = {
|
|
306
|
+
export type validationOptions = {
|
|
223
307
|
/**
|
|
224
308
|
* Whether to allow attributes without value
|
|
225
309
|
*
|
|
226
310
|
* Defaults to `false`
|
|
227
311
|
*/
|
|
228
312
|
allowBooleanAttributes?: boolean;
|
|
229
|
-
|
|
313
|
+
|
|
230
314
|
/**
|
|
231
315
|
* List of tags without closing tags
|
|
232
316
|
*
|
|
@@ -235,12 +319,12 @@ type validationOptions = {
|
|
|
235
319
|
unpairedTags?: string[];
|
|
236
320
|
};
|
|
237
321
|
|
|
238
|
-
type XmlBuilderOptions = {
|
|
322
|
+
export type XmlBuilderOptions = {
|
|
239
323
|
/**
|
|
240
324
|
* Give a prefix to the attribute name in the resulting JS object
|
|
241
325
|
*
|
|
242
326
|
* Defaults to '@_'
|
|
243
|
-
*/
|
|
327
|
+
*/
|
|
244
328
|
attributeNamePrefix?: string;
|
|
245
329
|
|
|
246
330
|
/**
|
|
@@ -387,20 +471,20 @@ type XmlBuilderOptions = {
|
|
|
387
471
|
oneListGroup?: boolean;
|
|
388
472
|
};
|
|
389
473
|
|
|
390
|
-
type ESchema = string | object | Array<string|object>;
|
|
474
|
+
type ESchema = string | object | Array<string | object>;
|
|
391
475
|
|
|
392
|
-
type ValidationError = {
|
|
393
|
-
err: {
|
|
476
|
+
export type ValidationError = {
|
|
477
|
+
err: {
|
|
394
478
|
code: string;
|
|
395
479
|
msg: string,
|
|
396
480
|
line: number,
|
|
397
|
-
col: number
|
|
481
|
+
col: number
|
|
398
482
|
};
|
|
399
483
|
};
|
|
400
484
|
|
|
401
485
|
export class XMLParser {
|
|
402
486
|
constructor(options?: X2jOptions);
|
|
403
|
-
parse(xmlData: string |
|
|
487
|
+
parse(xmlData: string | Uint8Array, validationOptions?: validationOptions | boolean): any;
|
|
404
488
|
/**
|
|
405
489
|
* Add Entity which is not by default supported by this library
|
|
406
490
|
* @param entityIdentifier {string} Eg: 'ent' for &ent;
|
|
@@ -409,10 +493,10 @@ export class XMLParser {
|
|
|
409
493
|
addEntity(entityIdentifier: string, entityValue: string): void;
|
|
410
494
|
}
|
|
411
495
|
|
|
412
|
-
export class XMLValidator{
|
|
413
|
-
static validate(
|
|
496
|
+
export class XMLValidator {
|
|
497
|
+
static validate(xmlData: string, options?: validationOptions): true | ValidationError;
|
|
414
498
|
}
|
|
415
499
|
export class XMLBuilder {
|
|
416
500
|
constructor(options?: XmlBuilderOptions);
|
|
417
|
-
build(jObj: any):
|
|
501
|
+
build(jObj: any): string;
|
|
418
502
|
}
|
|
@@ -18,10 +18,21 @@ function arrToStr(arr, options, jPath, indentation) {
|
|
|
18
18
|
let xmlStr = "";
|
|
19
19
|
let isPreviousElementTag = false;
|
|
20
20
|
|
|
21
|
+
|
|
22
|
+
if (!Array.isArray(arr)) {
|
|
23
|
+
// Non-array values (e.g. string tag values) should be treated as text content
|
|
24
|
+
if (arr !== undefined && arr !== null) {
|
|
25
|
+
let text = arr.toString();
|
|
26
|
+
text = replaceEntitiesValue(text, options);
|
|
27
|
+
return text;
|
|
28
|
+
}
|
|
29
|
+
return "";
|
|
30
|
+
}
|
|
31
|
+
|
|
21
32
|
for (let i = 0; i < arr.length; i++) {
|
|
22
33
|
const tagObj = arr[i];
|
|
23
34
|
const tagName = propName(tagObj);
|
|
24
|
-
if(tagName === undefined) continue;
|
|
35
|
+
if (tagName === undefined) continue;
|
|
25
36
|
|
|
26
37
|
let newJPath = "";
|
|
27
38
|
if (jPath.length === 0) newJPath = tagName
|
|
@@ -92,7 +103,7 @@ function propName(obj) {
|
|
|
92
103
|
const keys = Object.keys(obj);
|
|
93
104
|
for (let i = 0; i < keys.length; i++) {
|
|
94
105
|
const key = keys[i];
|
|
95
|
-
if(!
|
|
106
|
+
if (!Object.prototype.hasOwnProperty.call(obj, key)) continue;
|
|
96
107
|
if (key !== ":@") return key;
|
|
97
108
|
}
|
|
98
109
|
}
|
|
@@ -101,7 +112,7 @@ function attr_to_str(attrMap, options) {
|
|
|
101
112
|
let attrStr = "";
|
|
102
113
|
if (attrMap && !options.ignoreAttributes) {
|
|
103
114
|
for (let attr in attrMap) {
|
|
104
|
-
if(!
|
|
115
|
+
if (!Object.prototype.hasOwnProperty.call(attrMap, attr)) continue;
|
|
105
116
|
let attrVal = options.attributeValueProcessor(attr, attrMap[attr]);
|
|
106
117
|
attrVal = replaceEntitiesValue(attrVal, options);
|
|
107
118
|
if (attrVal === true && options.suppressBooleanAttributes) {
|