fast-xml-parser 4.1.4 → 4.2.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,9 +1,12 @@
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.2.0 / 2023-04-09**
4
+ * support `updateTag` parser property
5
+
3
6
  **4.1.4 / 2023-04-08**
4
7
  * update typings to let user create XMLBuilder instance without options (#556) (By [Patrick](https://github.com/omggga))
5
8
  * fix: IsArray option isn't parsing tags with 0 as value correctly #490 (#557) (By [Aleksandr Murashkin](https://github.com/p-kuen))
6
- * feature: support oneListGroup to group repeated children tags udder single group
9
+ * feature: support `oneListGroup` to group repeated children tags udder single group
7
10
 
8
11
  **4.1.3 / 2023-02-26**
9
12
  * fix #546: Support complex entity value
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fast-xml-parser",
3
- "version": "4.1.4",
3
+ "version": "4.2.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
@@ -32,6 +32,14 @@ Control how tag value should be parsed. Called only if tag value is not empty
32
32
  ignorePiTags: boolean;
33
33
  transformTagName: ((tagName: string) => string) | false;
34
34
  transformAttributeName: ((attributeName: string) => string) | false;
35
+ /**
36
+ Change the tag name when a different name is returned. Skip the tag from parsed result when false is returned.
37
+ Modify `attrs` object to control attributes for the given tag.
38
+
39
+ @returns {string} new tag name.
40
+ @returns false to skip the tag
41
+ */
42
+ updateTag: (tagName: string, jPath: string, attrs: {[k: string]: string}) => string | boolean;
35
43
  };
