fast-xml-parser 5.3.9 → 5.4.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 -0
- package/lib/fxbuilder.min.js +1 -1
- package/lib/fxbuilder.min.js.map +1 -1
- package/lib/fxp.cjs +1 -1
- package/lib/fxp.min.js +1 -1
- package/lib/fxp.min.js.map +1 -1
- package/lib/fxparser.min.js +1 -1
- package/lib/fxparser.min.js.map +1 -1
- package/package.json +2 -1
- package/src/fxp.js +1 -1
- package/src/xmlbuilder/json2xml.js +5 -284
- package/src/xmlparser/OrderedObjParser.js +16 -5
- package/src/xmlbuilder/orderedJs2Xml.js +0 -145
- package/src/xmlbuilder/prettifyJs2Xml.js +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fast-xml-parser",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.4.1",
|
|
4
4
|
"description": "Validate XML, Parse XML, Build XML without C/C++ based libraries",
|
|
5
5
|
"main": "./lib/fxp.cjs",
|
|
6
6
|
"type": "module",
|
|
@@ -87,6 +87,7 @@
|
|
|
87
87
|
}
|
|
88
88
|
],
|
|
89
89
|
"dependencies": {
|
|
90
|
+
"fast-xml-builder": "^1.0.0",
|
|
90
91
|
"strnum": "^2.1.2"
|
|
91
92
|
}
|
|
92
93
|
}
|
package/src/fxp.js
CHANGED
|
@@ -1,285 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import getIgnoreAttributesFn from "../ignoreAttributes.js";
|
|
5
|
-
|
|
6
|
-
const defaultOptions = {
|
|
7
|
-
attributeNamePrefix: '@_',
|
|
8
|
-
attributesGroupName: false,
|
|
9
|
-
textNodeName: '#text',
|
|
10
|
-
ignoreAttributes: true,
|
|
11
|
-
cdataPropName: false,
|
|
12
|
-
format: false,
|
|
13
|
-
indentBy: ' ',
|
|
14
|
-
suppressEmptyNode: false,
|
|
15
|
-
suppressUnpairedNode: true,
|
|
16
|
-
suppressBooleanAttributes: true,
|
|
17
|
-
tagValueProcessor: function (key, a) {
|
|
18
|
-
return a;
|
|
19
|
-
},
|
|
20
|
-
attributeValueProcessor: function (attrName, a) {
|
|
21
|
-
return a;
|
|
22
|
-
},
|
|
23
|
-
preserveOrder: false,
|
|
24
|
-
commentPropName: false,
|
|
25
|
-
unpairedTags: [],
|
|
26
|
-
entities: [
|
|
27
|
-
{ regex: new RegExp("&", "g"), val: "&" },//it must be on top
|
|
28
|
-
{ regex: new RegExp(">", "g"), val: ">" },
|
|
29
|
-
{ regex: new RegExp("<", "g"), val: "<" },
|
|
30
|
-
{ regex: new RegExp("\'", "g"), val: "'" },
|
|
31
|
-
{ regex: new RegExp("\"", "g"), val: """ }
|
|
32
|
-
],
|
|
33
|
-
processEntities: true,
|
|
34
|
-
stopNodes: [],
|
|
35
|
-
// transformTagName: false,
|
|
36
|
-
// transformAttributeName: false,
|
|
37
|
-
oneListGroup: false
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
export default function Builder(options) {
|
|
41
|
-
this.options = Object.assign({}, defaultOptions, options);
|
|
42
|
-
if (this.options.ignoreAttributes === true || this.options.attributesGroupName) {
|
|
43
|
-
this.isAttribute = function (/*a*/) {
|
|
44
|
-
return false;
|
|
45
|
-
};
|
|
46
|
-
} else {
|
|
47
|
-
this.ignoreAttributesFn = getIgnoreAttributesFn(this.options.ignoreAttributes)
|
|
48
|
-
this.attrPrefixLen = this.options.attributeNamePrefix.length;
|
|
49
|
-
this.isAttribute = isAttribute;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
this.processTextOrObjNode = processTextOrObjNode
|
|
53
|
-
|
|
54
|
-
if (this.options.format) {
|
|
55
|
-
this.indentate = indentate;
|
|
56
|
-
this.tagEndChar = '>\n';
|
|
57
|
-
this.newLine = '\n';
|
|
58
|
-
} else {
|
|
59
|
-
this.indentate = function () {
|
|
60
|
-
return '';
|
|
61
|
-
};
|
|
62
|
-
this.tagEndChar = '>';
|
|
63
|
-
this.newLine = '';
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
Builder.prototype.build = function (jObj) {
|
|
68
|
-
if (this.options.preserveOrder) {
|
|
69
|
-
return buildFromOrderedJs(jObj, this.options);
|
|
70
|
-
} else {
|
|
71
|
-
if (Array.isArray(jObj) && this.options.arrayNodeName && this.options.arrayNodeName.length > 1) {
|
|
72
|
-
jObj = {
|
|
73
|
-
[this.options.arrayNodeName]: jObj
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
return this.j2x(jObj, 0, []).val;
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
Builder.prototype.j2x = function (jObj, level, ajPath) {
|
|
81
|
-
let attrStr = '';
|
|
82
|
-
let val = '';
|
|
83
|
-
const jPath = ajPath.join('.')
|
|
84
|
-
for (let key in jObj) {
|
|
85
|
-
if (!Object.prototype.hasOwnProperty.call(jObj, key)) continue;
|
|
86
|
-
if (typeof jObj[key] === 'undefined') {
|
|
87
|
-
// supress undefined node only if it is not an attribute
|
|
88
|
-
if (this.isAttribute(key)) {
|
|
89
|
-
val += '';
|
|
90
|
-
}
|
|
91
|
-
} else if (jObj[key] === null) {
|
|
92
|
-
// null attribute should be ignored by the attribute list, but should not cause the tag closing
|
|
93
|
-
if (this.isAttribute(key)) {
|
|
94
|
-
val += '';
|
|
95
|
-
} else if (key === this.options.cdataPropName) {
|
|
96
|
-
val += '';
|
|
97
|
-
} else if (key[0] === '?') {
|
|
98
|
-
val += this.indentate(level) + '<' + key + '?' + this.tagEndChar;
|
|
99
|
-
} else {
|
|
100
|
-
val += this.indentate(level) + '<' + key + '/' + this.tagEndChar;
|
|
101
|
-
}
|
|
102
|
-
// val += this.indentate(level) + '<' + key + '/' + this.tagEndChar;
|
|
103
|
-
} else if (jObj[key] instanceof Date) {
|
|
104
|
-
val += this.buildTextValNode(jObj[key], key, '', level);
|
|
105
|
-
} else if (typeof jObj[key] !== 'object') {
|
|
106
|
-
//premitive type
|
|
107
|
-
const attr = this.isAttribute(key);
|
|
108
|
-
if (attr && !this.ignoreAttributesFn(attr, jPath)) {
|
|
109
|
-
attrStr += this.buildAttrPairStr(attr, '' + jObj[key]);
|
|
110
|
-
} else if (!attr) {
|
|
111
|
-
//tag value
|
|
112
|
-
if (key === this.options.textNodeName) {
|
|
113
|
-
let newval = this.options.tagValueProcessor(key, '' + jObj[key]);
|
|
114
|
-
val += this.replaceEntitiesValue(newval);
|
|
115
|
-
} else {
|
|
116
|
-
val += this.buildTextValNode(jObj[key], key, '', level);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
} else if (Array.isArray(jObj[key])) {
|
|
120
|
-
//repeated nodes
|
|
121
|
-
const arrLen = jObj[key].length;
|
|
122
|
-
let listTagVal = "";
|
|
123
|
-
let listTagAttr = "";
|
|
124
|
-
for (let j = 0; j < arrLen; j++) {
|
|
125
|
-
const item = jObj[key][j];
|
|
126
|
-
if (typeof item === 'undefined') {
|
|
127
|
-
// supress undefined node
|
|
128
|
-
} else if (item === null) {
|
|
129
|
-
if (key[0] === "?") val += this.indentate(level) + '<' + key + '?' + this.tagEndChar;
|
|
130
|
-
else val += this.indentate(level) + '<' + key + '/' + this.tagEndChar;
|
|
131
|
-
// val += this.indentate(level) + '<' + key + '/' + this.tagEndChar;
|
|
132
|
-
} else if (typeof item === 'object') {
|
|
133
|
-
if (this.options.oneListGroup) {
|
|
134
|
-
const result = this.j2x(item, level + 1, ajPath.concat(key));
|
|
135
|
-
listTagVal += result.val;
|
|
136
|
-
if (this.options.attributesGroupName && item.hasOwnProperty(this.options.attributesGroupName)) {
|
|
137
|
-
listTagAttr += result.attrStr
|
|
138
|
-
}
|
|
139
|
-
} else {
|
|
140
|
-
listTagVal += this.processTextOrObjNode(item, key, level, ajPath)
|
|
141
|
-
}
|
|
142
|
-
} else {
|
|
143
|
-
if (this.options.oneListGroup) {
|
|
144
|
-
let textValue = this.options.tagValueProcessor(key, item);
|
|
145
|
-
textValue = this.replaceEntitiesValue(textValue);
|
|
146
|
-
listTagVal += textValue;
|
|
147
|
-
} else {
|
|
148
|
-
listTagVal += this.buildTextValNode(item, key, '', level);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
if (this.options.oneListGroup) {
|
|
153
|
-
listTagVal = this.buildObjectNode(listTagVal, key, listTagAttr, level);
|
|
154
|
-
}
|
|
155
|
-
val += listTagVal;
|
|
156
|
-
} else {
|
|
157
|
-
//nested node
|
|
158
|
-
if (this.options.attributesGroupName && key === this.options.attributesGroupName) {
|
|
159
|
-
const Ks = Object.keys(jObj[key]);
|
|
160
|
-
const L = Ks.length;
|
|
161
|
-
for (let j = 0; j < L; j++) {
|
|
162
|
-
attrStr += this.buildAttrPairStr(Ks[j], '' + jObj[key][Ks[j]]);
|
|
163
|
-
}
|
|
164
|
-
} else {
|
|
165
|
-
val += this.processTextOrObjNode(jObj[key], key, level, ajPath)
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
return { attrStr: attrStr, val: val };
|
|
170
|
-
};
|
|
171
|
-
|
|
172
|
-
Builder.prototype.buildAttrPairStr = function (attrName, val) {
|
|
173
|
-
val = this.options.attributeValueProcessor(attrName, '' + val);
|
|
174
|
-
val = this.replaceEntitiesValue(val);
|
|
175
|
-
if (this.options.suppressBooleanAttributes && val === "true") {
|
|
176
|
-
return ' ' + attrName;
|
|
177
|
-
} else return ' ' + attrName + '="' + val + '"';
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
function processTextOrObjNode(object, key, level, ajPath) {
|
|
181
|
-
const result = this.j2x(object, level + 1, ajPath.concat(key));
|
|
182
|
-
if (object[this.options.textNodeName] !== undefined && Object.keys(object).length === 1) {
|
|
183
|
-
return this.buildTextValNode(object[this.options.textNodeName], key, result.attrStr, level);
|
|
184
|
-
} else {
|
|
185
|
-
return this.buildObjectNode(result.val, key, result.attrStr, level);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
Builder.prototype.buildObjectNode = function (val, key, attrStr, level) {
|
|
190
|
-
if (val === "") {
|
|
191
|
-
if (key[0] === "?") return this.indentate(level) + '<' + key + attrStr + '?' + this.tagEndChar;
|
|
192
|
-
else {
|
|
193
|
-
return this.indentate(level) + '<' + key + attrStr + this.closeTag(key) + this.tagEndChar;
|
|
194
|
-
}
|
|
195
|
-
} else {
|
|
196
|
-
|
|
197
|
-
let tagEndExp = '</' + key + this.tagEndChar;
|
|
198
|
-
let piClosingChar = "";
|
|
199
|
-
|
|
200
|
-
if (key[0] === "?") {
|
|
201
|
-
piClosingChar = "?";
|
|
202
|
-
tagEndExp = "";
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// attrStr is an empty string in case the attribute came as undefined or null
|
|
206
|
-
if ((attrStr || attrStr === '') && val.indexOf('<') === -1) {
|
|
207
|
-
return (this.indentate(level) + '<' + key + attrStr + piClosingChar + '>' + val + tagEndExp);
|
|
208
|
-
} else if (this.options.commentPropName !== false && key === this.options.commentPropName && piClosingChar.length === 0) {
|
|
209
|
-
return this.indentate(level) + `<!--${val}-->` + this.newLine;
|
|
210
|
-
} else {
|
|
211
|
-
return (
|
|
212
|
-
this.indentate(level) + '<' + key + attrStr + piClosingChar + this.tagEndChar +
|
|
213
|
-
val +
|
|
214
|
-
this.indentate(level) + tagEndExp);
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
Builder.prototype.closeTag = function (key) {
|
|
220
|
-
let closeTag = "";
|
|
221
|
-
if (this.options.unpairedTags.indexOf(key) !== -1) { //unpaired
|
|
222
|
-
if (!this.options.suppressUnpairedNode) closeTag = "/"
|
|
223
|
-
} else if (this.options.suppressEmptyNode) { //empty
|
|
224
|
-
closeTag = "/";
|
|
225
|
-
} else {
|
|
226
|
-
closeTag = `></${key}`
|
|
227
|
-
}
|
|
228
|
-
return closeTag;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
function buildEmptyObjNode(val, key, attrStr, level) {
|
|
232
|
-
if (val !== '') {
|
|
233
|
-
return this.buildObjectNode(val, key, attrStr, level);
|
|
234
|
-
} else {
|
|
235
|
-
if (key[0] === "?") return this.indentate(level) + '<' + key + attrStr + '?' + this.tagEndChar;
|
|
236
|
-
else {
|
|
237
|
-
return this.indentate(level) + '<' + key + attrStr + '/' + this.tagEndChar;
|
|
238
|
-
// return this.buildTagStr(level,key, attrStr);
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
Builder.prototype.buildTextValNode = function (val, key, attrStr, level) {
|
|
244
|
-
if (this.options.cdataPropName !== false && key === this.options.cdataPropName) {
|
|
245
|
-
return this.indentate(level) + `<![CDATA[${val}]]>` + this.newLine;
|
|
246
|
-
} else if (this.options.commentPropName !== false && key === this.options.commentPropName) {
|
|
247
|
-
return this.indentate(level) + `<!--${val}-->` + this.newLine;
|
|
248
|
-
} else if (key[0] === "?") {//PI tag
|
|
249
|
-
return this.indentate(level) + '<' + key + attrStr + '?' + this.tagEndChar;
|
|
250
|
-
} else {
|
|
251
|
-
let textValue = this.options.tagValueProcessor(key, val);
|
|
252
|
-
textValue = this.replaceEntitiesValue(textValue);
|
|
253
|
-
|
|
254
|
-
if (textValue === '') {
|
|
255
|
-
return this.indentate(level) + '<' + key + attrStr + this.closeTag(key) + this.tagEndChar;
|
|
256
|
-
} else {
|
|
257
|
-
return this.indentate(level) + '<' + key + attrStr + '>' +
|
|
258
|
-
textValue +
|
|
259
|
-
'</' + key + this.tagEndChar;
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
Builder.prototype.replaceEntitiesValue = function (textValue) {
|
|
265
|
-
if (textValue && textValue.length > 0 && this.options.processEntities) {
|
|
266
|
-
for (let i = 0; i < this.options.entities.length; i++) {
|
|
267
|
-
const entity = this.options.entities[i];
|
|
268
|
-
textValue = textValue.replace(entity.regex, entity.val);
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
return textValue;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
function indentate(level) {
|
|
275
|
-
return this.options.indentBy.repeat(level);
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
function isAttribute(name /*, options*/) {
|
|
279
|
-
if (name.startsWith(this.options.attributeNamePrefix) && name !== this.options.textNodeName) {
|
|
280
|
-
return name.substr(this.attrPrefixLen);
|
|
281
|
-
} else {
|
|
282
|
-
return false;
|
|
283
|
-
}
|
|
284
|
-
}
|
|
1
|
+
// Re-export from fast-xml-builder for backward compatibility
|
|
2
|
+
import XMLBuilder from 'fast-xml-builder';
|
|
3
|
+
export default XMLBuilder;
|
|
285
4
|
|
|
5
|
+
// If there are any named exports you also want to re-export:
|
|
6
|
+
export * from 'fast-xml-builder';
|
|
@@ -414,6 +414,17 @@ const parseXml = function (xmlData) {
|
|
|
414
414
|
this.addChild(currentNode, childNode, jPath, startIndex);
|
|
415
415
|
jPath = jPath.substr(0, jPath.lastIndexOf("."));
|
|
416
416
|
}
|
|
417
|
+
else if(this.options.unpairedTags.indexOf(tagName) !== -1){//unpaired tag
|
|
418
|
+
const childNode = new xmlNode(tagName);
|
|
419
|
+
if(tagName !== tagExp && attrExpPresent){
|
|
420
|
+
childNode[":@"] = this.buildAttributesMap(tagExp, jPath);
|
|
421
|
+
}
|
|
422
|
+
this.addChild(currentNode, childNode, jPath, startIndex);
|
|
423
|
+
jPath = jPath.substr(0, jPath.lastIndexOf("."));
|
|
424
|
+
i = result.closeIndex;
|
|
425
|
+
// Continue to next iteration without changing currentNode
|
|
426
|
+
continue;
|
|
427
|
+
}
|
|
417
428
|
//opening tag
|
|
418
429
|
else {
|
|
419
430
|
const childNode = new xmlNode(tagName);
|
|
@@ -535,19 +546,19 @@ const replaceEntitiesValue = function (val, tagName, jPath) {
|
|
|
535
546
|
}
|
|
536
547
|
|
|
537
548
|
|
|
538
|
-
function saveTextToParentTag(textData,
|
|
549
|
+
function saveTextToParentTag(textData, parentNode, jPath, isLeafNode) {
|
|
539
550
|
if (textData) { //store previously collected data as textNode
|
|
540
|
-
if (isLeafNode === undefined) isLeafNode =
|
|
551
|
+
if (isLeafNode === undefined) isLeafNode = parentNode.child.length === 0
|
|
541
552
|
|
|
542
553
|
textData = this.parseTextData(textData,
|
|
543
|
-
|
|
554
|
+
parentNode.tagname,
|
|
544
555
|
jPath,
|
|
545
556
|
false,
|
|
546
|
-
|
|
557
|
+
parentNode[":@"] ? Object.keys(parentNode[":@"]).length !== 0 : false,
|
|
547
558
|
isLeafNode);
|
|
548
559
|
|
|
549
560
|
if (textData !== undefined && textData !== "")
|
|
550
|
-
|
|
561
|
+
parentNode.add(this.options.textNodeName, textData);
|
|
551
562
|
textData = "";
|
|
552
563
|
}
|
|
553
564
|
return textData;
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
const EOL = "\n";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
*
|
|
5
|
-
* @param {array} jArray
|
|
6
|
-
* @param {any} options
|
|
7
|
-
* @returns
|
|
8
|
-
*/
|
|
9
|
-
export default function toXml(jArray, options) {
|
|
10
|
-
let indentation = "";
|
|
11
|
-
if (options.format && options.indentBy.length > 0) {
|
|
12
|
-
indentation = EOL;
|
|
13
|
-
}
|
|
14
|
-
return arrToStr(jArray, options, "", indentation);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function arrToStr(arr, options, jPath, indentation) {
|
|
18
|
-
let xmlStr = "";
|
|
19
|
-
let isPreviousElementTag = false;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
if (!Array.isArray(arr)) {
|
|
23
|
-
// Non-array values (e.g. string tag values) should be treated as text content
|
|
24
|
-
if (arr !== undefined && arr !== null) {
|
|
25
|
-
let text = arr.toString();
|
|
26
|
-
text = replaceEntitiesValue(text, options);
|
|
27
|
-
return text;
|
|
28
|
-
}
|
|
29
|
-
return "";
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
for (let i = 0; i < arr.length; i++) {
|
|
33
|
-
const tagObj = arr[i];
|
|
34
|
-
const tagName = propName(tagObj);
|
|
35
|
-
if (tagName === undefined) continue;
|
|
36
|
-
|
|
37
|
-
let newJPath = "";
|
|
38
|
-
if (jPath.length === 0) newJPath = tagName
|
|
39
|
-
else newJPath = `${jPath}.${tagName}`;
|
|
40
|
-
|
|
41
|
-
if (tagName === options.textNodeName) {
|
|
42
|
-
let tagText = tagObj[tagName];
|
|
43
|
-
if (!isStopNode(newJPath, options)) {
|
|
44
|
-
tagText = options.tagValueProcessor(tagName, tagText);
|
|
45
|
-
tagText = replaceEntitiesValue(tagText, options);
|
|
46
|
-
}
|
|
47
|
-
if (isPreviousElementTag) {
|
|
48
|
-
xmlStr += indentation;
|
|
49
|
-
}
|
|
50
|
-
xmlStr += tagText;
|
|
51
|
-
isPreviousElementTag = false;
|
|
52
|
-
continue;
|
|
53
|
-
} else if (tagName === options.cdataPropName) {
|
|
54
|
-
if (isPreviousElementTag) {
|
|
55
|
-
xmlStr += indentation;
|
|
56
|
-
}
|
|
57
|
-
xmlStr += `<![CDATA[${tagObj[tagName][0][options.textNodeName]}]]>`;
|
|
58
|
-
isPreviousElementTag = false;
|
|
59
|
-
continue;
|
|
60
|
-
} else if (tagName === options.commentPropName) {
|
|
61
|
-
xmlStr += indentation + `<!--${tagObj[tagName][0][options.textNodeName]}-->`;
|
|
62
|
-
isPreviousElementTag = true;
|
|
63
|
-
continue;
|
|
64
|
-
} else if (tagName[0] === "?") {
|
|
65
|
-
const attStr = attr_to_str(tagObj[":@"], options);
|
|
66
|
-
const tempInd = tagName === "?xml" ? "" : indentation;
|
|
67
|
-
let piTextNodeName = tagObj[tagName][0][options.textNodeName];
|
|
68
|
-
piTextNodeName = piTextNodeName.length !== 0 ? " " + piTextNodeName : ""; //remove extra spacing
|
|
69
|
-
xmlStr += tempInd + `<${tagName}${piTextNodeName}${attStr}?>`;
|
|
70
|
-
isPreviousElementTag = true;
|
|
71
|
-
continue;
|
|
72
|
-
}
|
|
73
|
-
let newIdentation = indentation;
|
|
74
|
-
if (newIdentation !== "") {
|
|
75
|
-
newIdentation += options.indentBy;
|
|
76
|
-
}
|
|
77
|
-
const attStr = attr_to_str(tagObj[":@"], options);
|
|
78
|
-
const tagStart = indentation + `<${tagName}${attStr}`;
|
|
79
|
-
const tagValue = arrToStr(tagObj[tagName], options, newJPath, newIdentation);
|
|
80
|
-
if (options.unpairedTags.indexOf(tagName) !== -1) {
|
|
81
|
-
if (options.suppressUnpairedNode) xmlStr += tagStart + ">";
|
|
82
|
-
else xmlStr += tagStart + "/>";
|
|
83
|
-
} else if ((!tagValue || tagValue.length === 0) && options.suppressEmptyNode) {
|
|
84
|
-
xmlStr += tagStart + "/>";
|
|
85
|
-
} else if (tagValue && tagValue.endsWith(">")) {
|
|
86
|
-
xmlStr += tagStart + `>${tagValue}${indentation}</${tagName}>`;
|
|
87
|
-
} else {
|
|
88
|
-
xmlStr += tagStart + ">";
|
|
89
|
-
if (tagValue && indentation !== "" && (tagValue.includes("/>") || tagValue.includes("</"))) {
|
|
90
|
-
xmlStr += indentation + options.indentBy + tagValue + indentation;
|
|
91
|
-
} else {
|
|
92
|
-
xmlStr += tagValue;
|
|
93
|
-
}
|
|
94
|
-
xmlStr += `</${tagName}>`;
|
|
95
|
-
}
|
|
96
|
-
isPreviousElementTag = true;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
return xmlStr;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
function propName(obj) {
|
|
103
|
-
const keys = Object.keys(obj);
|
|
104
|
-
for (let i = 0; i < keys.length; i++) {
|
|
105
|
-
const key = keys[i];
|
|
106
|
-
if (!Object.prototype.hasOwnProperty.call(obj, key)) continue;
|
|
107
|
-
if (key !== ":@") return key;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
function attr_to_str(attrMap, options) {
|
|
112
|
-
let attrStr = "";
|
|
113
|
-
if (attrMap && !options.ignoreAttributes) {
|
|
114
|
-
for (let attr in attrMap) {
|
|
115
|
-
if (!Object.prototype.hasOwnProperty.call(attrMap, attr)) continue;
|
|
116
|
-
let attrVal = options.attributeValueProcessor(attr, attrMap[attr]);
|
|
117
|
-
attrVal = replaceEntitiesValue(attrVal, options);
|
|
118
|
-
if (attrVal === true && options.suppressBooleanAttributes) {
|
|
119
|
-
attrStr += ` ${attr.substr(options.attributeNamePrefix.length)}`;
|
|
120
|
-
} else {
|
|
121
|
-
attrStr += ` ${attr.substr(options.attributeNamePrefix.length)}="${attrVal}"`;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
return attrStr;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
function isStopNode(jPath, options) {
|
|
129
|
-
jPath = jPath.substr(0, jPath.length - options.textNodeName.length - 1);
|
|
130
|
-
let tagName = jPath.substr(jPath.lastIndexOf(".") + 1);
|
|
131
|
-
for (let index in options.stopNodes) {
|
|
132
|
-
if (options.stopNodes[index] === jPath || options.stopNodes[index] === "*." + tagName) return true;
|
|
133
|
-
}
|
|
134
|
-
return false;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
function replaceEntitiesValue(textValue, options) {
|
|
138
|
-
if (textValue && textValue.length > 0 && options.processEntities) {
|
|
139
|
-
for (let i = 0; i < options.entities.length; i++) {
|
|
140
|
-
const entity = options.entities[i];
|
|
141
|
-
textValue = textValue.replace(entity.regex, entity.val);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
return textValue;
|
|
145
|
-
}
|
|
File without changes
|