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 +10 -1
- package/README.md +20 -10
- package/package.json +1 -1
- package/src/fxp.d.ts +4 -2
- package/src/xmlbuilder/json2xml.js +16 -5
- package/src/xmlbuilder/orderedJs2Xml.js +4 -0
- package/src/xmlparser/OrderedObjParser.js +6 -3
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
|
-
[](https://snyk.io/test/github/naturalintelligence/fast-xml-parser)
|
|
3
3
|
[![NPM quality][quality-image]][quality-url]
|
|
4
4
|
[](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
|
-
>
|
|
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
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
|
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
|
-
|
|
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
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):
|
|
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:
|
|
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
|
-
|
|
86
|
-
|
|
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
|
-
|
|
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)) {
|
|
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,
|
|
322
|
-
if(!result) throw new Error(`Unexpected end of ${
|
|
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
|
/**
|