fast-xml-parser 4.1.4 → 4.2.1
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 +7 -1
- package/package.json +1 -1
- package/src/fxp.d.ts +8 -0
- package/src/xmlparser/OptionsBuilder.js +4 -0
- package/src/xmlparser/OrderedObjParser.js +40 -20
package/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
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.1 / 2023-04-18**
|
|
4
|
+
* fix: jpath after unpaired tags
|
|
5
|
+
|
|
6
|
+
**4.2.0 / 2023-04-09**
|
|
7
|
+
* support `updateTag` parser property
|
|
8
|
+
|
|
3
9
|
**4.1.4 / 2023-04-08**
|
|
4
10
|
* update typings to let user create XMLBuilder instance without options (#556) (By [Patrick](https://github.com/omggga))
|
|
5
11
|
* 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
|
|
12
|
+
* feature: support `oneListGroup` to group repeated children tags udder single group
|
|
7
13
|
|
|
8
14
|
**4.1.3 / 2023-02-26**
|
|
9
15
|
* fix #546: Support complex entity value
|
package/package.json
CHANGED
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
|
|
|
@@ -205,9 +206,18 @@ const parseXml = function(xmlData) {
|
|
|
205
206
|
textData = this.saveTextToParentTag(textData, currentNode, jPath);
|
|
206
207
|
}
|
|
207
208
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
209
|
+
//check if last tag of nested tag was unpaired tag
|
|
210
|
+
const lastTagName = jPath.substring(jPath.lastIndexOf(".")+1);
|
|
211
|
+
let propIndex = 0
|
|
212
|
+
if(lastTagName && this.options.unpairedTags.indexOf(lastTagName) !== -1 ){
|
|
213
|
+
propIndex = jPath.lastIndexOf('.', jPath.lastIndexOf('.')-1)
|
|
214
|
+
if(propIndex < 1) propIndex = jPath.lastIndexOf(".");
|
|
215
|
+
}else{
|
|
216
|
+
propIndex = jPath.lastIndexOf(".");
|
|
217
|
+
}
|
|
218
|
+
jPath = jPath.substring(0, propIndex);
|
|
219
|
+
|
|
220
|
+
currentNode = this.tagsNodeStack.pop();//avoid recursion, set the parent tag scope
|
|
211
221
|
textData = "";
|
|
212
222
|
i = closeIndex;
|
|
213
223
|
} else if( xmlData[i+1] === '?') {
|
|
@@ -224,9 +234,9 @@ const parseXml = function(xmlData) {
|
|
|
224
234
|
childNode.add(this.options.textNodeName, "");
|
|
225
235
|
|
|
226
236
|
if(tagData.tagName !== tagData.tagExp && tagData.attrExpPresent){
|
|
227
|
-
childNode[":@"] = this.buildAttributesMap(tagData.tagExp, jPath);
|
|
237
|
+
childNode[":@"] = this.buildAttributesMap(tagData.tagExp, jPath, tagData.tagName);
|
|
228
238
|
}
|
|
229
|
-
|
|
239
|
+
this.addChild(currentNode, childNode, jPath)
|
|
230
240
|
|
|
231
241
|
}
|
|
232
242
|
|
|
@@ -283,23 +293,22 @@ const parseXml = function(xmlData) {
|
|
|
283
293
|
}
|
|
284
294
|
}
|
|
285
295
|
|
|
286
|
-
if(tagName !== xmlObj.tagname){
|
|
287
|
-
jPath += jPath ? "." + tagName : tagName;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
296
|
//check if last tag was unpaired tag
|
|
291
297
|
const lastTag = currentNode;
|
|
292
298
|
if(lastTag && this.options.unpairedTags.indexOf(lastTag.tagname) !== -1 ){
|
|
293
299
|
currentNode = this.tagsNodeStack.pop();
|
|
300
|
+
jPath = jPath.substring(0, jPath.lastIndexOf("."));
|
|
301
|
+
}
|
|
302
|
+
if(tagName !== xmlObj.tagname){
|
|
303
|
+
jPath += jPath ? "." + tagName : tagName;
|
|
294
304
|
}
|
|
295
|
-
|
|
296
305
|
if (this.isItStopNode(this.options.stopNodes, jPath, tagName)) { //TODO: namespace
|
|
297
306
|
let tagContent = "";
|
|
298
307
|
//self-closing tag
|
|
299
308
|
if(tagExp.length > 0 && tagExp.lastIndexOf("/") === tagExp.length - 1){
|
|
300
309
|
i = result.closeIndex;
|
|
301
310
|
}
|
|
302
|
-
//
|
|
311
|
+
//unpaired tag
|
|
303
312
|
else if(this.options.unpairedTags.indexOf(tagName) !== -1){
|
|
304
313
|
i = result.closeIndex;
|
|
305
314
|
}
|
|
@@ -314,7 +323,7 @@ const parseXml = function(xmlData) {
|
|
|
314
323
|
|
|
315
324
|
const childNode = new xmlNode(tagName);
|
|
316
325
|
if(tagName !== tagExp && attrExpPresent){
|
|
317
|
-
childNode[":@"] = this.buildAttributesMap(tagExp, jPath);
|
|
326
|
+
childNode[":@"] = this.buildAttributesMap(tagExp, jPath, tagName);
|
|
318
327
|
}
|
|
319
328
|
if(tagContent) {
|
|
320
329
|
tagContent = this.parseTextData(tagContent, tagName, jPath, true, attrExpPresent, true, true);
|
|
@@ -323,7 +332,7 @@ const parseXml = function(xmlData) {
|
|
|
323
332
|
jPath = jPath.substr(0, jPath.lastIndexOf("."));
|
|
324
333
|
childNode.add(this.options.textNodeName, tagContent);
|
|
325
334
|
|
|
326
|
-
|
|
335
|
+
this.addChild(currentNode, childNode, jPath)
|
|
327
336
|
}else{
|
|
328
337
|
//selfClosing tag
|
|
329
338
|
if(tagExp.length > 0 && tagExp.lastIndexOf("/") === tagExp.length - 1){
|
|
@@ -340,10 +349,10 @@ const parseXml = function(xmlData) {
|
|
|
340
349
|
|
|
341
350
|
const childNode = new xmlNode(tagName);
|
|
342
351
|
if(tagName !== tagExp && attrExpPresent){
|
|
343
|
-
childNode[":@"] = this.buildAttributesMap(tagExp, jPath);
|
|
352
|
+
childNode[":@"] = this.buildAttributesMap(tagExp, jPath, tagName);
|
|
344
353
|
}
|
|
354
|
+
this.addChild(currentNode, childNode, jPath)
|
|
345
355
|
jPath = jPath.substr(0, jPath.lastIndexOf("."));
|
|
346
|
-
currentNode.addChild(childNode);
|
|
347
356
|
}
|
|
348
357
|
//opening tag
|
|
349
358
|
else{
|
|
@@ -351,9 +360,9 @@ const parseXml = function(xmlData) {
|
|
|
351
360
|
this.tagsNodeStack.push(currentNode);
|
|
352
361
|
|
|
353
362
|
if(tagName !== tagExp && attrExpPresent){
|
|
354
|
-
childNode[":@"] = this.buildAttributesMap(tagExp, jPath);
|
|
363
|
+
childNode[":@"] = this.buildAttributesMap(tagExp, jPath, tagName);
|
|
355
364
|
}
|
|
356
|
-
|
|
365
|
+
this.addChild(currentNode, childNode, jPath)
|
|
357
366
|
currentNode = childNode;
|
|
358
367
|
}
|
|
359
368
|
textData = "";
|
|
@@ -367,6 +376,17 @@ const parseXml = function(xmlData) {
|
|
|
367
376
|
return xmlObj.child;
|
|
368
377
|
}
|
|
369
378
|
|
|
379
|
+
function addChild(currentNode, childNode, jPath){
|
|
380
|
+
const result = this.options.updateTag(childNode.tagname, jPath, childNode[":@"])
|
|
381
|
+
if(result === false){
|
|
382
|
+
}else if(typeof result === "string"){
|
|
383
|
+
childNode.tagname = result
|
|
384
|
+
currentNode.addChild(childNode);
|
|
385
|
+
}else{
|
|
386
|
+
currentNode.addChild(childNode);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
370
390
|
const replaceEntitiesValue = function(val){
|
|
371
391
|
|
|
372
392
|
if(this.options.processEntities){
|
|
@@ -423,7 +443,7 @@ function isItStopNode(stopNodes, jPath, currentTagName){
|
|
|
423
443
|
}
|
|
424
444
|
|
|
425
445
|
/**
|
|
426
|
-
* Returns the tag Expression and where it is ending handling single-
|
|
446
|
+
* Returns the tag Expression and where it is ending handling single-double quotes situation
|
|
427
447
|
* @param {string} xmlData
|
|
428
448
|
* @param {number} i starting index
|
|
429
449
|
* @returns
|