xml-toolkit 1.0.6 → 1.0.9

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.
@@ -2,40 +2,38 @@ const assert = require ('assert')
2
2
 
3
3
  const NamespacePrefixesMap = class extends Map {
4
4
 
5
- constructor (schemata, o) {
5
+ constructor (schemata, node) {
6
6
 
7
- assert.strictEqual (typeof o, 'object')
8
-
9
7
  super ()
10
8
 
11
9
  this.schemata = schemata
12
10
 
13
- this.add (o)
14
-
11
+ this.checkNode (node)
12
+
15
13
  }
16
14
 
17
- add (o) {
18
-
19
- if (this.isAddedAsNamespaceReference (o)) return
15
+ checkNode ({targetNamespace, attributes, children}) {
16
+
17
+ this.checkURI (targetNamespace)
18
+
19
+ for (const a of Object.values (attributes))
20
20
 
21
- for (let v of Object.values (o)) if (typeof v === 'object') this.add (v)
21
+ if (Array.isArray (a) && a.length === 2)
22
+
23
+ this.checkURI (a [1])
24
+
25
+ for (const i of children) this.checkNode (i)
22
26
 
23
27
  }
24
28
 
25
- isAddedAsNamespaceReference (a) {
29
+ checkURI (uri) {
26
30
 
27
- if (!Array.isArray (a)) return false
28
-
29
- if (a.length !== 2) return false
30
-
31
- const uri = a [1]
32
-
33
- if (!this.schemata.has (uri)) return false
31
+ if (this.has (uri)) return
32
+
33
+ if (!this.schemata.has (uri)) return
34
34
 
35
- if (this.has (uri)) return true
36
-
37
35
  this.set (uri, 'ns' + this.size)
38
-
36
+
39
37
  }
40
38
 
41
39
  QName (localName, namespaceURI) {
@@ -37,148 +37,160 @@ const XMLMarshaller = class {
37
37
 
38
38
  }
39
39
 
40
- stringify (content, name) {
41
-
42
- const qName = this.ns.QName (name || this.schemaElement.name, this.schema.targetNamespace)
43
-
44
- let {complexType, sequence, choice, all, type} = this.schemaElement, group = sequence || choice || all
45
-
46
- if (type) {
47
-
48
- type = this.xs.getByReference (type)
49
-
50
- switch (type._type) {
51
-
52
- case 'complexType':
53
- complexType = type
54
- break
55
-
56
- case 'simpleType':
57
- simpleType = type
58
- break
59
-
60
- }
40
+ stringify (data, name) {
41
+
42
+ const {schemaElement} = this, {targetNamespace, attributes, children} = schemaElement
61
43
 
62
- }
44
+ const qName = this.ns.QName (name || attributes.name, targetNamespace)
63
45
 
64
- let buf = ['<' + qName]
46
+ this.buf = ['<' + qName]
65
47
 
66
- this.ns.appendTo (buf)
48
+ this.ns.appendTo (this.buf)
67
49
 
68
- if (complexType) this._aComplexType (buf, complexType, content)
50
+ this.appendAttributes (schemaElement, data)
69
51
 
70
- buf [0] += '>'
52
+ this.buf [0] += '>'
53
+
54
+ this.appendElementBody (schemaElement, data)
55
+
56
+ const xml = this.buf [0] + '</' + qName + '>'
71
57
 
72
- if (complexType) this._bComplexType (buf, complexType, content)
73
- if (group) this._bSequence (buf, group, content)
58
+ delete this.buf
74
59
 
75
- return buf [0] + '</' + qName + '>'
60
+ return xml
76
61
 
77
62
  }
63
+
64
+ appendNullElement (node) {
78
65
 
79
- /// _a: attributes
66
+ const {attributes: {name, nillable}, targetNamespace} = node
80
67
 
81
- _aComplexType (buf, complexType, content) {
68
+ if (BOOL.get (nillable) !== 'true') return
82
69
 
83
- const {complexContent, attribute} = complexType
70
+ const qName = this.ns.QName (name, targetNamespace)
84
71
 
85
- if (attribute)
86
- for (const e of Array.isArray (attribute) ? attribute : [attribute])
87
- this._aAttribute (buf, e, content [e.name])
88
-
89
- if (complexContent) this._aComplexContent (buf, complexContent, content)
90
-
91
- }
92
-
93
- _aComplexContent (buf, complexContent, content) {
94
-
95
- const {extension} = complexContent
72
+ this.buf [0] += `<${qName} xsi:nil="true" />`
96
73
 
97
- if (extension) this._aExtension (buf, extension, content)
98
-
99
74
  }
100
75
 
101
- _aExtension (buf, extension, content) {
76
+ appendScalar (node, data, restriction = {}) {
102
77
 
103
- const {base, attribute} = extension
78
+ for (const {localName, attributes, children} of node.children) {
104
79
 
105
- if (base) {
106
-
107
- const [localName, namespaceURI] = base
108
-
109
- const schema = this.xs.get (namespaceURI)
110
-
111
- const type = schema.get (localName)
80
+ if (localName === 'restriction') {
81
+
82
+ for (const {localName, attributes: {value}} of children) restriction [localName] = value
83
+
84
+ return this.appendScalar (this.xs.getByReference (attributes.base), data, restriction)
85
+
86
+ }
112
87
 
113
- if (type._type === 'complexType') this._aComplexType (buf, type, content)
114
-
115
88
  }
116
89
 
117
- if (attribute)
118
- for (const a of Array.isArray (attribute) ? attribute : [attribute])
119
- this._aAttribute (buf, a, content [a.name])
90
+ this.buf [0] += this.to_string (data, node.attributes.name, restriction)
120
91
 
121
- }
92
+ }
122
93
 
123
- _aAttribute (buf, attribute, content) {
94
+ appendElementBody (node, data) {
124
95
 
125
- if (content == null) return
96
+ const {attributes: {type}, children} = node
126
97
 
127
- let {name, targetNamespace, simpleType, type} = attribute
128
-
129
- if (type) {
98
+ if (type) return this.appendContent (this.xs.getByReference (type), data)
130
99
 
131
- type = this.xs.getByReference (type)
100
+ for (const i of children) this.appendContent (i, data)
132
101
 
133
- switch (type._type) {
102
+ }
134
103
 
135
- case 'simpleType':
136
- simpleType = type
137
- break
104
+ appendAttributes (node, data) {
138
105
 
139
- }
106
+ const {localName, namespaceURI, attributes, children, targetNamespace} = node, {name, type, ref} = attributes
140
107
 
141
- }
108
+ if (ref) return this.appendAttributes (this.xs.getByReference (ref), data)
109
+
110
+ switch (localName) {
142
111
 
143
- const qName = this.ns.QName (name, targetNamespace)
144
-
145
- buf [0] += ' ' + qName + '="'
146
-
147
- if (simpleType) this._bSimpleType (buf, simpleType, content)
112
+ case 'attribute':
113
+
114
+ if (!(name in data)) return
115
+
116
+ let v = data [name]; if (v == null) return
117
+
118
+ this.buf [0] += ' ' + this.ns.QName (name, targetNamespace) + '="'
119
+
120
+ this.appendScalar (this.xs.getByReference (type), v)
121
+
122
+ this.buf [0] += '"'
123
+
124
+ break
125
+
126
+ case 'extension':
148
127
 
149
- buf [0] += '"'
128
+ this.appendAttributes (this.xs.getByReference (attributes.base), data)
129
+
130
+ case 'any':
131
+ case 'sequence':
132
+ case 'choice':
133
+ case 'group':
134
+ case 'simpleType':
150
135
 
151
- }
152
-
153
- /// _b: body
154
-
155
- _bComplexType (buf, complexType, content) {
136
+ return
156
137
 
157
- const {complexContent, sequence, choice, all} = complexType, group = sequence || choice || all
138
+ default:
158
139
 
159
- if (group) this._bSequence (buf, group, content)
160
- if (complexContent) this._bComplexContent (buf, complexContent, content)
140
+ for (const i of children) this.appendAttributes (i, data)
141
+
142
+ }
161
143
 
162
144
  }
145
+
146
+ appendContent (node, data) {
163
147
 
164
- _bSimpleType (buf, simpleType, content, _restriction = {}) {
148
+ const {localName, namespaceURI, attributes, children, targetNamespace} = node, {name, type, ref} = attributes
165
149
 
166
- let {restriction} = simpleType; if (restriction) {
150
+ if (ref) return this.appendContent (this.xs.getByReference (ref), data)
167
151
 
168
- for (const [k, v] of Object.entries (_restriction)) switch (k) {
169
- case 'base': case 'targetNamespace': break
170
- default: restriction [k] = v
171
- }
152
+ switch (localName) {
153
+
154
+ case 'simpleType':
155
+
156
+ return this.appendScalar (node, data)
172
157
 
173
- this._bSimpleType (buf, this.xs.getByReference (restriction.base), content, restriction)
158
+ case 'element':
174
159
 
175
- }
176
- else {
160
+ if (!(name in data)) return
161
+
162
+ let v = data [name]; if (v == null) return this.appendNullElement (node)
163
+
164
+ if (!Array.isArray (v)) v = [v]
177
165
 
178
- buf [0] += this.to_string (content, simpleType.name, _restriction)
166
+ const qName = this.ns.QName (name, targetNamespace)
167
+
168
+ for (const d of Array.isArray (v) ? v : [v]) {
169
+
170
+ this.buf [0] += '<' + qName
171
+
172
+ this.appendAttributes (node, d)
173
+
174
+ this.buf [0] += '>'
175
+
176
+ this.appendElementBody (node, d)
177
+
178
+ this.buf [0] += '</' + qName + '>'
179
+
180
+ }
179
181
 
182
+ break
183
+
184
+ case 'extension':
185
+
186
+ this.appendContent (this.xs.getByReference (attributes.base), data)
187
+
188
+ default:
189
+
190
+ for (const i of children) this.appendContent (i, data)
191
+
180
192
  }
181
-
193
+
182
194
  }
183
195
 
184
196
  to_string (v, type, restriction = {}) {
@@ -277,113 +289,6 @@ const XMLMarshaller = class {
277
289
 
278
290
  }
279
291
 
280
- _bComplexContent (buf, complexContent, content) {
281
-
282
- const {extension} = complexContent
283
-
284
- if (extension) this._bExtension (buf, extension, content)
285
-
286
- }
287
-
288
- _bExtension (buf, _extension, content) {
289
-
290
- const {base, sequence, choice, all} = _extension, group = sequence || choice || all
291
-
292
- if (base) {
293
-
294
- const [localName, namespaceURI] = base
295
-
296
- const schema = this.xs.get (namespaceURI)
297
-
298
- const type = schema.get (localName)
299
-
300
- if (type._type === 'complexType') this._bComplexType (buf, type, content)
301
-
302
- }
303
-
304
- if (group) this._bSequence (buf, group, content)
305
-
306
- }
307
-
308
- _bSequence (buf, _sequence, content) {
309
-
310
- const {element, sequence, choice, all} = _sequence, group = sequence || choice || all
311
-
312
- if (group) this._bSequence (buf, group, content)
313
-
314
- if (element) {
315
-
316
- for (let e of Array.isArray (element) ? element : [element]) {
317
-
318
- const {ref} = e; if (ref) e = this.xs.getByReference (ref)
319
-
320
- const c = content [e.name]
321
-
322
- this._bElement (buf, e, c)
323
-
324
- }
325
-
326
- }
327
-
328
- }
329
-
330
- _bElement_null (buf, element) {
331
-
332
- if (BOOL.get (element.nillable) !== 'true') return
333
-
334
- const {name, targetNamespace} = element, qName = this.ns.QName (name, targetNamespace)
335
-
336
- buf [0] += `<${qName} xsi:nil="true" />`
337
-
338
- }
339
-
340
- _bElement (buf, element, content) {
341
-
342
- if (content == null) return this._bElement_null (buf, element)
343
-
344
- if (!Array.isArray (content)) content = [content]
345
-
346
- if (content.length === 0) return
347
-
348
- let {name, targetNamespace, complexType, simpleType, type} = element
349
-
350
- if (type) {
351
-
352
- type = this.xs.getByReference (type)
353
-
354
- switch (type._type) {
355
-
356
- case 'complexType':
357
- complexType = type
358
- break
359
-
360
- case 'simpleType':
361
- simpleType = type
362
- break
363
-
364
- }
365
-
366
- }
367
-
368
- const qName = this.ns.QName (name, targetNamespace)
369
-
370
- for (const i of content) {
371
-
372
- buf [0] += '<' + qName
373
-
374
- if (complexType) this._aComplexType (buf, complexType, content)
375
-
376
- buf [0] += '>'
377
-
378
- if (complexType) this._bComplexType (buf, complexType, i)
379
- if (simpleType) this._bSimpleType (buf, simpleType, i)
380
-
381
- buf [0] += '</' + qName + '>'
382
-
383
- }
384
-
385
- }
386
-
387
292
  }
388
293
 
389
294
  module.exports = XMLMarshaller
package/lib/XMLNode.js CHANGED
@@ -132,6 +132,35 @@ const XMLNode = class extends SAXEvent {
132
132
 
133
133
  }
134
134
 
135
+ detach (o = {}) {
136
+
137
+ switch (this.type) {
138
+
139
+ case SAXEvent.TYPES.CHARACTERS:
140
+ case SAXEvent.TYPES.CDATA:
141
+ return this.text
142
+
143
+ default:
144
+
145
+ const m2o = m => Object.fromEntries (m.entries ())
146
+
147
+ const {localName, namespaceURI, attributes, children, namespacesMap} = this
148
+
149
+ let r = {
150
+ localName,
151
+ namespaceURI,
152
+ attributes : m2o (attributes),
153
+ children : (children || []).map (n => n.detach (o)),
154
+ }
155
+
156
+ if (o.nsMap) r.namespacesMap = m2o (namespacesMap || [])
157
+
158
+ return r
159
+
160
+ }
161
+
162
+ }
163
+
135
164
  }
136
165
 
137
166
  XMLNode.getLocalName = name => {
package/lib/XMLSchema.js CHANGED
@@ -13,56 +13,33 @@ const XMLSchema = class extends Map {
13
13
  }
14
14
 
15
15
  add (node, options = {}) {
16
+
17
+ this.copyTargetNamespace (node)
18
+
19
+ const {attributes, children} = node
16
20
 
17
- if (node.elementFormDefault === 'unqualified') this.isDefaultElementFormQualified = false
18
- if (node.attributeFormDefault === 'qualified') this.isAttributeElementFormQualified = true
19
-
20
- for (const type of [
21
-
22
- 'element',
23
- 'complexType',
24
- 'simpleType',
25
-
26
- ]) if (type in node) {
27
-
28
- let list = node [type]
29
-
30
- if (!Array.isArray (list)) list = [list]
21
+ if (attributes.elementFormDefault === 'unqualified') this.isDefaultElementFormQualified = false
22
+ if (attributes.attributeFormDefault === 'qualified') this.isAttributeElementFormQualified = true
23
+
24
+ for (const e of children) {
25
+
26
+ const {name} = e.attributes
31
27
 
32
- for (const item of list) {
28
+ this.set (name, e)
33
29
 
34
- delete item.annotation
35
-
36
- item._type = type
37
-
38
- this.copyTargetNamespace (item)
39
-
40
- this.set (item.name, item)
41
-
42
- this.parent.register (item.name, this.targetNamespace)
43
-
44
- }
45
-
30
+ this.parent.register (name, this.targetNamespace)
31
+
46
32
  }
47
33
 
48
34
  }
49
35
 
50
- copyTargetNamespace (o) {
51
-
52
- if (typeof o !== 'object') return
36
+ copyTargetNamespace (node) {
53
37
 
54
- if (Array.isArray (o)) {
38
+ if (typeof node !== 'object') return
55
39
 
56
- for (const v of o) this.copyTargetNamespace (v)
57
-
58
- }
59
- else {
60
-
61
- o.targetNamespace = this.targetNamespace
40
+ node.targetNamespace = this.targetNamespace
62
41
 
63
- for (const v of Object.values (o)) this.copyTargetNamespace (v)
64
-
65
- }
42
+ for (const e of node.children) this.copyTargetNamespace (e)
66
43
 
67
44
  }
68
45
 
@@ -86,6 +63,7 @@ XMLSchema.adjustNode = node => {
86
63
 
87
64
  case 'attribute':
88
65
  case 'element':
66
+ case 'group':
89
67
  splitNs ('ref')
90
68
  splitNs ('type')
91
69
  break
@@ -101,4 +79,6 @@ XMLSchema.adjustNode = node => {
101
79
 
102
80
  }
103
81
 
82
+ XMLSchema.namespaceURI = 'http://www.w3.org/2001/XMLSchema'
83
+
104
84
  module.exports = XMLSchema
@@ -35,9 +35,13 @@ const XMLSchemata = class extends Map {
35
35
 
36
36
  const [localName, namespaceURI] = ref
37
37
 
38
- if (namespaceURI === 'http://www.w3.org/2001/XMLSchema') return {
39
- _type: 'simpleType',
40
- name: localName
38
+ if (namespaceURI === XMLSchema.namespaceURI) return {
39
+ localName: 'simpleType',
40
+ namespaceURI,
41
+ attributes: {name: localName},
42
+ children: [],
43
+ namespacesMap: {},
44
+ targetNamespace: namespaceURI
41
45
  }
42
46
 
43
47
  return this.get (namespaceURI).get (localName)
@@ -83,21 +87,21 @@ const XMLSchemata = class extends Map {
83
87
  }
84
88
 
85
89
  async addSchema (node, options = {}) {
86
-
87
- let {targetNamespace} = node; if (!targetNamespace) targetNamespace = options.targetNamespace
90
+
91
+ let {targetNamespace} = node.attributes; if (!targetNamespace) targetNamespace = options.targetNamespace
88
92
 
89
93
  if (!this.has (targetNamespace)) this.set (targetNamespace, new XMLSchema (this, targetNamespace))
90
94
 
91
- let imp = node.import; if (imp) {
95
+ const imp = node.children.filter (e => e.localName === 'import' && e.namespaceURI === XMLSchema.namespaceURI)
92
96
 
93
- const {addLocation} = options
97
+ if (imp.length !== 0) await Promise.all (imp.map (i => {
94
98
 
95
- if (!Array.isArray (imp)) imp = [imp]
99
+ const {schemaLocation, namespace} = i.attributes
96
100
 
97
- for (const {schemaLocation, namespace} of imp) await addLocation (schemaLocation, namespace)
101
+ return options.addLocation (schemaLocation, namespace)
102
+
103
+ }))
98
104
 
99
- }
100
-
101
105
  this.get (targetNamespace).add (node)
102
106
 
103
107
  }
@@ -110,12 +114,12 @@ const XMLSchemata = class extends Map {
110
114
 
111
115
  }
112
116
 
113
- const {targetNamespace} = options, mapper = XMLNode.toObject ({})
117
+ const {targetNamespace} = options, mapper = n => n.detach ()
114
118
 
115
119
  for await (const node of
116
120
 
117
121
  new XMLReader ({
118
- filterElements: e => e.namespaceURI === 'http://www.w3.org/2001/XMLSchema',
122
+ filterElements: e => e.namespaceURI === XMLSchema.namespaceURI,
119
123
  map: adjustNode,
120
124
  })
121
125
  .process (fs.createReadStream (fn))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xml-toolkit",
3
- "version": "1.0.6",
3
+ "version": "1.0.9",
4
4
  "description": "Collection of classes for dealing with XML",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/test/test.js CHANGED
@@ -59,12 +59,15 @@ console.log (xml)
59
59
 
60
60
  const sax = new XMLReader ({
61
61
  // stripSpace: true,
62
+ // filterElements: 'root',
63
+ // filterElements: 'PARAMTYPES'
62
64
  filterElements: 'SendRequestRequest',
63
- map: XMLNode.toObject ({
65
+ map: n => n.detach ({nsMap: true}),
66
+ // map: XMLNode.toObject ({
64
67
  // wrap: 1,
65
- getName: (localName, namespaceURI) => (!namespaceURI ? '' : '{' + namespaceURI + '}') + localName,
66
- map: o => Object.fromEntries (Object.entries (o).map (([k, v]) => [k + '111', v]))
67
- })
68
+ // getName: (localName, namespaceURI) => (!namespaceURI ? '' : '{' + namespaceURI + '}') + localName,
69
+ // map: o => Object.fromEntries (Object.entries (o).map (([k, v]) => [k + '111', v]))
70
+ // })
68
71
  })
69
72
 
70
73
  /*
@@ -111,7 +114,12 @@ async function test_004_schemata (fn) {
111
114
  const o = s.get (localName)
112
115
 
113
116
  const nspm = xs.getNamespacePrefixesMap (o)
114
- */
117
+
118
+ console.log (xs.stringify ({
119
+ "ExportDebtRequestsRequest": {Id: 1}
120
+ }))
121
+ */
122
+
115
123
  console.log (xs.stringify ({
116
124
  "ExportDebtRequestsResponse": {
117
125
  "request-data": {
@@ -208,6 +216,10 @@ async function test_004_schemata (fn) {
208
216
  console.log (xs.get ('urn:dom.gosuslugi.ru/debt-requests/1.0.0').get ('ActionType').restriction)
209
217
  */
210
218
 
219
+ console.log (xs.stringify ({
220
+ "ExportDebtRequestsRequest": {Id: 1}
221
+ }))
222
+
211
223
  }
212
224
 
213
225
  async function test_005_schemata (fn) {
@@ -273,7 +285,7 @@ async function test_005_schemata (fn) {
273
285
  async function test_006_schemata (fn) {
274
286
 
275
287
  const xs = await XMLSchemata.fromFile ('test/snils-by-additionalData-1.0.1.xsd')
276
-
288
+
277
289
  const data = {
278
290
  "SnilsByAdditionalDataRequest": {
279
291
  "FamilyName": "ИВАНОВ",
@@ -315,11 +327,11 @@ async function main () {
315
327
  // await test_003_emitter_sync ('E05a.xml')
316
328
  // await test_003_emitter_sync ('param_types.xml')
317
329
  // await test_003_emitter_sync ('not-sa01.xml')
318
- // await test_003_emitter_sync ('ent.xml')
330
+ // await test_003_emitter_sync ('ent.xml')
319
331
  // await test_003_emitter_sync ('soap.xml')
320
332
  await test_004_schemata ()
321
- await test_005_schemata ()
322
- await test_006_schemata ()
333
+ // await test_005_schemata ()
334
+ // await test_006_schemata ()
323
335
 
324
336
  }
325
337