xml-toolkit 1.0.43 → 1.0.46

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/XMLLexer.js CHANGED
@@ -14,11 +14,10 @@ const CH_MINUS = '-'.charCodeAt (0)
14
14
  const CH_SQUARE = '['.charCodeAt (0)
15
15
  const CH_GT = '>'.charCodeAt (0)
16
16
 
17
- const CL_DEAFULT = Buffer.from ('')
18
- const CL_PI = Buffer.from ('?', 'ascii')
19
- const CL_COMMENT = Buffer.from ('--', 'ascii')
20
- const CL_SQ_1 = Buffer.from (']', 'ascii')
21
- const CL_SQ_2 = Buffer.from (']]', 'ascii')
17
+ const CL_DEAFULT = ''
18
+ const CL_PI = '?'
19
+ const CL_COMMENT = '--'
20
+ const CL_SQ_1 = ']'
22
21
 
23
22
  const S_ENCODING = Symbol ('encoding')
24
23
 
@@ -54,13 +53,11 @@ const XMLLexer = class extends Transform {
54
53
 
55
54
  isClosing (pos) {
56
55
 
57
- const {awaited} = this, {length} = awaited; if (length === 0) return true
56
+ const {awaited, body} = this, {length} = awaited; if (length === 0) return true
58
57
 
59
- let from = pos - length; if (from < this.start) return false
58
+ const from = pos - length; if (from < this.start) return false
60
59
 
61
- if (this.body.charCodeAt (from) !== awaited [0]) return false
62
-
63
- if (length === 2 && this.body.charCodeAt (from + 1) !== awaited [1]) return false
60
+ for (let i = 0; i < length; i ++) if (body.charCodeAt (from + i) !== awaited.charCodeAt (i)) return false
64
61
 
65
62
  return true
66
63
 
@@ -114,7 +111,7 @@ const XMLLexer = class extends Transform {
114
111
 
115
112
  }
116
113
 
117
- }
114
+ }
118
115
 
119
116
  break
120
117
 