36
44
  type strnumOptions = {
37
45
  hex: boolean;
@@ -34,6 +34,10 @@ const defaultOptions = {
34
34
  ignorePiTags: false,
35
35
  transformTagName: false,
36
36
  transformAttributeName: false,
37
+ updateTag: function(tagName, jPath, attrs){
38
+ return tagName
39
+ },
40
+ // skipEmptyListItem: false
37
41
  };
38
42
 
39
43
  const buildOptions = function(options) {
@@ -50,6 +50,7 @@ class OrderedObjParser{
50
50
  this.replaceEntitiesValue = replaceEntitiesValue;
51
51
  this.readStopNodeData = readStopNodeData;
52
52
  this.saveTextToParentTag = saveTextToParentTag;
53
+ this.addChild = addChild;
53
54
  }
54
55
 
55
56
  }
@@ -121,7 +122,7 @@ function resolveNameSpace(tagname) {
121
122
  //const attrsRegx = new RegExp("([\\w\\-\\.\\:]+)\\s*=\\s*(['\"])((.|\n)*?)\\2","gm");
122
123
  const attrsRegx = new RegExp('([^\\s=]+)\\s*(=\\s*([\'"])([\\s\\S]*?)\\3)?', 'gm');
123
124
 
124
- function buildAttributesMap(attrStr, jPath) {
125
+ function buildAttributesMap(attrStr, jPath, tagName) {
125
126
  if (!this.options.ignoreAttributes && typeof attrStr === 'string') {
126
127
  // attrStr = attrStr.replace(/\r?\n/g, ' ');
127
128
  //attrStr = attrStr || attrStr.trim();
@@ -171,7 +172,7 @@ function buildAttributesMap(attrStr, jPath) {
171
172
  attrCollection[this.options.attributesGroupName] = attrs;
172
173
  return attrCollection;
173
174
  }
174
- return attrs;
175
+ return attrs
175
176
  }
176
177
  }
177
178
 
@@ -207,7 +208,7 @@ const parseXml = function(xmlData) {
207
208
 
208
209
  jPath = jPath.substr(0, jPath.lastIndexOf("."));
209
210
 
210
- currentNode = this.tagsNodeStack.pop();//avoid recurssion, set the parent tag scope
211
+ currentNode = this.tagsNodeStack.pop();//avoid recursion, set the parent tag scope
211
212
  textData = "";
212
213
  i = closeIndex;
213
214
  } else if( xmlData[i+1] === '?') {
@@ -224,9 +225,9 @@ const parseXml = function(xmlData) {
224
225
  childNode.add(this.options.textNodeName, "");
225
226
 
226
227
  if(tagData.tagName !== tagData.tagExp && tagData.attrExpPresent){
227
- childNode[":@"] = this.buildAttributesMap(tagData.tagExp, jPath);
228
+ childNode[":@"] = this.buildAttributesMap(tagData.tagExp, jPath, tagData.tagName);
228
229
  }
229
- currentNode.addChild(childNode);
230
+ this.addChild(currentNode, childNode, jPath)
230
231
 
231
232
  }
232
233
 
@@ -314,7 +315,7 @@ const parseXml = function(xmlData) {
314
315
 
315
316
  const childNode = new xmlNode(tagName);
316
317
  if(tagName !== tagExp && attrExpPresent){
317
- childNode[":@"] = this.buildAttributesMap(tagExp, jPath);
318
+ childNode[":@"] = this.buildAttributesMap(tagExp, jPath, tagName);
318
319
  }
319
320
  if(tagContent) {
320
321
  tagContent = this.parseTextData(tagContent, tagName, jPath, true, attrExpPresent, true, true);
@@ -323,7 +324,7 @@ const parseXml = function(xmlData) {
323
324
  jPath = jPath.substr(0, jPath.lastIndexOf("."));
324
325
  childNode.add(this.options.textNodeName, tagContent);
325
326
 
326
- currentNode.addChild(childNode);
327
+ this.addChild(currentNode, childNode, jPath)
327
328
  }else{
328
329
  //selfClosing tag
329
330
  if(tagExp.length > 0 && tagExp.lastIndexOf("/") === tagExp.length - 1){
@@ -340,10 +341,10 @@ const parseXml = function(xmlData) {
340
341
 
341
342
  const childNode = new xmlNode(tagName);
342
343
  if(tagName !== tagExp && attrExpPresent){
343
- childNode[":@"] = this.buildAttributesMap(tagExp, jPath);
344
+ childNode[":@"] = this.buildAttributesMap(tagExp, jPath, tagName);
344
345
  }
345
346
  jPath = jPath.substr(0, jPath.lastIndexOf("."));
346
- currentNode.addChild(childNode);
347
+ this.addChild(currentNode, childNode, jPath)
347
348
  }
348
349
  //opening tag
349
350
  else{
@@ -351,9 +352,9 @@ const parseXml = function(xmlData) {
351
352
  this.tagsNodeStack.push(currentNode);
352
353
 
353
354
  if(tagName !== tagExp && attrExpPresent){
354
- childNode[":@"] = this.buildAttributesMap(tagExp, jPath);
355
+ childNode[":@"] = this.buildAttributesMap(tagExp, jPath, tagName);
355
356
  }
356
- currentNode.addChild(childNode);
357
+ this.addChild(currentNode, childNode, jPath)
357
358
  currentNode = childNode;
358
359
  }
359
360
  textData = "";
@@ -367,6 +368,17 @@ const parseXml = function(xmlData) {
367
368
  return xmlObj.child;
368
369
  }
369
370
 
371
+ function addChild(currentNode, childNode, jPath){
372
+ const result = this.options.updateTag(childNode.tagname, jPath, childNode[":@"])
373
+ if(result === false){
374
+ }else if(typeof result === "string"){
375
+ childNode.tagname = result
376
+ currentNode.addChild(childNode);
377
+ }else{
378
+ currentNode.addChild(childNode);
379
+ }
380
+ }
381
+
370
382
  const replaceEntitiesValue = function(val){
371
383
 
372
384
  if(this.options.processEntities){
@@ -423,7 +435,7 @@ function isItStopNode(stopNodes, jPath, currentTagName){
423
435
  }
424
436
 
425
437
  /**
426
- * Returns the tag Expression and where it is ending handling single-dobule quotes situation
438
+ * Returns the tag Expression and where it is ending handling single-double quotes situation
427
439
  * @param {string} xmlData
428
440
  * @param {number} i starting index
429
441
  * @returns