fast-xml-parser 4.2.6 → 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/CHANGELOG.md CHANGED
@@ -1,7 +1,16 @@
1
1
  Note: If you find missing information about particular minor version, that version must have been changed without any functional change in this library.
2
2
 
3
+ **4.3.0 / 2023-09-20**
4
+ * Fix stopNodes to work with removeNSPrefix (#607) (#608) (By [Craig Andrews]https://github.com/candrews))
5
+ * Fix #610 ignore properties set to Object.prototype
6
+ * Fix typings for builder and parser to make return type generic (By [Sarah Dayan](https://github.com/sarahdayan))
7
+
8
+ **4.2.7 / 2023-07-30**
9
+ * Fix: builder should set text node correctly when only textnode is present (#589) (By [qianqing](https://github.com/joneqian))
10
+ * Fix: Fix for null and undefined attributes when building xml (#585) (#598). A null or undefined value should be ignored. (By [Eugenio Ceschia](https://github.com/cecia234))
11
+
3
12
  **4.2.6 / 2023-07-17**
4
- * Remove trailing slash from jPath for self-closing tags (#595) (By [Maciej Radzikowski](https://github.com/m-radzikowski))
13
+ * Fix: Remove trailing slash from jPath for self-closing tags (#595) (By [Maciej Radzikowski](https://github.com/m-radzikowski))
5
14
 
6
15
  **4.2.5 / 2023-06-22**
7
16
  * change code implementation
package/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  # [fast-xml-parser](https://www.npmjs.com/package/fast-xml-parser)
2
- [![Backers on Open Collective](https://opencollective.com/fast-xml-parser/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/fast-xml-parser/sponsors/badge.svg)](#sponsors) [![Known Vulnerabilities](https://snyk.io/test/github/naturalintelligence/fast-xml-parser/badge.svg)](https://snyk.io/test/github/naturalintelligence/fast-xml-parser)
2
+ [![Known Vulnerabilities](https://snyk.io/test/github/naturalintelligence/fast-xml-parser/badge.svg)](https://snyk.io/test/github/naturalintelligence/fast-xml-parser)
3
3
  [![NPM quality][quality-image]][quality-url]
4
4
  [![Coverage Status](https://coveralls.io/repos/github/NaturalIntelligence/fast-xml-parser/badge.svg?branch=master)](https://coveralls.io/github/NaturalIntelligence/fast-xml-parser?branch=master)
5
5
  [<img src="https://img.shields.io/badge/Try-me-blue.svg?colorA=FFA500&colorB=0000FF" alt="Try me"/>](https://naturalintelligence.github.io/fast-xml-parser/)
@@ -11,20 +11,28 @@
11
11
 
12
12
  Validate XML, Parse XML to JS Object, or Build XML from JS Object without C/C++ based libraries and no callback.
13
13
 
14
- > Looking for maintainers
14
+ <font size="6">I need a Career advice. I've posted the query on my <a href="github.com/amitguptagwl">profile</a>. Your support would be appreciable.</font>
15
15
 
16
- Support this project by becoming a **Sponsor**.
17
-
18
- Click on Sponsor button above or
16
+ Sponsor this project 👉
17
+ <a href="https://github.com/sponsors/NaturalIntelligence">
18
+ <img src="https://raw.githubusercontent.com/NaturalIntelligence/ThankYouBackers/main/github_sponsor.png" width="200" />
19
+ </a>
19
20
  <a href="https://opencollective.com/fast-xml-parser/donate" target="_blank">
20
21
  <img src="https://opencollective.com/fast-xml-parser/donate/button@2x.png?color=blue" width=200 />
21
22
  </a>
22
23
  <a href="https://paypal.me/naturalintelligence"> <img src="static/img/support_paypal.svg" alt="Stubmatic donate button" width="200"/></a>
23
24
 
24
25
 
25
- ### Sponsors
26
+ ### Current Sponsors
27
+
28
+ Check the complete list at [ThankYouBackers](https://github.com/NaturalIntelligence/ThankYouBackers) for our sponsors and supporters.
29
+
30
+ Through Github
26
31
 
27
32
  <a href="https://github.com/getsentry" target="_blank"><img src="https://user-images.githubusercontent.com/7692328/204701653-ce369b29-6fdb-48f2-9848-593d04628a2b.png" width="60px"></a>
33
+
34
+ Through OpenCollective
35
+
28
36
  <a href="https://opencollective.com/fast-xml-parser/sponsor/0/website" target="_blank"><img src="https://opencollective.com/fast-xml-parser/sponsor/0/avatar.svg"></a>
29
37
  <a href="https://opencollective.com/fast-xml-parser/sponsor/1/website" target="_blank"><img src="https://opencollective.com/fast-xml-parser/sponsor/1/avatar.svg"></a>
30
38
  <a href="https://opencollective.com/fast-xml-parser/sponsor/2/website" target="_blank"><img src="https://opencollective.com/fast-xml-parser/sponsor/2/avatar.svg"></a>
@@ -37,8 +45,6 @@ Click on Sponsor button above or
37
45
  <a href="https://opencollective.com/fast-xml-parser/sponsor/9/website" target="_blank"><img src="https://opencollective.com/fast-xml-parser/sponsor/9/avatar.svg"></a>
38
46
 
39
47
 
40
- Check [ThankYouBackers](https://github.com/NaturalIntelligence/ThankYouBackers) for our supporters
41
-
42
48
  ## Users
43
49
 
44
50
  <a href="https://github.com/renovatebot/renovate" title="renovate" ><img src="https://avatars1.githubusercontent.com/u/38656520" width="60px" ></a>
@@ -56,9 +62,13 @@ Check [ThankYouBackers](https://github.com/NaturalIntelligence/ThankYouBackers)
56
62
  <a href="https://github.com/postmanlabs" title="postman" > <img src="https://user-images.githubusercontent.com/7692328/204835529-e9e290ad-696a-49ad-9d34-08e955704715.png" width="60px" ></a>
57
63
  <a href="https://github.com/react-native-community" title="React Native Community" > <img src="https://avatars.githubusercontent.com/u/20269980?v=4" width="60px" ></a>
58
64
 
59
- Check the list of all known users [here](./USERs.md);
65
+ Check the bigger [list](./USERs.md)
66
+
67
+ <small>The list of users is collected either from the list published by Github, communicated directly through mails/chat , or from other resources. If you feel that your name in the above list is incorrectly published or you're not the user of this library anymore then you can inform us to remove it. We'll do the necessary changes ASAP.</small>
60
68
 
61
- <small>The list of users is collected either from the list published by Github, cummunicated directly through mails/chat , or from other resources. If you feel that your name in the above list is incorrectly published or you're not the user of this library anymore then you can inform us to remove it. We'll do the necessary changes ASAP.</small>
69
+ If you want to be an anonymous user of this application and don't want to be highlighted anywhere then you can contact me at
70
+ - githubissues@proton.me
71
+ - https://linkedin.com/in/amitguptagwl/
62
72
 
63
73
  ## Main Features
64
74
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fast-xml-parser",
3
- "version": "4.2.6",
3
+ "version": "4.3.0",
4
4
  "description": "Validate XML, Parse XML, Build XML without C/C++ based libraries",
5
5
  "main": "./src/fxp.js",
6
6
  "scripts": {
package/src/fxp.d.ts CHANGED
@@ -88,9 +88,11 @@ type ValidationError = {
88
88
  };
89
89
  };
90
90
 
91
+ type GenericObjectOrArray<TValue> = Record<string, unknown> | TValue[];
92
+
91
93
  export class XMLParser {
92
94
  constructor(options?: X2jOptionsOptional);
93
- parse(xmlData: string | Buffer ,validationOptions?: validationOptionsOptional | boolean): any;
95
+ parse<TObject extends GenericObjectOrArray<unknown> = GenericObjectOrArray<unknown>>(xmlData: string | Buffer ,validationOptions?: validationOptionsOptional | boolean): TObject;
94
96
  /**
95
97
  * Add Entity which is not by default supported by this library
96
98
  * @param entityIndentifier {string} Eg: 'ent' for &ent;
@@ -104,5 +106,5 @@ export class XMLValidator{
104
106
  }
105
107
  export class XMLBuilder {
106
108
  constructor(options?: XmlBuilderOptionsOptional);
107
- build(jObj: any): any;
109
+ build<TObject extends GenericObjectOrArray<unknown> = GenericObjectOrArray<unknown>>(jObj: TObject): string;
108
110
  }
@@ -79,11 +79,21 @@ Builder.prototype.j2x = function(jObj, level) {
79
79
  let attrStr = '';
80
80
  let val = '';
81
81
  for (let key in jObj) {
82
+ if(!jObj.hasOwnProperty(key)) continue;
82
83
  if (typeof jObj[key] === 'undefined') {
83
- // supress undefined node
84
+ // supress undefined node only if it is not an attribute
85
+ if (this.isAttribute(key)) {
86
+ val += '';
87
+ }
84
88
  } else if (jObj[key] === null) {
85
- if(key[0] === "?") val += this.indentate(level) + '<' + key + '?' + this.tagEndChar;
86
- else val += this.indentate(level) + '<' + key + '/' + this.tagEndChar;
89
+ // null attribute should be ignored by the attribute list, but should not cause the tag closing
90
+ if (this.isAttribute(key)) {
91
+ val += '';
92
+ } else if (key[0] === '?') {
93
+ val += this.indentate(level) + '<' + key + '?' + this.tagEndChar;
94
+ } else {
95
+ val += this.indentate(level) + '<' + key + '/' + this.tagEndChar;
96
+ }
87
97
  // val += this.indentate(level) + '<' + key + '/' + this.tagEndChar;
88
98
  } else if (jObj[key] instanceof Date) {
89
99
  val += this.buildTextValNode(jObj[key], key, '', level);
@@ -176,7 +186,8 @@ Builder.prototype.buildObjectNode = function(val, key, attrStr, level) {
176
186
  tagEndExp = "";
177
187
  }
178
188
 
179
- if (attrStr && val.indexOf('<') === -1) {
189
+ // attrStr is an empty string in case the attribute came as undefined or null
190
+ if ((attrStr || attrStr === '') && val.indexOf('<') === -1) {
180
191
  return ( this.indentate(level) + '<' + key + attrStr + piClosingChar + '>' + val + tagEndExp );
181
192
  } else if (this.options.commentPropName !== false && key === this.options.commentPropName && piClosingChar.length === 0) {
182
193
  return this.indentate(level) + `<!--${val}-->` + this.newLine;
@@ -249,7 +260,7 @@ function indentate(level) {
249
260
  }
250
261
 
251
262
  function isAttribute(name /*, options*/) {
252
- if (name.startsWith(this.options.attributeNamePrefix)) {
263
+ if (name.startsWith(this.options.attributeNamePrefix) && name !== this.options.textNodeName) {
253
264
  return name.substr(this.attrPrefixLen);
254
265
  } else {
255
266
  return false;
@@ -21,6 +21,8 @@ function arrToStr(arr, options, jPath, indentation) {
21
21
  for (let i = 0; i < arr.length; i++) {
22
22
  const tagObj = arr[i];
23
23
  const tagName = propName(tagObj);
24
+ if(tagName === undefined) continue;
25
+
24
26
  let newJPath = "";
25
27
  if (jPath.length === 0) newJPath = tagName
26
28
  else newJPath = `${jPath}.${tagName}`;
@@ -90,6 +92,7 @@ function propName(obj) {
90
92
  const keys = Object.keys(obj);
91
93
  for (let i = 0; i < keys.length; i++) {
92
94
  const key = keys[i];
95
+ if(!obj.hasOwnProperty(key)) continue;
93
96
  if (key !== ":@") return key;
94
97
  }
95
98
  }
@@ -98,6 +101,7 @@ function attr_to_str(attrMap, options) {
98
101
  let attrStr = "";
99
102
  if (attrMap && !options.ignoreAttributes) {
100
103
  for (let attr in attrMap) {
104
+ if(!attrMap.hasOwnProperty(attr)) continue;
101
105
  let attrVal = options.attributeValueProcessor(attr, attrMap[attr]);
102
106
  attrVal = replaceEntitiesValue(attrVal, options);
103
107
  if (attrVal === true && options.suppressBooleanAttributes) {
@@ -280,6 +280,7 @@ const parseXml = function(xmlData) {
280
280
  }else {//Opening tag
281
281
  let result = readTagExp(xmlData,i, this.options.removeNSPrefix);
282
282
  let tagName= result.tagName;
283
+ const rawTagName = result.rawTagName;
283
284
  let tagExp = result.tagExp;
284
285
  let attrExpPresent = result.attrExpPresent;
285
286
  let closeIndex = result.closeIndex;
@@ -305,7 +306,7 @@ const parseXml = function(xmlData) {
305
306
  if(tagName !== xmlObj.tagname){
306
307
  jPath += jPath ? "." + tagName : tagName;
307
308
  }
308
- if (this.isItStopNode(this.options.stopNodes, jPath, tagName)) { //TODO: namespace
309
+ if (this.isItStopNode(this.options.stopNodes, jPath, tagName)) {
309
310
  let tagContent = "";
310
311
  //self-closing tag
311
312
  if(tagExp.length > 0 && tagExp.lastIndexOf("/") === tagExp.length - 1){
@@ -318,8 +319,8 @@ const parseXml = function(xmlData) {
318
319
  //normal tag
319
320
  else{
320
321
  //read until closing tag is found
321
- const result = this.readStopNodeData(xmlData, tagName, closeIndex + 1);
322
- if(!result) throw new Error(`Unexpected end of ${tagName}`);
322
+ const result = this.readStopNodeData(xmlData, rawTagName, closeIndex + 1);
323
+ if(!result) throw new Error(`Unexpected end of ${rawTagName}`);
323
324
  i = result.i;
324
325
  tagContent = result.tagContent;
325
326
  }
@@ -504,6 +505,7 @@ function readTagExp(xmlData,i, removeNSPrefix, closingChar = ">"){
504
505
  tagExp = tagExp.substr(separatorIndex + 1);
505
506
  }
506
507
 
508
+ const rawTagName = tagName;
507
509
  if(removeNSPrefix){
508
510
  const colonIndex = tagName.indexOf(":");
509
511
  if(colonIndex !== -1){
@@ -517,6 +519,7 @@ function readTagExp(xmlData,i, removeNSPrefix, closingChar = ">"){
517
519
  tagExp: tagExp,
518
520
  closeIndex: closeIndex,
519
521
  attrExpPresent: attrExpPresent,
522
+ rawTagName: rawTagName,
520
523
  }
521
524
  }
522
525
  /**