xml-toolkit 1.0.60 → 1.0.61
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/index.js +2 -1
- package/lib/XMLMarshaller.js +56 -23
- package/lib/XMLNode.js +1 -1
- package/lib/{XMLPrinter.js → printer/Base.js} +19 -30
- package/lib/printer/XMLPrinter.js +39 -0
- package/lib/printer/XMLStreamPrinter.js +122 -0
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -20,7 +20,8 @@ module.exports = {
|
|
|
20
20
|
XMLNode: require ('./lib/XMLNode'),
|
|
21
21
|
XMLLexer: require ('./lib/XMLLexer'),
|
|
22
22
|
XMLParser: require ('./lib/XMLParser'),
|
|
23
|
-
XMLPrinter: require ('./lib/XMLPrinter'),
|
|
23
|
+
XMLPrinter: require ('./lib/printer/XMLPrinter'),
|
|
24
|
+
XMLStreamPrinter: require ('./lib/printer/XMLStreamPrinter'),
|
|
24
25
|
XMLReader: require ('./lib/XMLReader'),
|
|
25
26
|
XMLSchema: require ('./lib/XMLSchema'),
|
|
26
27
|
XMLSchemaBuiltIn: require ('./lib/XMLSchemaBuiltIn'),
|
package/lib/XMLMarshaller.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
const assert = require ('assert')
|
|
2
2
|
const NamespacePrefixesMap = require ('./NamespacePrefixesMap.js')
|
|
3
|
-
const XMLPrinter = require ('./XMLPrinter.js')
|
|
3
|
+
const XMLPrinter = require ('./printer/XMLPrinter.js')
|
|
4
|
+
const XMLStreamPrinter = require ('./printer/XMLStreamPrinter.js')
|
|
5
|
+
const {Readable} = require ('node:stream')
|
|
4
6
|
|
|
5
7
|
const XSI_TYPE = Symbol.for ('type')
|
|
6
8
|
|
|
@@ -15,10 +17,10 @@ const XMLMarshaller = class {
|
|
|
15
17
|
this.schemaElement = this.schema.get (localName); assert (this.schemaElement, 'No schema element found for namespaceURI = ' + namespaceURI + ', localName = ' + localName)
|
|
16
18
|
|
|
17
19
|
this.ns = new NamespacePrefixesMap (xs)
|
|
18
|
-
|
|
20
|
+
|
|
19
21
|
this.isNsDumped = false
|
|
20
|
-
|
|
21
|
-
this.printer = new XMLPrinter (printerOptions)
|
|
22
|
+
|
|
23
|
+
this.printer = new ('out' in printerOptions ? XMLStreamPrinter : XMLPrinter) (printerOptions)
|
|
22
24
|
|
|
23
25
|
}
|
|
24
26
|
|
|
@@ -40,7 +42,18 @@ const XMLMarshaller = class {
|
|
|
40
42
|
|
|
41
43
|
try {
|
|
42
44
|
|
|
43
|
-
this.appendElement (schemaElement, data, this.ns.QName (o.localName || attributes.name, targetNamespace))
|
|
45
|
+
const result = this.appendElement (schemaElement, data, this.ns.QName (o.localName || attributes.name, targetNamespace))
|
|
46
|
+
|
|
47
|
+
if (result instanceof Promise) {
|
|
48
|
+
|
|
49
|
+
result.then (printer.end, printer.destroy)
|
|
50
|
+
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
|
|
54
|
+
return printer.text
|
|
55
|
+
|
|
56
|
+
}
|
|
44
57
|
|
|
45
58
|
}
|
|
46
59
|
catch (cause) {
|
|
@@ -51,17 +64,17 @@ const XMLMarshaller = class {
|
|
|
51
64
|
|
|
52
65
|
}
|
|
53
66
|
|
|
54
|
-
return printer.text
|
|
55
|
-
|
|
56
67
|
}
|
|
57
68
|
|
|
58
69
|
appendElement (node, data, qName) {
|
|
59
70
|
|
|
60
71
|
this.appendStartTag (node, data, qName)
|
|
61
|
-
|
|
62
|
-
this.appendElementBody (node, data)
|
|
63
|
-
|
|
64
|
-
|
|
72
|
+
|
|
73
|
+
const result = this.appendElementBody (node, data), finish = () => this.printer.closeElement ()
|
|
74
|
+
|
|
75
|
+
if (!(result instanceof Promise)) return finish ()
|
|
76
|
+
|
|
77
|
+
return result.then (finish, this.printer.destroy)
|
|
65
78
|
|
|
66
79
|
}
|
|
67
80
|
|
|
@@ -71,7 +84,7 @@ const XMLMarshaller = class {
|
|
|
71
84
|
|
|
72
85
|
if (!this.isNsDumped) {
|
|
73
86
|
|
|
74
|
-
this.printer.
|
|
87
|
+
this.printer.write (this.ns.toString ())
|
|
75
88
|
|
|
76
89
|
this.isNsDumped = true
|
|
77
90
|
|
|
@@ -110,13 +123,19 @@ const XMLMarshaller = class {
|
|
|
110
123
|
const {attributes: {type}, children} = node
|
|
111
124
|
|
|
112
125
|
if (data && data [XSI_TYPE]) {
|
|
113
|
-
|
|
114
|
-
|
|
126
|
+
|
|
127
|
+
const d = {}; for (let k in data) d [k] = data [k]
|
|
128
|
+
|
|
129
|
+
return this.appendContent (this.schema.getType (data [XSI_TYPE]), d)
|
|
130
|
+
|
|
115
131
|
}
|
|
132
|
+
else if (type) {
|
|
116
133
|
|
|
117
|
-
|
|
134
|
+
return this.appendContent (this.xs.getType (type), data)
|
|
118
135
|
|
|
119
|
-
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return this.appendAllContent (children, data)
|
|
120
139
|
|
|
121
140
|
}
|
|
122
141
|
|
|
@@ -142,7 +161,7 @@ const XMLMarshaller = class {
|
|
|
142
161
|
|
|
143
162
|
return this.printer.writeAttribute (
|
|
144
163
|
this.ns.QName (name, targetNamespace),
|
|
145
|
-
this.xs.getAttributeSimpleType (node).stringify (v)
|
|
164
|
+
this.xs.getAttributeSimpleType (node).stringify (v) // throws
|
|
146
165
|
)
|
|
147
166
|
|
|
148
167
|
case 'extension':
|
|
@@ -178,7 +197,7 @@ const XMLMarshaller = class {
|
|
|
178
197
|
|
|
179
198
|
const type = this.xs.getSimpleType (node)
|
|
180
199
|
|
|
181
|
-
const xml = type.stringify (data)
|
|
200
|
+
const xml = type.stringify (data) // throws
|
|
182
201
|
|
|
183
202
|
this.printer.writeCharacters (xml)
|
|
184
203
|
|
|
@@ -192,6 +211,8 @@ const XMLMarshaller = class {
|
|
|
192
211
|
|
|
193
212
|
const qName = this.ns.QName (name, targetNamespace)
|
|
194
213
|
|
|
214
|
+
if (v instanceof Readable) return this.printer.forEach (v, d => this.appendElement (node, d, qName))
|
|
215
|
+
|
|
195
216
|
if (!Array.isArray (v)) return this.appendElement (node, v, qName)
|
|
196
217
|
|
|
197
218
|
for (const d of v) this.appendElement (node, d, qName)
|
|
@@ -199,17 +220,29 @@ const XMLMarshaller = class {
|
|
|
199
220
|
return
|
|
200
221
|
|
|
201
222
|
case 'extension':
|
|
202
|
-
|
|
203
|
-
this.
|
|
204
|
-
|
|
223
|
+
|
|
224
|
+
return this.appendAllContent ([this.xs.getType (attributes.base), ...children], data)
|
|
225
|
+
|
|
205
226
|
default:
|
|
206
227
|
|
|
207
|
-
|
|
228
|
+
return this.appendAllContent (children, data)
|
|
208
229
|
|
|
209
230
|
}
|
|
210
231
|
|
|
211
232
|
}
|
|
212
|
-
|
|
233
|
+
|
|
234
|
+
appendAllContent (list, data) {
|
|
235
|
+
|
|
236
|
+
for (let i = 0; i < list.length; i ++) {
|
|
237
|
+
|
|
238
|
+
const result = this.appendContent (list [i], data); if (!(result instanceof Promise)) continue
|
|
239
|
+
|
|
240
|
+
return result.then (this.appendAllContent (list.slice (i + 1), data), this.printer.destroy)
|
|
241
|
+
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
}
|
|
245
|
+
|
|
213
246
|
}
|
|
214
247
|
|
|
215
248
|
module.exports = XMLMarshaller
|
package/lib/XMLNode.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const os = require ('os')
|
|
2
2
|
const stringEscape = require ('string-escape-map')
|
|
3
|
-
const SAXEvent = require ('
|
|
3
|
+
const SAXEvent = require ('../SAXEvent.js')
|
|
4
4
|
|
|
5
5
|
const CH_QQ = '"'.charCodeAt (0)
|
|
6
6
|
const CH_GT = '>'.charCodeAt (0)
|
|
@@ -19,7 +19,7 @@ const ESC = [
|
|
|
19
19
|
|
|
20
20
|
const isSafeNonNegative = value => Number.isSafeInteger (value) && value >= 0
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
module.exports = class {
|
|
23
23
|
|
|
24
24
|
constructor (o = {}) {
|
|
25
25
|
|
|
@@ -85,7 +85,6 @@ const XMLPrinter = class {
|
|
|
85
85
|
|
|
86
86
|
reset () {
|
|
87
87
|
|
|
88
|
-
this.text = ''
|
|
89
88
|
this.stack = []
|
|
90
89
|
this.isOpening = false
|
|
91
90
|
|
|
@@ -97,15 +96,7 @@ const XMLPrinter = class {
|
|
|
97
96
|
|
|
98
97
|
newLine (delta = 0) {
|
|
99
98
|
|
|
100
|
-
this.
|
|
101
|
-
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
get lastCharCode () {
|
|
105
|
-
|
|
106
|
-
const {text} = this
|
|
107
|
-
|
|
108
|
-
return text.charCodeAt (text.length - 1)
|
|
99
|
+
this.write (`${this.EOL}${this.space.repeat (this.level + this.stack.length + delta)}`)
|
|
109
100
|
|
|
110
101
|
}
|
|
111
102
|
|
|
@@ -113,12 +104,12 @@ const XMLPrinter = class {
|
|
|
113
104
|
|
|
114
105
|
if (this.stack.length !== 0) {
|
|
115
106
|
if (this.attrSpace && this.lastCharCode === CH_QQ) this.newLine (-1)
|
|
116
|
-
if (this.isOpening) this.
|
|
107
|
+
if (this.isOpening) this.write (`>`)
|
|
117
108
|
}
|
|
118
109
|
|
|
119
|
-
if (this.space && this.
|
|
110
|
+
if (this.space && !this.isVirgin) this.newLine ()
|
|
120
111
|
|
|
121
|
-
this.
|
|
112
|
+
this.write (`<${name}`)
|
|
122
113
|
this.stack.push (name)
|
|
123
114
|
|
|
124
115
|
this.isOpening = true
|
|
@@ -139,16 +130,16 @@ const XMLPrinter = class {
|
|
|
139
130
|
|
|
140
131
|
this.newLine (-1)
|
|
141
132
|
|
|
142
|
-
this.
|
|
133
|
+
this.write (this.attrSpace)
|
|
143
134
|
|
|
144
135
|
}
|
|
145
136
|
else {
|
|
146
137
|
|
|
147
|
-
this.
|
|
138
|
+
this.write (' ')
|
|
148
139
|
|
|
149
140
|
}
|
|
150
141
|
|
|
151
|
-
this.
|
|
142
|
+
this.write (`${name}="${this.ESC_ATTR.escape (value)}"`)
|
|
152
143
|
|
|
153
144
|
return this
|
|
154
145
|
|
|
@@ -170,11 +161,11 @@ const XMLPrinter = class {
|
|
|
170
161
|
|
|
171
162
|
if (this.isOpening) {
|
|
172
163
|
if (this.attrSpace && this.lastCharCode === CH_QQ) this.newLine (-1)
|
|
173
|
-
this.
|
|
164
|
+
this.write (`>`)
|
|
174
165
|
this.isOpening = false
|
|
175
166
|
}
|
|
176
167
|
|
|
177
|
-
this.
|
|
168
|
+
this.write (value)
|
|
178
169
|
|
|
179
170
|
return this
|
|
180
171
|
|
|
@@ -186,12 +177,12 @@ const XMLPrinter = class {
|
|
|
186
177
|
|
|
187
178
|
if (this.isOpening) {
|
|
188
179
|
if (this.attrSpace && this.lastCharCode === CH_QQ) this.newLine ()
|
|
189
|
-
this.
|
|
180
|
+
this.write (` />`)
|
|
190
181
|
this.isOpening = false
|
|
191
182
|
}
|
|
192
183
|
else {
|
|
193
184
|
if (this.space && this.lastCharCode === CH_GT) this.newLine ()
|
|
194
|
-
this.
|
|
185
|
+
this.write (`</${name}>`)
|
|
195
186
|
}
|
|
196
187
|
|
|
197
188
|
return this
|
|
@@ -271,18 +262,16 @@ const XMLPrinter = class {
|
|
|
271
262
|
|
|
272
263
|
if (this.stack.length !== 0) throw Error ('The document is already started')
|
|
273
264
|
|
|
274
|
-
this.
|
|
265
|
+
this.write ('<?xml version="1.0"')
|
|
275
266
|
|
|
276
|
-
if (encoding != null) this.
|
|
267
|
+
if (encoding != null) this.write (` encoding="${encoding}"`)
|
|
277
268
|
|
|
278
|
-
if (standalone != null) this.
|
|
269
|
+
if (standalone != null) this.write (` standalone="${standalone ? 'yes' : 'no'}"`)
|
|
279
270
|
|
|
280
|
-
this.
|
|
271
|
+
this.write ('?>')
|
|
281
272
|
|
|
282
273
|
return this
|
|
283
274
|
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
}
|
|
275
|
+
}
|
|
287
276
|
|
|
288
|
-
|
|
277
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const XMLPrinter = class extends (require ('./Base.js')) {
|
|
2
|
+
|
|
3
|
+
get destroy () {
|
|
4
|
+
|
|
5
|
+
return err => {throw err}
|
|
6
|
+
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
reset () {
|
|
10
|
+
|
|
11
|
+
this.text = ''
|
|
12
|
+
|
|
13
|
+
return super.reset ()
|
|
14
|
+
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
get lastCharCode () {
|
|
18
|
+
|
|
19
|
+
const {text} = this
|
|
20
|
+
|
|
21
|
+
return text.charCodeAt (text.length - 1)
|
|
22
|
+
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
get isVirgin () {
|
|
26
|
+
|
|
27
|
+
return this.text.length === 0
|
|
28
|
+
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
write (s) {
|
|
32
|
+
|
|
33
|
+
this.text += s
|
|
34
|
+
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
module.exports = XMLPrinter
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
const {Writable} = require ('node:stream')
|
|
2
|
+
|
|
3
|
+
const XMLStreamPrinter = class extends (require ('./Base.js')) {
|
|
4
|
+
|
|
5
|
+
#inStreams = []
|
|
6
|
+
#isVirgin = true
|
|
7
|
+
#lastCharCode = 0
|
|
8
|
+
#open = true
|
|
9
|
+
|
|
10
|
+
constructor (o) {
|
|
11
|
+
|
|
12
|
+
if (!o || typeof o !== 'object' || !('out' in o)) throw Error (`XMLStreamPrinter requires an .out option`)
|
|
13
|
+
if (!(o.out instanceof Writable)) throw Error (`.out must be Writable, ${typeof o.out} ${o.out} found`)
|
|
14
|
+
|
|
15
|
+
super (o)
|
|
16
|
+
|
|
17
|
+
this.out = o.out
|
|
18
|
+
this.out.on ('drain', () => this.open = true)
|
|
19
|
+
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
get end () {
|
|
23
|
+
|
|
24
|
+
return () => this.out.end ()
|
|
25
|
+
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
get destroy () {
|
|
29
|
+
|
|
30
|
+
return err => this.out.destroy (err)
|
|
31
|
+
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
get inStream () {
|
|
35
|
+
|
|
36
|
+
return this.#inStreams.at (-1)
|
|
37
|
+
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
forEach (stream, onData) {
|
|
41
|
+
|
|
42
|
+
if (this.#inStreams.length !== 0) return this.destroy (Error ('Nested streams not yet supported'))
|
|
43
|
+
|
|
44
|
+
if (!this.#open) stream.pause ()
|
|
45
|
+
|
|
46
|
+
this.#inStreams.push (stream)
|
|
47
|
+
|
|
48
|
+
return new Promise ((ok, fail) => {
|
|
49
|
+
|
|
50
|
+
stream.on ('error', err => {
|
|
51
|
+
|
|
52
|
+
this.destroy (err)
|
|
53
|
+
|
|
54
|
+
fail (err)
|
|
55
|
+
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
stream.on ('end', () => {
|
|
59
|
+
|
|
60
|
+
this.#inStreams.pop ()
|
|
61
|
+
|
|
62
|
+
ok ()
|
|
63
|
+
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
stream.on ('data', data => {
|
|
67
|
+
|
|
68
|
+
try {
|
|
69
|
+
|
|
70
|
+
onData (data)
|
|
71
|
+
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
|
|
75
|
+
stream.destroy (err)
|
|
76
|
+
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
set open (nowOpen) {
|
|
86
|
+
|
|
87
|
+
const wasOpen = this.#open; if (wasOpen === nowOpen) return
|
|
88
|
+
|
|
89
|
+
this.#open = nowOpen
|
|
90
|
+
|
|
91
|
+
if (!this.inStream) return
|
|
92
|
+
|
|
93
|
+
nowOpen ? this.inStream.resume () : this.inStream.pause ()
|
|
94
|
+
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
get lastCharCode () {
|
|
98
|
+
|
|
99
|
+
return this.#lastCharCode
|
|
100
|
+
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
get isVirgin () {
|
|
104
|
+
|
|
105
|
+
return this.#isVirgin
|
|
106
|
+
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
write (s) {
|
|
110
|
+
|
|
111
|
+
const {length} = s; if (length === 0) return
|
|
112
|
+
|
|
113
|
+
this.#lastCharCode = s.charCodeAt (length - 1)
|
|
114
|
+
this.#isVirgin = false
|
|
115
|
+
|
|
116
|
+
this.open = this.out.write (s)
|
|
117
|
+
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
module.exports = XMLStreamPrinter
|