fast-xml-parser 4.4.0 → 4.5.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 +332 -324
- package/README.md +70 -42
- package/package.json +1 -2
- package/src/fxp.d.ts +19 -3
- package/src/ignoreAttributes.js +20 -0
- package/src/v5/OutputBuilders/JsArrBuilder.js +1 -1
- package/src/v5/OutputBuilders/JsMinArrBuilder.js +1 -1
- package/src/v5/OutputBuilders/JsObjBuilder.js +1 -1
- package/src/v5/OutputBuilders/ParserOptionsBuilder.js +4 -1
- package/src/v5/valueParsers/currency.js +12 -3
- package/src/xmlbuilder/json2xml.js +27 -13
- package/src/xmlparser/OrderedObjParser.js +6 -1
package/README.md
CHANGED
|
@@ -1,29 +1,32 @@
|
|
|
1
1
|
# [fast-xml-parser](https://www.npmjs.com/package/fast-xml-parser)
|
|
2
|
-
[](https://snyk.io/test/github/naturalintelligence/fast-xml-parser)
|
|
3
2
|
[![NPM quality][quality-image]][quality-url]
|
|
4
3
|
[](https://coveralls.io/github/NaturalIntelligence/fast-xml-parser?branch=master)
|
|
5
4
|
[<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/)
|
|
6
5
|
[](https://npm.im/fast-xml-parser)
|
|
7
6
|
|
|
8
|
-
[quality-image]: http://npm.packagequality.com/shield/fast-xml-parser.svg?style=flat-square
|
|
9
|
-
[quality-url]: http://packagequality.com/#?package=fast-xml-parser
|
|
10
|
-
|
|
11
7
|
|
|
12
8
|
Validate XML, Parse XML to JS Object, or Build XML from JS Object without C/C++ based libraries and no callback.
|
|
13
9
|
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
<a href="https://www.amazon.in/Power-Glasses-world-imagination-Perspective-ebook/dp/B0CW1CJGNK/"><img align="left" src="https://github.com/NaturalIntelligence/fast-xml-parser/assets/7692328/e7a42bcc-5186-45e3-bfee-de8d8b9a69d4" alt="ads-thePowerGlassesBook"/></a>
|
|
13
|
+
I had recently published a book, The Power Glasses. Please have a look. Your feedback would be helpful. You can [mail](githubissues@proton.me) me for a free copy.
|
|
14
|
+
<br>
|
|
15
|
+
|
|
16
|
+
Sponsor this project
|
|
16
17
|
|
|
17
|
-
Sponsor this project 👉
|
|
18
18
|
<a href="https://github.com/sponsors/NaturalIntelligence">
|
|
19
|
-
<img src="https://raw.githubusercontent.com/NaturalIntelligence/ThankYouBackers/main/github_sponsor.png" width="
|
|
19
|
+
<img src="https://raw.githubusercontent.com/NaturalIntelligence/ThankYouBackers/main/github_sponsor.png" width="180" />
|
|
20
20
|
</a>
|
|
21
21
|
<a href="https://opencollective.com/fast-xml-parser/donate" target="_blank">
|
|
22
|
-
<img src="https://opencollective.com/fast-xml-parser/donate/button@2x.png?color=blue" width=
|
|
22
|
+
<img src="https://opencollective.com/fast-xml-parser/donate/button@2x.png?color=blue" width=180 />
|
|
23
23
|
</a>
|
|
24
|
-
<a href="https://paypal.me/naturalintelligence"> <img src="static/img/support_paypal.svg" alt="Stubmatic donate button" width="
|
|
25
|
-
|
|
24
|
+
<a href="https://paypal.me/naturalintelligence"> <img src="static/img/support_paypal.svg" alt="Stubmatic donate button" width="180"/></a>
|
|
25
|
+
<br>
|
|
26
|
+
<br>
|
|
27
|
+
<br>
|
|
26
28
|
|
|
29
|
+
<!--
|
|
27
30
|
### Current Sponsors
|
|
28
31
|
|
|
29
32
|
Check the complete list at [ThankYouBackers](https://github.com/NaturalIntelligence/ThankYouBackers) for our sponsors and supporters.
|
|
@@ -45,7 +48,9 @@ Through OpenCollective
|
|
|
45
48
|
<a href="https://opencollective.com/fast-xml-parser/sponsor/7/website" target="_blank"><img src="https://opencollective.com/fast-xml-parser/sponsor/7/avatar.svg"></a>
|
|
46
49
|
<a href="https://opencollective.com/fast-xml-parser/sponsor/8/website" target="_blank"><img src="https://opencollective.com/fast-xml-parser/sponsor/8/avatar.svg"></a>
|
|
47
50
|
<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>
|
|
51
|
+
-->
|
|
48
52
|
|
|
53
|
+

|
|
49
54
|
|
|
50
55
|
## Users
|
|
51
56
|
|
|
@@ -63,14 +68,15 @@ Through OpenCollective
|
|
|
63
68
|
<a href="https://github.com/SAP" title="SAP" > <img src="https://user-images.githubusercontent.com/7692328/204835214-d9d25b58-e3df-408d-87a3-c7d36b578ee4.png" width="60px" ></a>
|
|
64
69
|
<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>
|
|
65
70
|
<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>
|
|
71
|
+
<a href="https://github.com/googleapis" title="Google APIs" > <img src="https://avatars.githubusercontent.com/u/16785467?v=4" width="60px" ></a>
|
|
72
|
+
<a href="https://github.com/langchain-ai" title="Langchain AI" > <img src="https://avatars.githubusercontent.com/u/126733545?v=4" width="60px" ></a>
|
|
73
|
+
<a href="https://github.com/withastro" title="Astro websie builder" > <img src="https://avatars.githubusercontent.com/u/44914786?v=4" width="60px" ></a>
|
|
74
|
+
<a href="https://github.com/baidu" title="Baidu" > <img src="https://avatars.githubusercontent.com/u/13245940?v=4" width="60px" ></a>
|
|
75
|
+
[more](./USERs.md)
|
|
66
76
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
<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>
|
|
77
|
+
<small>The list of users are mostly published by Github or communicated directly. Feel free to contact if you find any information wrong.</small>
|
|
70
78
|
|
|
71
|
-
|
|
72
|
-
- githubissues@proton.me
|
|
73
|
-
- https://linkedin.com/in/amitguptagwl/
|
|
79
|
+
---
|
|
74
80
|
|
|
75
81
|
## Main Features
|
|
76
82
|
|
|
@@ -79,7 +85,7 @@ If you want to be an anonymous user of this application and don't want to be hig
|
|
|
79
85
|
* Validate XML data syntactically
|
|
80
86
|
* Parse XML to JS Object
|
|
81
87
|
* Build XML from JS Object
|
|
82
|
-
*
|
|
88
|
+
* Compatible to node js packages, in browser, and in CLI (click try me button above for demo)
|
|
83
89
|
* Faster than any other pure JS implementation.
|
|
84
90
|
* It can handle big files (tested up to 100mb).
|
|
85
91
|
* Controlled parsing using various options
|
|
@@ -137,49 +143,71 @@ In a HTML page
|
|
|
137
143
|
</script>
|
|
138
144
|
```
|
|
139
145
|
|
|
140
|
-
|
|
146
|
+
Bundle size
|
|
141
147
|
|
|
142
148
|
| Bundle Name | Size |
|
|
143
149
|
| ------------------ | ---- |
|
|
144
|
-
| fxbuilder.min.js |
|
|
145
|
-
| fxparser.js
|
|
146
|
-
|
|
|
147
|
-
| fxp.min.js | 22K |
|
|
150
|
+
| fxbuilder.min.js | 6.5K |
|
|
151
|
+
| fxparser.min.js | 20K |
|
|
152
|
+
| fxp.min.js | 26K |
|
|
148
153
|
| fxvalidator.min.js | 5.7K |
|
|
149
154
|
|
|
150
155
|
### Documents
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
156
|
+
<table>
|
|
157
|
+
<tr><td>v3</td><td>v4</td><td>v5</td></tr>
|
|
158
|
+
<tr>
|
|
159
|
+
<td>
|
|
160
|
+
<a href="./docs/v3/docs.md">documents</a>
|
|
161
|
+
</td>
|
|
162
|
+
<td><ol>
|
|
163
|
+
<li><a href="./docs/v4/1.GettingStarted.md">Getting Started</a></li>
|
|
164
|
+
<li><a href="./docs/v4/2.XMLparseOptions.md">XML Parser</a></li>
|
|
165
|
+
<li><a href="./docs/v4/3.XMLBuilder.md">XML Builder</a></li>
|
|
166
|
+
<li><a href="./docs/v4/4.XMLValidator.md">XML Validator</a></li>
|
|
167
|
+
<li><a href="./docs/v4/5.Entities.md">Entities</a></li>
|
|
168
|
+
<li><a href="./docs/v4/6.HTMLParsing.md">HTML Document Parsing</a></li>
|
|
169
|
+
<li><a href="./docs/v4/7.PITags.md">PI Tag processing</a></li>
|
|
170
|
+
</ol></td>
|
|
171
|
+
<td><ol>
|
|
172
|
+
<li></li><a href="./docs/v5/1.GettingStarted.md">Getting Started</a></li>
|
|
173
|
+
<li><a href="./docs/v5/2.Features.md">Features</a></li>
|
|
174
|
+
<li><a href="./docs/v5/3.Options.md">Options</a></li>
|
|
175
|
+
<li><a href="./docs/v5/4.OutputBuilders.md">Output Builders</a></li>
|
|
176
|
+
<li><a href="./docs/v5/5.ValueParsers.md">Value Parsers</a></li>
|
|
177
|
+
</ol></td>
|
|
178
|
+
</tr>
|
|
179
|
+
</table>
|
|
180
|
+
|
|
181
|
+
**note**: version 5 is released with version 4 tfor experimental use. Based on it's demand, it'll be developed and the features can be different in final release.
|
|
182
|
+
|
|
162
183
|
## Performance
|
|
184
|
+
<small>negative means error</small>
|
|
163
185
|
|
|
164
186
|
### XML Parser
|
|
165
187
|
|
|
166
|
-
|
|
188
|
+
<img align="left" src="./docs/imgs/XMLParser_v4.png" width="45%" />
|
|
189
|
+
<img src="./docs/imgs/XMLParser_large_v4.png" width="47%" />
|
|
190
|
+
|
|
167
191
|
* Y-axis: requests per second
|
|
168
192
|
* X-axis: File size
|
|
169
193
|
|
|
170
|
-
**Large files**
|
|
171
|
-

|
|
172
|
-
* Y-axis: requests per second
|
|
173
|
-
* X-axis: File size
|
|
174
194
|
### XML Builder
|
|
175
195
|
|
|
176
|
-
|
|
196
|
+
<img src="./docs/imgs/XMLBuilder_v4.png" width="50%" />
|
|
177
197
|
* Y-axis: requests per second
|
|
178
198
|
|
|
179
|
-
<small>negative means error</small>
|
|
180
199
|
|
|
181
|
-
[](https://github.com/NaturalIntelligence/ads/)
|
|
182
200
|
|
|
201
|
+
<!-- [](https://github.com/NaturalIntelligence/ads/) -->
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
## Usage Trend
|
|
205
|
+
|
|
206
|
+
[Usage Trend of fast-xml-parser](https://npm-compare.com/fast-xml-parser#timeRange=THREE_YEARS)
|
|
207
|
+
|
|
208
|
+
<a href="https://npm-compare.com/fast-xml-parser#timeRange=THREE_YEARS" target="_blank">
|
|
209
|
+
<img src="https://npm-compare.com/img/npm-trend/THREE_YEARS/fast-xml-parser.png" width="50%" alt="NPM Usage Trend of fast-xml-parser" />
|
|
210
|
+
</a>
|
|
183
211
|
|
|
184
212
|
## Supporters
|
|
185
213
|
### Contributors
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fast-xml-parser",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.5.0",
|
|
4
4
|
"description": "Validate XML, Parse XML, Build XML without C/C++ based libraries",
|
|
5
5
|
"main": "./src/fxp.js",
|
|
6
6
|
"scripts": {
|
|
@@ -49,7 +49,6 @@
|
|
|
49
49
|
"@babel/register": "^7.13.8",
|
|
50
50
|
"@types/node": "20",
|
|
51
51
|
"babel-loader": "^8.2.2",
|
|
52
|
-
"cytorus": "^0.2.9",
|
|
53
52
|
"eslint": "^8.3.0",
|
|
54
53
|
"he": "^1.2.0",
|
|
55
54
|
"jasmine": "^3.6.4",
|
package/src/fxp.d.ts
CHANGED
|
@@ -30,9 +30,17 @@ type X2jOptions = {
|
|
|
30
30
|
/**
|
|
31
31
|
* Whether to ignore attributes when parsing
|
|
32
32
|
*
|
|
33
|
+
* When `true` - ignores all the attributes
|
|
34
|
+
*
|
|
35
|
+
* When `false` - parses all the attributes
|
|
36
|
+
*
|
|
37
|
+
* When `Array<string | RegExp>` - filters out attributes that match provided patterns
|
|
38
|
+
*
|
|
39
|
+
* When `Function` - calls the function for each attribute and filters out those for which the function returned `true`
|
|
40
|
+
*
|
|
33
41
|
* Defaults to `true`
|
|
34
42
|
*/
|
|
35
|
-
ignoreAttributes?: boolean;
|
|
43
|
+
ignoreAttributes?: boolean | (string | RegExp)[] | ((attrName: string, jPath: string) => boolean);
|
|
36
44
|
|
|
37
45
|
/**
|
|
38
46
|
* Whether to remove namespace string from tag and attribute names
|
|
@@ -250,11 +258,19 @@ type XmlBuilderOptions = {
|
|
|
250
258
|
textNodeName?: string;
|
|
251
259
|
|
|
252
260
|
/**
|
|
253
|
-
* Whether to ignore attributes when
|
|
261
|
+
* Whether to ignore attributes when building
|
|
262
|
+
*
|
|
263
|
+
* When `true` - ignores all the attributes
|
|
264
|
+
*
|
|
265
|
+
* When `false` - builds all the attributes
|
|
266
|
+
*
|
|
267
|
+
* When `Array<string | RegExp>` - filters out attributes that match provided patterns
|
|
268
|
+
*
|
|
269
|
+
* When `Function` - calls the function for each attribute and filters out those for which the function returned `true`
|
|
254
270
|
*
|
|
255
271
|
* Defaults to `true`
|
|
256
272
|
*/
|
|
257
|
-
ignoreAttributes?: boolean;
|
|
273
|
+
ignoreAttributes?: boolean | (string | RegExp)[] | ((attrName: string, jPath: string) => boolean);
|
|
258
274
|
|
|
259
275
|
/**
|
|
260
276
|
* Give a property name to set CDATA values to instead of merging to tag's text value
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
function getIgnoreAttributesFn(ignoreAttributes) {
|
|
2
|
+
if (typeof ignoreAttributes === 'function') {
|
|
3
|
+
return ignoreAttributes
|
|
4
|
+
}
|
|
5
|
+
if (Array.isArray(ignoreAttributes)) {
|
|
6
|
+
return (attrName) => {
|
|
7
|
+
for (const pattern of ignoreAttributes) {
|
|
8
|
+
if (typeof pattern === 'string' && attrName === pattern) {
|
|
9
|
+
return true
|
|
10
|
+
}
|
|
11
|
+
if (pattern instanceof RegExp && pattern.test(attrName)) {
|
|
12
|
+
return true
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return () => false
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
module.exports = getIgnoreAttributesFn
|
|
@@ -3,7 +3,7 @@ const {buildOptions,registerCommonValueParsers} = require("./ParserOptionsBuilde
|
|
|
3
3
|
class OutputBuilder{
|
|
4
4
|
constructor(options){
|
|
5
5
|
this.options = buildOptions(options);
|
|
6
|
-
this.registeredParsers = registerCommonValueParsers();
|
|
6
|
+
this.registeredParsers = registerCommonValueParsers(this.options);
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
registerValueParser(name,parserInstance){//existing name will override the parser without warning
|
|
@@ -3,7 +3,7 @@ const {buildOptions,registerCommonValueParsers} = require("./ParserOptionsBuilde
|
|
|
3
3
|
class OutputBuilder{
|
|
4
4
|
constructor(options){
|
|
5
5
|
this.options = buildOptions(options);
|
|
6
|
-
this.registeredParsers = registerCommonValueParsers();
|
|
6
|
+
this.registeredParsers = registerCommonValueParsers(this.options);
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
registerValueParser(name,parserInstance){//existing name will override the parser without warning
|
|
@@ -5,7 +5,7 @@ const {buildOptions,registerCommonValueParsers} = require("./ParserOptionsBuilde
|
|
|
5
5
|
class OutputBuilder{
|
|
6
6
|
constructor(builderOptions){
|
|
7
7
|
this.options = buildOptions(builderOptions);
|
|
8
|
-
this.registeredParsers = registerCommonValueParsers();
|
|
8
|
+
this.registeredParsers = registerCommonValueParsers(this.options);
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
registerValueParser(name,parserInstance){//existing name will override the parser without warning
|
|
@@ -34,6 +34,9 @@ const defaultOptions={
|
|
|
34
34
|
// "currency",
|
|
35
35
|
// "date",
|
|
36
36
|
]
|
|
37
|
+
},
|
|
38
|
+
dataType:{
|
|
39
|
+
|
|
37
40
|
}
|
|
38
41
|
}
|
|
39
42
|
|
|
@@ -75,7 +78,7 @@ function copyProperties(target, source) {
|
|
|
75
78
|
}
|
|
76
79
|
}
|
|
77
80
|
|
|
78
|
-
function registerCommonValueParsers(){
|
|
81
|
+
function registerCommonValueParsers(options){
|
|
79
82
|
return {
|
|
80
83
|
"trim": new trimParser(),
|
|
81
84
|
// "join": this.entityParser.parse,
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
const defaultOptions = {
|
|
2
|
+
maxLength: 200,
|
|
3
|
+
// locale: "en-IN"
|
|
4
|
+
}
|
|
2
5
|
const localeMap = {
|
|
3
6
|
"$":"en-US",
|
|
4
7
|
"€":"de-DE",
|
|
@@ -6,15 +9,19 @@ const localeMap = {
|
|
|
6
9
|
"¥":"ja-JP",
|
|
7
10
|
"₹":"en-IN",
|
|
8
11
|
}
|
|
12
|
+
const sign = "(?:-|\+)?";
|
|
13
|
+
const digitsAndSeparator = "(?:\d+|\d{1,3}(?:,\d{3})+)";
|
|
14
|
+
const decimalPart = "(?:\.\d{1,2})?";
|
|
15
|
+
const symbol = "(?:\$|€|¥|₹)?";
|
|
9
16
|
|
|
10
17
|
const currencyCheckRegex = /^\s*(?:-|\+)?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d{1,2})?\s*(?:\$|€|¥|₹)?\s*$/u;
|
|
11
18
|
|
|
12
19
|
class CurrencyParser{
|
|
13
20
|
constructor(options){
|
|
14
|
-
this.options = options;
|
|
21
|
+
this.options = options || defaultOptions;
|
|
15
22
|
}
|
|
16
23
|
parse(val){
|
|
17
|
-
if (typeof val === 'string') {
|
|
24
|
+
if (typeof val === 'string' && val.length <= this.options.maxLength) {
|
|
18
25
|
if(val.indexOf(",,") !== -1 && val.indexOf(".." !== -1)){
|
|
19
26
|
const match = val.match(currencyCheckRegex);
|
|
20
27
|
if(match){
|
|
@@ -28,4 +35,6 @@ class CurrencyParser{
|
|
|
28
35
|
return val;
|
|
29
36
|
}
|
|
30
37
|
}
|
|
38
|
+
CurrencyParser.defaultOptions = defaultOptions;
|
|
39
|
+
|
|
31
40
|
module.exports = CurrencyParser;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
//parse Empty Node as self closing node
|
|
3
3
|
const buildFromOrderedJs = require('./orderedJs2Xml');
|
|
4
|
+
const getIgnoreAttributesFn = require('../ignoreAttributes')
|
|
4
5
|
|
|
5
6
|
const defaultOptions = {
|
|
6
7
|
attributeNamePrefix: '@_',
|
|
@@ -38,11 +39,12 @@ const defaultOptions = {
|
|
|
38
39
|
|
|
39
40
|
function Builder(options) {
|
|
40
41
|
this.options = Object.assign({}, defaultOptions, options);
|
|
41
|
-
if (this.options.ignoreAttributes || this.options.attributesGroupName) {
|
|
42
|
+
if (this.options.ignoreAttributes === true || this.options.attributesGroupName) {
|
|
42
43
|
this.isAttribute = function(/*a*/) {
|
|
43
44
|
return false;
|
|
44
45
|
};
|
|
45
46
|
} else {
|
|
47
|
+
this.ignoreAttributesFn = getIgnoreAttributesFn(this.options.ignoreAttributes)
|
|
46
48
|
this.attrPrefixLen = this.options.attributeNamePrefix.length;
|
|
47
49
|
this.isAttribute = isAttribute;
|
|
48
50
|
}
|
|
@@ -71,13 +73,14 @@ Builder.prototype.build = function(jObj) {
|
|
|
71
73
|
[this.options.arrayNodeName] : jObj
|
|
72
74
|
}
|
|
73
75
|
}
|
|
74
|
-
return this.j2x(jObj, 0).val;
|
|
76
|
+
return this.j2x(jObj, 0, []).val;
|
|
75
77
|
}
|
|
76
78
|
};
|
|
77
79
|
|
|
78
|
-
Builder.prototype.j2x = function(jObj, level) {
|
|
80
|
+
Builder.prototype.j2x = function(jObj, level, ajPath) {
|
|
79
81
|
let attrStr = '';
|
|
80
82
|
let val = '';
|
|
83
|
+
const jPath = ajPath.join('.')
|
|
81
84
|
for (let key in jObj) {
|
|
82
85
|
if(!Object.prototype.hasOwnProperty.call(jObj, key)) continue;
|
|
83
86
|
if (typeof jObj[key] === 'undefined') {
|
|
@@ -100,9 +103,9 @@ Builder.prototype.j2x = function(jObj, level) {
|
|
|
100
103
|
} else if (typeof jObj[key] !== 'object') {
|
|
101
104
|
//premitive type
|
|
102
105
|
const attr = this.isAttribute(key);
|
|
103
|
-
if (attr) {
|
|
106
|
+
if (attr && !this.ignoreAttributesFn(attr, jPath)) {
|
|
104
107
|
attrStr += this.buildAttrPairStr(attr, '' + jObj[key]);
|
|
105
|
-
}else {
|
|
108
|
+
} else if (!attr) {
|
|
106
109
|
//tag value
|
|
107
110
|
if (key === this.options.textNodeName) {
|
|
108
111
|
let newval = this.options.tagValueProcessor(key, '' + jObj[key]);
|
|
@@ -115,6 +118,7 @@ Builder.prototype.j2x = function(jObj, level) {
|
|
|
115
118
|
//repeated nodes
|
|
116
119
|
const arrLen = jObj[key].length;
|
|
117
120
|
let listTagVal = "";
|
|
121
|
+
let listTagAttr = "";
|
|
118
122
|
for (let j = 0; j < arrLen; j++) {
|
|
119
123
|
const item = jObj[key][j];
|
|
120
124
|
if (typeof item === 'undefined') {
|
|
@@ -124,17 +128,27 @@ Builder.prototype.j2x = function(jObj, level) {
|
|
|
124
128
|
else val += this.indentate(level) + '<' + key + '/' + this.tagEndChar;
|
|
125
129
|
// val += this.indentate(level) + '<' + key + '/' + this.tagEndChar;
|
|
126
130
|
} else if (typeof item === 'object') {
|
|
127
|
-
if(this.options.oneListGroup
|
|
128
|
-
|
|
131
|
+
if(this.options.oneListGroup){
|
|
132
|
+
const result = this.j2x(item, level + 1, ajPath.concat(key));
|
|
133
|
+
listTagVal += result.val;
|
|
134
|
+
if (this.options.attributesGroupName && item.hasOwnProperty(this.options.attributesGroupName)) {
|
|
135
|
+
listTagAttr += result.attrStr
|
|
136
|
+
}
|
|
129
137
|
}else{
|
|
130
|
-
listTagVal += this.processTextOrObjNode(item, key, level)
|
|
138
|
+
listTagVal += this.processTextOrObjNode(item, key, level, ajPath)
|
|
131
139
|
}
|
|
132
140
|
} else {
|
|
133
|
-
|
|
141
|
+
if (this.options.oneListGroup) {
|
|
142
|
+
let textValue = this.options.tagValueProcessor(key, item);
|
|
143
|
+
textValue = this.replaceEntitiesValue(textValue);
|
|
144
|
+
listTagVal += textValue;
|
|
145
|
+
} else {
|
|
146
|
+
listTagVal += this.buildTextValNode(item, key, '', level);
|
|
147
|
+
}
|
|
134
148
|
}
|
|
135
149
|
}
|
|
136
150
|
if(this.options.oneListGroup){
|
|
137
|
-
listTagVal = this.buildObjectNode(listTagVal, key,
|
|
151
|
+
listTagVal = this.buildObjectNode(listTagVal, key, listTagAttr, level);
|
|
138
152
|
}
|
|
139
153
|
val += listTagVal;
|
|
140
154
|
} else {
|
|
@@ -146,7 +160,7 @@ Builder.prototype.j2x = function(jObj, level) {
|
|
|
146
160
|
attrStr += this.buildAttrPairStr(Ks[j], '' + jObj[key][Ks[j]]);
|
|
147
161
|
}
|
|
148
162
|
} else {
|
|
149
|
-
val += this.processTextOrObjNode(jObj[key], key, level)
|
|
163
|
+
val += this.processTextOrObjNode(jObj[key], key, level, ajPath)
|
|
150
164
|
}
|
|
151
165
|
}
|
|
152
166
|
}
|
|
@@ -161,8 +175,8 @@ Builder.prototype.buildAttrPairStr = function(attrName, val){
|
|
|
161
175
|
} else return ' ' + attrName + '="' + val + '"';
|
|
162
176
|
}
|
|
163
177
|
|
|
164
|
-
function processTextOrObjNode (object, key, level) {
|
|
165
|
-
const result = this.j2x(object, level + 1);
|
|
178
|
+
function processTextOrObjNode (object, key, level, ajPath) {
|
|
179
|
+
const result = this.j2x(object, level + 1, ajPath.concat(key));
|
|
166
180
|
if (object[this.options.textNodeName] !== undefined && Object.keys(object).length === 1) {
|
|
167
181
|
return this.buildTextValNode(object[this.options.textNodeName], key, result.attrStr, level);
|
|
168
182
|
} else {
|
|
@@ -5,6 +5,7 @@ const util = require('../util');
|
|
|
5
5
|
const xmlNode = require('./xmlNode');
|
|
6
6
|
const readDocType = require("./DocTypeReader");
|
|
7
7
|
const toNumber = require("strnum");
|
|
8
|
+
const getIgnoreAttributesFn = require('../ignoreAttributes')
|
|
8
9
|
|
|
9
10
|
// const regx =
|
|
10
11
|
// '<((!\\[CDATA\\[([\\s\\S]*?)(]]>))|((NAME:)?(NAME))([^>]*)>|((\\/)(NAME)\\s*>))([^<]*)'
|
|
@@ -53,6 +54,7 @@ class OrderedObjParser{
|
|
|
53
54
|
this.readStopNodeData = readStopNodeData;
|
|
54
55
|
this.saveTextToParentTag = saveTextToParentTag;
|
|
55
56
|
this.addChild = addChild;
|
|
57
|
+
this.ignoreAttributesFn = getIgnoreAttributesFn(this.options.ignoreAttributes)
|
|
56
58
|
}
|
|
57
59
|
|
|
58
60
|
}
|
|
@@ -125,7 +127,7 @@ function resolveNameSpace(tagname) {
|
|
|
125
127
|
const attrsRegx = new RegExp('([^\\s=]+)\\s*(=\\s*([\'"])([\\s\\S]*?)\\3)?', 'gm');
|
|
126
128
|
|
|
127
129
|
function buildAttributesMap(attrStr, jPath, tagName) {
|
|
128
|
-
if (
|
|
130
|
+
if (this.options.ignoreAttributes !== true && typeof attrStr === 'string') {
|
|
129
131
|
// attrStr = attrStr.replace(/\r?\n/g, ' ');
|
|
130
132
|
//attrStr = attrStr || attrStr.trim();
|
|
131
133
|
|
|
@@ -134,6 +136,9 @@ function buildAttributesMap(attrStr, jPath, tagName) {
|
|
|
134
136
|
const attrs = {};
|
|
135
137
|
for (let i = 0; i < len; i++) {
|
|
136
138
|
const attrName = this.resolveNameSpace(matches[i][1]);
|
|
139
|
+
if (this.ignoreAttributesFn(attrName, jPath)) {
|
|
140
|
+
continue
|
|
141
|
+
}
|
|
137
142
|
let oldVal = matches[i][4];
|
|
138
143
|
let aName = this.options.attributeNamePrefix + attrName;
|
|
139
144
|
if (attrName.length) {
|