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 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.2",
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": "nyc --reporter=lcov --reporter=text jasmine spec/*spec.js",
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
- "type": "github",
65
- "url": "https://github.com/sponsors/NaturalIntelligence"
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 X2jOptions = {
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 tag value with `strnum` package
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}) => string | boolean;
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
- type strnumOptions = {
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 | Buffer ,validationOptions?: validationOptions | boolean): any;
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( xmlData: string, options?: validationOptions): true | ValidationError;
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): 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(!obj.hasOwnProperty(key)) continue;
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(!attrMap.hasOwnProperty(attr)) continue;
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) {