@brickhouse-tech/xml2js 0.6.3 → 1.1.3
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/lib/bom.js +7 -12
- package/lib/builder.js +119 -98
- package/lib/defaults.js +74 -71
- package/lib/parser.js +356 -342
- package/lib/processors.js +23 -29
- package/lib/xml2js.js +20 -39
- package/package.json +22 -12
package/lib/bom.js
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
(
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
return str;
|
|
9
|
-
}
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
}).call(this);
|
|
1
|
+
export function stripBOM(str) {
|
|
2
|
+
if (str[0] === '\uFEFF') {
|
|
3
|
+
return str.substring(1);
|
|
4
|
+
} else {
|
|
5
|
+
return str;
|
|
6
|
+
}
|
|
7
|
+
}
|
package/lib/builder.js
CHANGED
|
@@ -1,93 +1,110 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
"use strict";
|
|
4
|
-
var builder, defaults, escapeCDATA, requiresCDATA, wrapCDATA,
|
|
5
|
-
hasProp = {}.hasOwnProperty;
|
|
1
|
+
import builder from 'xmlbuilder';
|
|
2
|
+
import { defaults } from './defaults.js';
|
|
6
3
|
|
|
7
|
-
|
|
4
|
+
function requiresCDATA(entry) {
|
|
5
|
+
return typeof entry === "string" && (entry.indexOf('&') >= 0 || entry.indexOf('>') >= 0 || entry.indexOf('<') >= 0);
|
|
6
|
+
}
|
|
8
7
|
|
|
9
|
-
|
|
8
|
+
// Note that we do this manually instead of using xmlbuilder's `.dat` method
|
|
9
|
+
// since it does not support escaping the CDATA close entity (throws an error if
|
|
10
|
+
// it exists, and if it's pre-escaped).
|
|
11
|
+
function wrapCDATA(entry) {
|
|
12
|
+
return `<![CDATA[${escapeCDATA(entry)}]]>`;
|
|
13
|
+
}
|
|
10
14
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
15
|
+
function escapeCDATA(entry) {
|
|
16
|
+
// Split the CDATA section in two;
|
|
17
|
+
// The first contains the ']]'
|
|
18
|
+
// The second contains the '>'
|
|
19
|
+
// When later parsed, it will be put back together as ']]>'
|
|
20
|
+
return entry.replace(']]>', ']]]]><![CDATA[>');
|
|
21
|
+
}
|
|
14
22
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
exports.Builder = (function() {
|
|
24
|
-
function Builder(opts) {
|
|
25
|
-
var key, ref, value;
|
|
26
|
-
this.options = {};
|
|
27
|
-
ref = defaults["0.2"];
|
|
28
|
-
for (key in ref) {
|
|
29
|
-
if (!hasProp.call(ref, key)) continue;
|
|
30
|
-
value = ref[key];
|
|
31
|
-
this.options[key] = value;
|
|
23
|
+
export class Builder {
|
|
24
|
+
constructor(opts) {
|
|
25
|
+
// copy this versions default options
|
|
26
|
+
this.options = {};
|
|
27
|
+
for (const key in defaults["0.2"]) {
|
|
28
|
+
if (Object.prototype.hasOwnProperty.call(defaults["0.2"], key)) {
|
|
29
|
+
this.options[key] = defaults["0.2"][key];
|
|
32
30
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
31
|
+
}
|
|
32
|
+
// overwrite them with the specified options, if any
|
|
33
|
+
if (opts) {
|
|
34
|
+
for (const key in opts) {
|
|
35
|
+
if (Object.prototype.hasOwnProperty.call(opts, key)) {
|
|
36
|
+
this.options[key] = opts[key];
|
|
37
|
+
}
|
|
37
38
|
}
|
|
38
39
|
}
|
|
40
|
+
}
|
|
39
41
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
42
|
+
buildObject(rootObj) {
|
|
43
|
+
const attrkey = this.options.attrkey;
|
|
44
|
+
const charkey = this.options.charkey;
|
|
45
|
+
|
|
46
|
+
let rootName;
|
|
47
|
+
// If there is a sane-looking first element to use as the root,
|
|
48
|
+
// and the user hasn't specified a non-default rootName,
|
|
49
|
+
if (Object.keys(rootObj).length === 1 && this.options.rootName === defaults['0.2'].rootName) {
|
|
50
|
+
// we'll take the first element as the root element
|
|
51
|
+
rootName = Object.keys(rootObj)[0];
|
|
52
|
+
rootObj = rootObj[rootName];
|
|
53
|
+
} else {
|
|
54
|
+
// otherwise we'll use whatever they've set, or the default
|
|
55
|
+
rootName = this.options.rootName;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const render = (element, obj) => {
|
|
59
|
+
if (typeof obj !== 'object') {
|
|
60
|
+
// single element, just append it as text
|
|
61
|
+
if (this.options.cdata && requiresCDATA(obj)) {
|
|
62
|
+
element.raw(wrapCDATA(obj));
|
|
63
|
+
} else {
|
|
64
|
+
element.txt(obj);
|
|
65
|
+
}
|
|
66
|
+
} else if (Array.isArray(obj)) {
|
|
67
|
+
// fix issue #119
|
|
68
|
+
for (const index in obj) {
|
|
69
|
+
if (Object.prototype.hasOwnProperty.call(obj, index)) {
|
|
70
|
+
const child = obj[index];
|
|
71
|
+
for (const key in child) {
|
|
72
|
+
if (Object.prototype.hasOwnProperty.call(child, key)) {
|
|
73
|
+
element = render(element.ele(key), child[key]).up();
|
|
66
74
|
}
|
|
67
75
|
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
} else {
|
|
79
|
+
for (const key in obj) {
|
|
80
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
81
|
+
const child = obj[key];
|
|
82
|
+
// Case #1 Attribute
|
|
83
|
+
if (key === attrkey) {
|
|
84
|
+
if (typeof child === "object") {
|
|
85
|
+
// Inserts tag attributes
|
|
86
|
+
for (const attr in child) {
|
|
87
|
+
if (Object.prototype.hasOwnProperty.call(child, attr)) {
|
|
88
|
+
element = element.att(attr, child[attr]);
|
|
77
89
|
}
|
|
78
90
|
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
} else
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// Case #2 Char data (CDATA, etc.)
|
|
94
|
+
else if (key === charkey) {
|
|
95
|
+
if (this.options.cdata && requiresCDATA(child)) {
|
|
96
|
+
element = element.raw(wrapCDATA(child));
|
|
97
|
+
} else {
|
|
98
|
+
element = element.txt(child);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// Case #3 Array data
|
|
102
|
+
else if (Array.isArray(child)) {
|
|
103
|
+
for (const index in child) {
|
|
104
|
+
if (Object.prototype.hasOwnProperty.call(child, index)) {
|
|
105
|
+
const entry = child[index];
|
|
89
106
|
if (typeof entry === 'string') {
|
|
90
|
-
if (
|
|
107
|
+
if (this.options.cdata && requiresCDATA(entry)) {
|
|
91
108
|
element = element.ele(key).raw(wrapCDATA(entry)).up();
|
|
92
109
|
} else {
|
|
93
110
|
element = element.ele(key, entry).up();
|
|
@@ -96,32 +113,36 @@
|
|
|
96
113
|
element = render(element.ele(key), entry).up();
|
|
97
114
|
}
|
|
98
115
|
}
|
|
99
|
-
}
|
|
100
|
-
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// Case #4 Objects
|
|
119
|
+
else if (typeof child === "object") {
|
|
120
|
+
element = render(element.ele(key), child).up();
|
|
121
|
+
}
|
|
122
|
+
// Case #5 String and remaining types
|
|
123
|
+
else {
|
|
124
|
+
if (typeof child === 'string' && this.options.cdata && requiresCDATA(child)) {
|
|
125
|
+
element = element.ele(key).raw(wrapCDATA(child)).up();
|
|
101
126
|
} else {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
if (child == null) {
|
|
106
|
-
child = '';
|
|
107
|
-
}
|
|
108
|
-
element = element.ele(key, child.toString()).up();
|
|
127
|
+
let childValue = child;
|
|
128
|
+
if (child == null) {
|
|
129
|
+
childValue = '';
|
|
109
130
|
}
|
|
131
|
+
element = element.ele(key, childValue.toString()).up();
|
|
110
132
|
}
|
|
111
133
|
}
|
|
112
134
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
})(this);
|
|
116
|
-
rootElement = builder.create(rootName, this.options.xmldec, this.options.doctype, {
|
|
117
|
-
headless: this.options.headless,
|
|
118
|
-
allowSurrogateChars: this.options.allowSurrogateChars
|
|
119
|
-
});
|
|
120
|
-
return render(rootElement, rootObj).end(this.options.renderOpts);
|
|
121
|
-
};
|
|
135
|
+
}
|
|
136
|
+
}
|
|
122
137
|
|
|
123
|
-
|
|
138
|
+
return element;
|
|
139
|
+
};
|
|
124
140
|
|
|
125
|
-
|
|
141
|
+
const rootElement = builder.create(rootName, this.options.xmldec, this.options.doctype, {
|
|
142
|
+
headless: this.options.headless,
|
|
143
|
+
allowSurrogateChars: this.options.allowSurrogateChars
|
|
144
|
+
});
|
|
126
145
|
|
|
127
|
-
|
|
146
|
+
return render(rootElement, rootObj).end(this.options.renderOpts);
|
|
147
|
+
}
|
|
148
|
+
}
|
package/lib/defaults.js
CHANGED
|
@@ -1,72 +1,75 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
mergeAttrs: false,
|
|
39
|
-
explicitRoot: true,
|
|
40
|
-
validator: null,
|
|
41
|
-
xmlns: false,
|
|
42
|
-
explicitChildren: false,
|
|
43
|
-
preserveChildrenOrder: false,
|
|
44
|
-
childkey: '$$',
|
|
45
|
-
charsAsChildren: false,
|
|
46
|
-
includeWhiteChars: false,
|
|
47
|
-
async: false,
|
|
48
|
-
strict: true,
|
|
49
|
-
attrNameProcessors: null,
|
|
50
|
-
attrValueProcessors: null,
|
|
51
|
-
tagNameProcessors: null,
|
|
52
|
-
valueProcessors: null,
|
|
53
|
-
rootName: 'root',
|
|
54
|
-
xmldec: {
|
|
55
|
-
'version': '1.0',
|
|
56
|
-
'encoding': 'UTF-8',
|
|
57
|
-
'standalone': true
|
|
58
|
-
},
|
|
59
|
-
doctype: null,
|
|
60
|
-
renderOpts: {
|
|
61
|
-
'pretty': true,
|
|
62
|
-
'indent': ' ',
|
|
63
|
-
'newline': '\n'
|
|
64
|
-
},
|
|
65
|
-
headless: false,
|
|
66
|
-
chunkSize: 10000,
|
|
67
|
-
emptyTag: '',
|
|
68
|
-
cdata: false
|
|
69
|
-
}
|
|
70
|
-
};
|
|
1
|
+
export const defaults = {
|
|
2
|
+
"0.1": {
|
|
3
|
+
explicitCharkey: false,
|
|
4
|
+
trim: true,
|
|
5
|
+
// normalize implicates trimming, just so you know
|
|
6
|
+
normalize: true,
|
|
7
|
+
// normalize tag names to lower case
|
|
8
|
+
normalizeTags: false,
|
|
9
|
+
// set default attribute object key
|
|
10
|
+
attrkey: "@",
|
|
11
|
+
// set default char object key
|
|
12
|
+
charkey: "#",
|
|
13
|
+
// always put child nodes in an array
|
|
14
|
+
explicitArray: false,
|
|
15
|
+
// ignore all attributes regardless
|
|
16
|
+
ignoreAttrs: false,
|
|
17
|
+
// merge attributes and child elements onto parent object. this may
|
|
18
|
+
// cause collisions.
|
|
19
|
+
mergeAttrs: false,
|
|
20
|
+
explicitRoot: false,
|
|
21
|
+
validator: null,
|
|
22
|
+
xmlns: false,
|
|
23
|
+
// fold children elements into dedicated property (works only in 0.2)
|
|
24
|
+
explicitChildren: false,
|
|
25
|
+
childkey: '@@',
|
|
26
|
+
charsAsChildren: false,
|
|
27
|
+
// include white-space only text nodes
|
|
28
|
+
includeWhiteChars: false,
|
|
29
|
+
// callbacks are async? not in 0.1 mode
|
|
30
|
+
async: false,
|
|
31
|
+
strict: true,
|
|
32
|
+
attrNameProcessors: null,
|
|
33
|
+
attrValueProcessors: null,
|
|
34
|
+
tagNameProcessors: null,
|
|
35
|
+
valueProcessors: null,
|
|
36
|
+
emptyTag: ''
|
|
37
|
+
},
|
|
71
38
|
|
|
72
|
-
|
|
39
|
+
"0.2": {
|
|
40
|
+
explicitCharkey: false,
|
|
41
|
+
trim: false,
|
|
42
|
+
normalize: false,
|
|
43
|
+
normalizeTags: false,
|
|
44
|
+
attrkey: "$",
|
|
45
|
+
charkey: "_",
|
|
46
|
+
explicitArray: true,
|
|
47
|
+
ignoreAttrs: false,
|
|
48
|
+
mergeAttrs: false,
|
|
49
|
+
explicitRoot: true,
|
|
50
|
+
validator: null,
|
|
51
|
+
xmlns: false,
|
|
52
|
+
explicitChildren: false,
|
|
53
|
+
preserveChildrenOrder: false,
|
|
54
|
+
childkey: '$$',
|
|
55
|
+
charsAsChildren: false,
|
|
56
|
+
// include white-space only text nodes
|
|
57
|
+
includeWhiteChars: false,
|
|
58
|
+
// not async in 0.2 mode either
|
|
59
|
+
async: false,
|
|
60
|
+
strict: true,
|
|
61
|
+
attrNameProcessors: null,
|
|
62
|
+
attrValueProcessors: null,
|
|
63
|
+
tagNameProcessors: null,
|
|
64
|
+
valueProcessors: null,
|
|
65
|
+
// xml building options
|
|
66
|
+
rootName: 'root',
|
|
67
|
+
xmldec: { 'version': '1.0', 'encoding': 'UTF-8', 'standalone': true },
|
|
68
|
+
doctype: null,
|
|
69
|
+
renderOpts: { 'pretty': true, 'indent': ' ', 'newline': '\n' },
|
|
70
|
+
headless: false,
|
|
71
|
+
chunkSize: 10000,
|
|
72
|
+
emptyTag: '',
|
|
73
|
+
cdata: false
|
|
74
|
+
}
|
|
75
|
+
};
|