fast-xml-parser 4.1.0 → 4.1.2

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,9 @@
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.1.1 / 2023-02-03**
4
+ * Fix #540: ignoreAttributes breaks unpairedTags
5
+ * Refactor XML builder code
6
+
3
7
  **4.1.0 / 2023-02-02**
4
8
  * Fix '<' or '>' in DTD comment throwing an error. (#533) (By [Adam Baker](https://github.com/Cwazywierdo))
5
9
  * Set "eNotation" to 'true' as default
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fast-xml-parser",
3
- "version": "4.1.0",
3
+ "version": "4.1.2",
4
4
  "description": "Validate XML, Parse XML, Build XML without C/C++ based libraries",
5
5
  "main": "./src/fxp.js",
6
6
  "scripts": {
@@ -59,20 +59,6 @@ function Builder(options) {
59
59
  this.tagEndChar = '>';
60
60
  this.newLine = '';
61
61
  }
62
-
63
- if (this.options.suppressEmptyNode) {
64
- this.buildTextNode = buildEmptyTextNode;
65
- this.buildObjNode = buildEmptyObjNode;
66
- } else {
67
- this.buildTextNode = buildTextValNode;
68
- this.buildObjNode = buildObjectNode;
69
- }
70
-
71
- this.buildTextValNode = buildTextValNode;
72
- this.buildObjectNode = buildObjectNode;
73
-
74
- this.replaceEntitiesValue = replaceEntitiesValue;
75
- this.buildAttrPairStr = buildAttrPairStr;
76
62
  }
77
63
 
78
64
  Builder.prototype.build = function(jObj) {
@@ -99,7 +85,7 @@ Builder.prototype.j2x = function(jObj, level) {
99
85
  else val += this.indentate(level) + '<' + key + '/' + this.tagEndChar;
100
86
  // val += this.indentate(level) + '<' + key + '/' + this.tagEndChar;
101
87
  } else if (jObj[key] instanceof Date) {
102
- val += this.buildTextNode(jObj[key], key, '', level);
88
+ val += this.buildTextValNode(jObj[key], key, '', level);
103
89
  } else if (typeof jObj[key] !== 'object') {
104
90
  //premitive type
105
91
  const attr = this.isAttribute(key);
@@ -111,7 +97,7 @@ Builder.prototype.j2x = function(jObj, level) {
111
97
  let newval = this.options.tagValueProcessor(key, '' + jObj[key]);
112
98
  val += this.replaceEntitiesValue(newval);
113
99
  } else {
114
- val += this.buildTextNode(jObj[key], key, '', level);
100
+ val += this.buildTextValNode(jObj[key], key, '', level);
115
101
  }
116
102
  }
117
103
  } else if (Array.isArray(jObj[key])) {
@@ -128,7 +114,7 @@ Builder.prototype.j2x = function(jObj, level) {
128
114
  } else if (typeof item === 'object') {
129
115
  val += this.processTextOrObjNode(item, key, level)
130
116
  } else {
131
- val += this.buildTextNode(item, key, '', level);
117
+ val += this.buildTextValNode(item, key, '', level);
132
118
  }
133
119
  }
134
120
  } else {
@@ -147,7 +133,7 @@ Builder.prototype.j2x = function(jObj, level) {
147
133
  return {attrStr: attrStr, val: val};
148
134
  };
149
135
 
150
- function buildAttrPairStr(attrName, val){
136
+ Builder.prototype.buildAttrPairStr = function(attrName, val){
151
137
  val = this.options.attributeValueProcessor(attrName, '' + val);
152
138
  val = this.replaceEntitiesValue(val);
153
139
  if (this.options.suppressBooleanAttributes && val === "true") {
@@ -158,31 +144,51 @@ function buildAttrPairStr(attrName, val){
158
144
  function processTextOrObjNode (object, key, level) {
159
145
  const result = this.j2x(object, level + 1);
160
146
  if (object[this.options.textNodeName] !== undefined && Object.keys(object).length === 1) {
161
- return this.buildTextNode(object[this.options.textNodeName], key, result.attrStr, level);
147
+ return this.buildTextValNode(object[this.options.textNodeName], key, result.attrStr, level);
162
148
  } else {
163
- return this.buildObjNode(result.val, key, result.attrStr, level);
149
+ return this.buildObjectNode(result.val, key, result.attrStr, level);
164
150
  }
165
151
  }
166
152
 
167
- function buildObjectNode(val, key, attrStr, level) {
168
- let tagEndExp = '</' + key + this.tagEndChar;
169
- let piClosingChar = "";
153
+ Builder.prototype.buildObjectNode = function(val, key, attrStr, level) {
154
+ if(val === ""){
155
+ if(key[0] === "?") return this.indentate(level) + '<' + key + attrStr+ '?' + this.tagEndChar;
156
+ else {
157
+ return this.indentate(level) + '<' + key + attrStr + this.closeTag(key) + this.tagEndChar;
158
+ }
159
+ }else{
160
+
161
+ let tagEndExp = '</' + key + this.tagEndChar;
162
+ let piClosingChar = "";
163
+
164
+ if(key[0] === "?") {
165
+ piClosingChar = "?";
166
+ tagEndExp = "";
167
+ }
170
168
 
171
- if(key[0] === "?") {
172
- piClosingChar = "?";
173
- tagEndExp = "";
169
+ if (attrStr && val.indexOf('<') === -1) {
170
+ return ( this.indentate(level) + '<' + key + attrStr + piClosingChar + '>' + val + tagEndExp );
171
+ } else if (this.options.commentPropName !== false && key === this.options.commentPropName && piClosingChar.length === 0) {
172
+ return this.indentate(level) + `<!--${val}-->` + this.newLine;
173
+ }else {
174
+ return (
175
+ this.indentate(level) + '<' + key + attrStr + piClosingChar + this.tagEndChar +
176
+ val +
177
+ this.indentate(level) + tagEndExp );
178
+ }
174
179
  }
180
+ }
175
181
 
176
- if (attrStr && val.indexOf('<') === -1) {
177
- return ( this.indentate(level) + '<' + key + attrStr + piClosingChar + '>' + val + tagEndExp );
178
- } else if (this.options.commentPropName !== false && key === this.options.commentPropName && piClosingChar.length === 0) {
179
- return this.indentate(level) + `<!--${val}-->` + this.newLine;
180
- }else {
181
- return (
182
- this.indentate(level) + '<' + key + attrStr + piClosingChar + this.tagEndChar +
183
- val +
184
- this.indentate(level) + tagEndExp );
182
+ Builder.prototype.closeTag = function(key){
183
+ let closeTag = "";
184
+ if(this.options.unpairedTags.indexOf(key) !== -1){ //unpaired
185
+ if(!this.options.suppressUnpairedNode) closeTag = "/"
186
+ }else if(this.options.suppressEmptyNode){ //empty
187
+ closeTag = "/";
188
+ }else{
189
+ closeTag = `></${key}`
185
190
  }
191
+ return closeTag;
186
192
  }
187
193
 
188
194
  function buildEmptyObjNode(val, key, attrStr, level) {
@@ -190,36 +196,35 @@ function buildEmptyObjNode(val, key, attrStr, level) {
190
196
  return this.buildObjectNode(val, key, attrStr, level);
191
197
  } else {
192
198
  if(key[0] === "?") return this.indentate(level) + '<' + key + attrStr+ '?' + this.tagEndChar;
193
- else return this.indentate(level) + '<' + key + attrStr + '/' + this.tagEndChar;
199
+ else {
200
+ return this.indentate(level) + '<' + key + attrStr + '/' + this.tagEndChar;
201
+ // return this.buildTagStr(level,key, attrStr);
202
+ }
194
203
  }
195
204
  }
196
205
 
197
- function buildTextValNode(val, key, attrStr, level) {
206
+ Builder.prototype.buildTextValNode = function(val, key, attrStr, level) {
198
207
  if (this.options.cdataPropName !== false && key === this.options.cdataPropName) {
199
208
  return this.indentate(level) + `<![CDATA[${val}]]>` + this.newLine;
200
209
  }else if (this.options.commentPropName !== false && key === this.options.commentPropName) {
201
210
  return this.indentate(level) + `<!--${val}-->` + this.newLine;
211
+ }else if(key[0] === "?") {//PI tag
212
+ return this.indentate(level) + '<' + key + attrStr+ '?' + this.tagEndChar;
202
213
  }else{
203
214
  let textValue = this.options.tagValueProcessor(key, val);
204
215
  textValue = this.replaceEntitiesValue(textValue);
205
216
 
206
- if( textValue === '' && this.options.unpairedTags.indexOf(key) !== -1){ //unpaired
207
- if(this.options.suppressUnpairedNode){
208
- return this.indentate(level) + '<' + key + this.tagEndChar;
209
- }else{
210
- return this.indentate(level) + '<' + key + "/" + this.tagEndChar;
211
- }
212
- } else{
213
- return (
214
- this.indentate(level) + '<' + key + attrStr + '>' +
217
+ if( textValue === ''){
218
+ return this.indentate(level) + '<' + key + attrStr + this.closeTag(key) + this.tagEndChar;
219
+ }else{
220
+ return this.indentate(level) + '<' + key + attrStr + '>' +
215
221
  textValue +
216
- '</' + key + this.tagEndChar );
222
+ '</' + key + this.tagEndChar;
217
223
  }
218
-
219
224
  }
220
225
  }
221
226
 
222
- function replaceEntitiesValue(textValue){
227
+ Builder.prototype.replaceEntitiesValue = function(textValue){
223
228
  if(textValue && textValue.length > 0 && this.options.processEntities){
224
229
  for (let i=0; i<this.options.entities.length; i++) {
225
230
  const entity = this.options.entities[i];
@@ -229,21 +234,6 @@ function replaceEntitiesValue(textValue){
229
234
  return textValue;
230
235
  }
231
236
 
232
- function buildEmptyTextNode(val, key, attrStr, level) {
233
- if( val === '' && this.options.unpairedTags.indexOf(key) !== -1){ //unpaired
234
- if(this.options.suppressUnpairedNode){
235
- return this.indentate(level) + '<' + key + this.tagEndChar;
236
- }else{
237
- return this.indentate(level) + '<' + key + "/" + this.tagEndChar;
238
- }
239
- }else if (val !== '') { //empty
240
- return this.buildTextValNode(val, key, attrStr, level);
241
- } else {
242
- if(key[0] === "?") return this.indentate(level) + '<' + key + attrStr+ '?' + this.tagEndChar; //PI tag
243
- else return this.indentate(level) + '<' + key + attrStr + '/' + this.tagEndChar; //normal
244
- }
245
- }
246
-
247
237
  function indentate(level) {
248
238
  return this.options.indentBy.repeat(level);
249
239
  }
@@ -137,6 +137,7 @@ function buildAttributesMap(attrStr, jPath) {
137
137
  if (this.options.transformAttributeName) {
138
138
  aName = this.options.transformAttributeName(aName);
139
139
  }
140
+ if(aName === "__proto__") aName = "#__proto__";
140
141
  if (oldVal !== undefined) {
141
142
  if (this.options.trimValues) {
142
143
  oldVal = oldVal.trim();
@@ -8,9 +8,11 @@ class XmlNode{
8
8
  }
9
9
  add(key,val){
10
10
  // this.child.push( {name : key, val: val, isCdata: isCdata });
11
+ if(key === "__proto__") key = "#__proto__";
11
12
  this.child.push( {[key]: val });
12
13
  }
13
14
  addChild(node) {
15
+ if(node.tagname === "__proto__") node.tagname = "#__proto__";
14
16
  if(node[":@"] && Object.keys(node[":@"]).length > 0){
15
17
  this.child.push( { [node.tagname]: node.child, [":@"]: node[":@"] });
16
18
  }else{