@@ -149,7 +146,7 @@ const XMLLexer = class extends Transform {
149
146
  {
150
147
 
151
148
  const pos = start + 2; if (pos >= body.length) return null
152
-
149
+
153
150
  switch (body.charCodeAt (pos)) {
154
151
 
155
152
  case CH_MINUS:
@@ -186,7 +183,7 @@ const XMLLexer = class extends Transform {
186
183
  case ST_TAG_X:
187
184
 
188
185
  for (let pos = this.position + 1; pos < body.length; pos ++) {
189
-
186
+
190
187
  switch (body.charCodeAt (pos)) {
191
188
 
192
189
  case CH_SQUARE:
@@ -197,10 +194,6 @@ const XMLLexer = class extends Transform {
197
194
  this.awaited = CL_SQ_1
198
195
  break
199
196
 
200
- case CL_SQ_1:
201
- this.awaited = CL_SQ_2
202
- break
203
-
204
197
  }
205
198
 
206
199
  this.position = pos
@@ -249,7 +242,7 @@ const XMLLexer = class extends Transform {
249
242
 
250
243
  let {beforeBody, start} = this
251
244
 
252
- return start === 0 ? beforeBody : beforeBody + BigInt (start)
245
+ return beforeBody + BigInt (start)
253
246
 
254
247
  }
255
248
 
@@ -265,7 +258,7 @@ const XMLLexer = class extends Transform {
265
258
 
266
259
  }
267
260
 
268
- _transform (chunk, encoding, callback) {
261
+ _transform (chunk, _, callback) {
269
262
 
270
263
  if (Buffer.isBuffer (chunk)) chunk = this.decoder.write (chunk)
271
264
 
@@ -1,56 +1,10 @@
1
1
  const assert = require ('assert')
2
- const stringEscape = require ('string-escape-map')
3
2
  const NamespacePrefixesMap = require ('./NamespacePrefixesMap.js')
4
-
5
- let esc = [
6
- ['<', '&lt;'],
7
- ['>', '&gt;'],
8
- ['&', '&amp;'],
9
- ['"', '&quot;']
10
- ]
11
-
12
- //const XML_BODY = new stringEscape (esc)
13
-
14
- //esc.push (['"', '&quot;'])
15
-
16
- const XML_ATTR = new stringEscape (esc)
17
-
18
- const BOOL = new Map ([
19
- ['0', 'false'],
20
- ['false', 'false'],
21
- ['N', 'false'],
22
- ['1', 'true'],
23
- ['true', 'true'],
24
- ['Y', 'true'],
25
- ])
26
-
27
- const XML_DECL = [
28
- ['version', '1.0'],
29
- ['encoding', null],
30
- ['standalone', null]
31
- ]
32
-
33
- const _declaration = o => {
34
-
35
- if (typeof o !== 'object' || o === null) return ''
36
-
37
- let s = '<?xml'
38
-
39
- for (const [name, def] of XML_DECL) {
40
-
41
- const f = name in o; if (!f && def === null) continue
42
-
43
- s += ' ' + name + '="' + (f ? o [name] : def) + '"'
44
-
45
- }
46
-
47
- return s + '?>'
48
-
49
- }
3
+ const XMLPrinter = require ('./XMLPrinter.js')
50
4
 
51
5
  const XMLMarshaller = class {
52
6
 
53
- constructor (xs, localName, namespaceURI) {
7
+ constructor (xs, localName, namespaceURI, printerOptions = {}) {
54
8
 
55
9
  this.xs = xs
56
10
 
@@ -62,25 +16,29 @@ const XMLMarshaller = class {
62
16
 
63
17
  this.isNsDumped = false
64
18
 
65
- this.qNames = []
19
+ this.printer = new XMLPrinter (printerOptions)
66
20
 
67
21
  }
68
22
 
69
23
  stringify (data, o = {}) {
70
24
 
71
- const {schemaElement} = this, {targetNamespace, attributes, children} = schemaElement
25
+ const {schemaElement, printer} = this, {targetNamespace, attributes} = schemaElement
72
26
 
73
27
  if (typeof o === 'string') o = {localName: o}
74
28
 
75
- this.buf = 'declaration' in o ? _declaration (o.declaration) : ''
29
+ {
30
+
31
+ const {declaration} = o
76
32
 
77
- this.appendElement (schemaElement, data, this.ns.QName (o.localName || attributes.name, targetNamespace))
33
+ if (declaration) printer.decl = declaration
78
34
 
79
- let xml = this.buf
35
+ }
80
36
 
81
- delete this.buf
37
+ printer.reset ()
82
38
 
83
- return xml
39
+ this.appendElement (schemaElement, data, this.ns.QName (o.localName || attributes.name, targetNamespace))
40
+
41
+ return printer.text
84
42
 
85
43
  }
86
44
 
@@ -90,68 +48,41 @@ const XMLMarshaller = class {
90
48
 
91
49
  this.appendElementBody (node, data)
92
50
 
93
- this.appendEndTag ()
51
+ this.printer.closeElement ()
94
52
 
95
53
  }
96
54
 
97
55
  appendStartTag (node, data, qName) {
98
-
99
- this.qNames.push (qName)
100
-
101
- this.buf += '<' + qName
102
-
56
+
57
+ this.printer.openElement (qName)
58
+
103
59
  if (!this.isNsDumped) {
104
60
 
105
- this.buf += this.ns
61
+ this.printer.text += this.ns
106
62
 
107
63
  this.isNsDumped = true
108
64
 
109
65
  }
110
66
 
111
- const {type} = node.attributes; if (type) this.appendAttributes (this.xs.getType (type), data)
112
-
113
67
  this.appendAttributes (node, data)
114
68
 
115
- this.buf += '>'
116
-
117
- }
118
-
119
- appendEndTag () {
120
-
121
- this.buf += '</' + this.qNames.pop () + '>'
122
-
123
69
  }
124
70
 
125
71
  appendNullElement (node) {
126
72
 
127
73
  const {attributes: {name, nillable}, targetNamespace} = node
128
74
 
129
- if (BOOL.get (nillable) !== 'true') return
75
+ if (nillable !== 'true' && nillable !== '1') return
130
76
 
131
77
  const qName = this.ns.QName (name, targetNamespace)
132
78
 
133
- this.buf += `<${qName} xsi:nil="true" />`
79
+ this.printer
80
+ .openElement (qName)
81
+ .writeAttribute ('xsi:nil', 'true')
82
+ .closeElement ()
134
83
 
135
84
  }
136
85
 
137
- appendScalar (node, data, restriction = {}) {
138
-
139
- for (const {localName, attributes, children} of node.children) {
140
-
141
- if (localName === 'restriction') {
142
-
143
- for (const {localName, attributes: {value}} of children) restriction [localName] = value
144
-
145
- return this.appendScalar (this.xs.getType (attributes.base), data, restriction)
146
-
147
- }
148
-
149
- }
150
-
151
- this.buf += this.to_string (data, node.attributes.name, restriction)
152
-
153
- }
154
-
155
86
  appendElementBody (node, data) {
156
87
 
157
88
  const {attributes: {type}, children} = node
@@ -164,65 +95,33 @@ const XMLMarshaller = class {
164
95
 
165
96
  appendAttributes (node, data) {
166
97
 
167
- const {localName, namespaceURI, attributes, children, targetNamespace} = node, {name, type, ref} = attributes
98
+ const {localName, attributes, children, targetNamespace} = node, {name, ref} = attributes
168
99
 
169
100
  if (ref) return this.appendAttributes (this.xs.getByReference (ref), data)
101
+
102
+ const {type} = node.attributes; if (type) this.appendAttributes (this.xs.getType (type), data)
170
103
 
171
104
  switch (localName) {
172
-
173
- case 'anyAttribute':
174
-
175
- if (data == null || typeof data !== 'object') return
176
-
177
- if (null in data)
178
-
179
- for (const o of Object.values (data [null]))
180
-
181
- for (const [k, v] of Object.entries (o))
182
-
183
- this.buf += ' ' + k + '="' + XML_ATTR.escape ('' + v) + '"'
184
-
185
- break
186
105
 
187
- case 'attribute':
188
-
189
- if (data == null || typeof data !== 'object') return
190
-
191
- if (!(name in data)) return
192
-
193
- let v = data [name]; if (v == null) return
194
-
195
- this.buf += ' ' + this.ns.QName (name, targetNamespace) + '="'
196
-
197
- if (type) {
198
-
199
- this.appendScalar (this.xs.getType (type), v)
200
-
201
- }
202
- else {
203
-
204
- for (const child of node.children) if (child.localName === 'simpleType') this.appendScalar (child, v)
205
-
206
- }
207
-
208
- this.buf += '"'
209
-
210
- break
211
-
212
- case 'any':
213
106
  case 'sequence':
214
107
  case 'choice':
215
108
  case 'group':
216
- case 'simpleType':
217
-
109
+ case 'simpleType':
218
110
  return
219
111
 
220
- case 'extension':
221
-
112
+ case 'attribute':
113
+
114
+ const v = data [name]; if (v == null) return
115
+
116
+ return this.printer.writeAttribute (
117
+ this.ns.QName (name, targetNamespace),
118
+ this.xs.getAttributeSimpleType (node).stringify (v)
119
+ )
120
+
121
+ case 'extension':
222
122
  this.appendAttributes (this.xs.getType (attributes.base), data)
223
123
 
224
124
  default:
225
-
226
125
  for (const i of children) this.appendAttributes (i, data)
227
126
 
228
127
  }
@@ -231,7 +130,7 @@ const XMLMarshaller = class {
231
130
 
232
131
  appendContent (node, data) {
233
132
 
234
- const {localName, namespaceURI, attributes, children, targetNamespace} = node, {name, type, ref} = attributes
133
+ const {localName, attributes, children, targetNamespace} = node, {name, ref} = attributes
235
134
 
236
135
  if (localName === 'attribute') return
237
136
 
@@ -241,16 +140,20 @@ const XMLMarshaller = class {
241
140
 
242
141
  case 'any':
243
142
 
244
- if (null in data) for (const xml in data [null]) this.buf += xml
143
+ if (null in data) for (const xml in data [null]) this.printer.writeBody (xml)
245
144
 
246
145
  return
247
146
 
248
147
  case 'simpleType':
249
148
 
250
- if (data !== null && typeof data === 'object' && !(data instanceof Date) && node.attributes.name !== 'QName') data = data [null]
149
+ if (typeof data === 'object' && data.hasOwnProperty (null)) data = data [null]
150
+
151
+ const type = this.xs.getSimpleType (node)
251
152
 
252
- if (data != null) this.appendScalar (node, data)
153
+ const xml = type.stringify (data)
253
154
 
155
+ this.printer.writeCharacters (xml)
156
+
254
157
  return
255
158
 
256
159
  case 'element':
@@ -278,108 +181,7 @@ const XMLMarshaller = class {
278
181
  }
279
182
 
280
183
  }
281
-
282
- to_string (v, type, restriction = {}) {
283
-
284
- const carp = () => {throw new Error (`Invalid value for ${type} type: ${v} (${typeof v})`)}
285
-
286
- switch (type) {
287
184
 
288
- case 'boolean':
289
- if (BOOL.has (v)) return BOOL.get (v)
290
- return !v ? 'false' : 'true'
291
-
292
- case 'date':
293
- switch (typeof v) {
294
- case 'string':
295
- if (v.length === 10) return v
296
- case 'number':
297
- case 'bigint':
298
- const d = new Date (v)
299
- if (isNaN (d)) carp ()
300
- v = d
301
- }
302
- if (v instanceof Date) {
303
- return v.toJSON ().slice (0, 10)
304
- }
305
- else {
306
- carp ()
307
- }
308
-
309
- case 'dateTime':
310
- switch (typeof v) {
311
- case 'string':
312
- if (v.length === 10) return v + 'T00:00:00'
313
- return v
314
- case 'number':
315
- case 'bigint':
316
- v = new Date (v)
317
- }
318
- if (v instanceof Date) {
319
- return v.toJSON ()
320
- }
321
- else {
322
- carp ()
323
- }
324
-
325
- case 'integer':
326
- case 'nonNegativeInteger':
327
- case 'positiveInteger':
328
- case 'nonPositiveInteger':
329
- case 'negativeInteger':
330
- case 'long':
331
- if (typeof v === 'string') v = BigInt (v)
332
- switch (typeof v) {
333
- case 'number':
334
- case 'bigint':
335
- return '' + v
336
- }
337
- carp ()
338
-
339
- case 'int':
340
- case 'short':
341
- case 'byte':
342
- case 'unsignedLong':
343
- case 'unsignedInt':
344
- case 'unsignedShort':
345
- case 'unsignedByte':
346
- if (typeof v === 'string') v = parseInt (v)
347
- switch (typeof v) {
348
- case 'number':
349
- if (!Number.isInteger (v)) carp ()
350
- case 'bigint':
351
- return '' + v
352
- }
353
- carp ()
354
-
355
- case 'float':
356
- case 'double':
357
- if (typeof v === 'string') v = parseFloat (v)
358
- if (typeof v === 'number') switch (v) {
359
- case Number.POSITIVE_INFINITY: return 'INF'
360
- case Number.NEGATIVE_INFINITY: return '-INF'
361
- default: return '' + v
362
- }
363
- carp ()
364
-
365
- case 'decimal':
366
- const {fractionDigits} = restriction
367
- if (typeof v === 'string') v = parseFloat (v)
368
- if (typeof v === 'number') return fractionDigits ? v.toFixed (fractionDigits.value) : '' + v
369
- carp ()
370
-
371
- case 'QName':
372
- if (typeof v === 'object' && 'localName' in v) v = this.ns.QName (v.localName, v.namespaceURI)
373
-
374
- default:
375
- return XML_ATTR.escape ('' + v)
376
-
377
- }
378
-
379
- }
380
-
381
185
  }
382
186
 
383
- XMLMarshaller.declaration = _declaration
384
-
385
187
  module.exports = XMLMarshaller
package/lib/XMLNode.js CHANGED
@@ -1,33 +1,16 @@
1
- const os = require ('os')
2
1
  const SAXEvent = require ('./SAXEvent.js')
3
2
  const XMLPrinter = require ('./XMLPrinter.js')
4
- const AttributesMap = require ('./AttributesMap')
5
3
  const NamespacesMap = require ('./NamespacesMap')
6
4
  const MoxyLikeJsonEncoder = require ('./MoxyLikeJsonEncoder')
7
5
 
8
- const ENTITY_RESOLVER = Symbol ('_entityResolver')
9
- const ATTRIBUTES = Symbol ('_attributes')
6
+ const ENTITY_RESOLVER = '_entityResolver'
7
+ const ATTRIBUTES = '_attributes'
10
8
  const TYPE = Symbol ('_type')
11
9
  const PARENT = Symbol ('_parent')
12
10
  const LEVEL = Symbol ('_level')
13
- const NS_MAP = Symbol ('_ns_map')
11
+ const NS_MAP = '_ns_map'
14
12
 
15
- const stringEscape = require ('string-escape-map')
16
-
17
- const ESC = [
18
- ['<', '&lt;'],
19
- ['>', '&gt;'],
20
- ['&', '&amp;'],
21
- [String.fromCharCode (10), '&#xA;'],
22
- [String.fromCharCode (13), '&#xD;'],
23
- ]
24
-
25
- const ESC_BODY = new stringEscape (ESC)
26
- const ESC_ATTR = new stringEscape ([...ESC, ['"', '&quot;']])
27
-
28
- const m2o =
29
- Object.fromEntries ? m => Object.fromEntries (m.entries ()) :
30
- m => {let o = {}; for (const [k, v] of m.entries ()) o [k] = v; return o}
13
+ const m2o = m => Object.fromEntries (m.entries ())
31
14
 
32
15
  const XMLNode = class extends SAXEvent {
33
16
 
@@ -41,7 +24,7 @@ const XMLNode = class extends SAXEvent {
41
24
  this [PARENT] = null
42
25
  this [LEVEL] = 0
43
26
 
44
- this.children = null
27
+ this.children = []
45
28
 
46
29
  }
47
30
 
@@ -77,6 +60,20 @@ const XMLNode = class extends SAXEvent {
77
60
 
78
61
  }
79
62
 
63
+ get xml () {
64
+
65
+ switch (this.type) {
66
+
67
+ case SAXEvent.TYPES.END_DOCUMENT: return ''
68
+
69
+ case SAXEvent.TYPES.END_ELEMENT: return this.isSelfEnclosed ? '' : `</${this.name}>`
70
+
71
+ default: return this.src
72
+
73
+ }
74
+
75
+ }
76
+
80
77
  readNamespaces () {
81
78
 
82
79
  this [NS_MAP] = new NamespacesMap (this)
@@ -93,7 +90,7 @@ const XMLNode = class extends SAXEvent {
93
90
 
94
91
  this [LEVEL] = 1 + _parent.level
95
92
 
96
- const {children} = _parent; if (children !== null) children.push (this)
93
+ const {children} = _parent; children.push (this)
97
94
 
98
95
  }
99
96
 
@@ -122,25 +119,7 @@ const XMLNode = class extends SAXEvent {
122
119
  return namespacesMap.getNamespaceURI (this.name, true)
123
120
 
124
121
  }
125
-
126
- readAttributes () {
127
-
128
- const m = new AttributesMap (this [ENTITY_RESOLVER], this [NS_MAP])
129
122
 
130
- this.writeAttributesToMap (m)
131
-
132
- this [ATTRIBUTES] = m
133
-
134
- }
135
-
136
- get attributes () {
137
-
138
- if (!(ATTRIBUTES in this)) this.readAttributes ()
139
-
140
- return this [ATTRIBUTES]
141
-
142
- }
143
-
144
123
  toString (options, level = 0) {
145
124
 
146
125
  if (arguments.length === 0) return this.toSourceString ()
@@ -167,46 +146,53 @@ const XMLNode = class extends SAXEvent {
167
146
 
168
147
  get text () {
169
148
 
170
- let s = super.text
171
-
172
- if (this [TYPE] === SAXEvent.TYPES.CHARACTERS) {
149
+ const s = super.text; if (this [TYPE] !== SAXEvent.TYPES.CHARACTERS) return s
173
150
 
174
- const entityResolver = this [ENTITY_RESOLVER]
175
-
176
- if (entityResolver) return entityResolver.fix (s)
177
-
178
- }
151
+ const entityResolver = this [ENTITY_RESOLVER]; return entityResolver ? entityResolver.fix (s) : s
152
+
153
+ }
179
154
 
180
- return s
155
+ get innerText () {
156
+
157
+ const {children} = this; if (!Array.isArray (children) || children.length === 0) return this.text
158
+
159
+ let s = ''; for (const child of children) s += child.innerText; return s
181
160
 
182
161
  }
183
162
 
184
- detach_children (list, o = {}) {
185
-
163
+ detachChildren (list) {
164
+
186
165
  if (!Array.isArray (list) || list.length === 0) return []
187
166
 
188
- let last = null, a = []; for (const i of list) {
189
-
167
+ const a = []; for (const i of list) {
168
+
190
169
  const d = i.detach (); if (d === null) continue
191
-
192
- if (d instanceof String && last instanceof String) {
193
170
 
194
- last += d
171
+ if (typeof d === 'string') {
172
+
173
+ let {length} = a; if (length !== 0) {
174
+
175
+ length --; if (typeof a [length] === 'string') {
176
+
177
+ a [length] += d
178
+
179
+ continue
180
+
181
+ }
182
+
183
+ }
195
184
 
196
185
  }
197
- else {
198
186
 
199
- a.push (last = d)
187
+ a.push (d)
200
188
 
201
- }
202
-
203
189
  }
204
-
190
+
205
191
  return a
206
192
 
207
193
  }
208
194
 
209
- detach (o = {}) {
195
+ detach () {
210
196
 
211
197
  switch (this.type) {
212
198
 
@@ -222,11 +208,9 @@ const XMLNode = class extends SAXEvent {
222
208
  localName,
223
209
  namespaceURI,
224
210
  attributes : m2o (attributes),
225
- children : this.detach_children (children, o),
211
+ children : this.detachChildren (children),
226
212
  }
227
213
 
228
- if (o.nsMap) r.namespacesMap = m2o (namespacesMap || [])
229
-
230
214
  return r
231
215
 
232
216
  default:
package/lib/XMLParser.js CHANGED
@@ -3,7 +3,7 @@ const SAXEvent = require ('./SAXEvent.js')
3
3
  const XMLNode = require ('./XMLNode.js')
4
4
  const XMLIterator = require ('./XMLIterator.js')
5
5
 
6
- const XMLReader = class {
6
+ const XMLParser = class {
7
7
 
8
8
  constructor (options = {}) {
9
9
 
@@ -21,7 +21,6 @@ const XMLReader = class {
21
21
  this.useNamespaces = options.useNamespaces
22
22
 
23
23
  if (this.useEntities) this.entityResolver = new (require ('./EntityResolver.js')) ()
24
-
25
24
 
26
25
  }
27
26
 
@@ -83,4 +82,4 @@ const XMLReader = class {
83
82
 
84
83
  }
85
84
 
86
- module.exports = XMLReader
85
+ module.exports = XMLParser