xml-toolkit 1.0.5 → 1.0.8

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.
@@ -37,148 +37,163 @@ 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 'simpleType':
113
+
114
+ return this.appendScalar (node, data)
115
+
116
+ case 'attribute':
117
+
118
+ if (!(name in data)) return
119
+
120
+ let v = data [name]; if (v == null) return
121
+
122
+ this.buf [0] += ' ' + this.ns.QName (name, targetNamespace) + '="'
123
+
124
+ this.appendScalar (this.xs.getByReference (type), v)
125
+
126
+ this.buf [0] += '"'
127
+
128
+ break
129
+
130
+ case 'extension':
148
131
 
149
- buf [0] += '"'
132
+ this.appendAttributes (this.xs.getByReference (attributes.base), data)
133
+
134
+ case 'any':
135
+ case 'sequence':
136
+ case 'choice':
137
+ case 'group':
150
138
 
151
- }
152
-
153
- /// _b: body
154
-
155
- _bComplexType (buf, complexType, content) {
139
+ return
156
140
 
157
- const {complexContent, sequence, choice, all} = complexType, group = sequence || choice || all
141
+ default:
158
142
 
159
- if (group) this._bSequence (buf, group, content)
160
- if (complexContent) this._bComplexContent (buf, complexContent, content)
143
+ for (const i of children) this.appendAttributes (i, data)
144
+
145
+ }
161
146
 
162
147
  }
148
+
149
+ appendContent (node, data) {
163
150
 
164
- _bSimpleType (buf, simpleType, content, _restriction = {}) {
151
+ const {localName, namespaceURI, attributes, children, targetNamespace} = node, {name, type, ref} = attributes
165
152
 
166
- let {restriction} = simpleType; if (restriction) {
153
+ if (ref) return this.appendContent (this.xs.getByReference (ref), data)
167
154
 
168
- for (const [k, v] of Object.entries (_restriction)) switch (k) {
169
- case 'base': case 'targetNamespace': break
170
- default: restriction [k] = v
171
- }
155
+ switch (localName) {
156
+
157
+ case 'simpleType':
158
+
159
+ return this.appendScalar (node, data)
172
160
 
173
- this._bSimpleType (buf, this.xs.getByReference (restriction.base), content, restriction)
161
+ case 'element':
174
162
 
175
- }
176
- else {
163
+ if (!(name in data)) return
164
+
165
+ let v = data [name]; if (v == null) return this.appendNullElement (node)
166
+
167
+ if (!Array.isArray (v)) v = [v]
177
168
 
178
- buf [0] += this.to_string (content, simpleType.name, _restriction)
169
+ const qName = this.ns.QName (name, targetNamespace)
170
+
171
+ for (const d of Array.isArray (v) ? v : [v]) {
172
+
173
+ this.buf [0] += '<' + qName
174
+
175
+ this.appendAttributes (node, d)
176
+
177
+ this.buf [0] += '>'
178
+
179
+ this.appendElementBody (node, d)
180
+
181
+ this.buf [0] += '</' + qName + '>'
182
+
183
+ }
179
184
 
185
+ break
186
+
187
+ case 'extension':
188
+
189
+ this.appendContent (this.xs.getByReference (attributes.base), data)
190
+
191
+ default:
192
+
193
+ for (const i of children) this.appendContent (i, data)
194
+
180
195
  }
181
-
196
+
182
197
  }
183
198
 
184
199
  to_string (v, type, restriction = {}) {
@@ -277,113 +292,6 @@ const XMLMarshaller = class {
277
292
 
278
293
  }
279
294
 
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
295
  }
388
296
 
389
297
  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
 
@@ -78,7 +55,7 @@ XMLSchema.adjustNode = node => {
78
55
 
79
56
  const [local, prefix] = attributes.get (name).split (':').reverse ()
80
57
 
81
- attributes.set (name, [local, namespacesMap.get (prefix)])
58
+ attributes.set (name, [local, namespacesMap.get (prefix || '')])
82
59
 
83
60
  }
84
61
 
@@ -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 ({nsMap: true})
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.5",
3
+ "version": "1.0.8",
4
4
  "description": "Collection of classes for dealing with XML",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -0,0 +1,29 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://common.kvs.pfr.com/1.0.0" xmlns:smev="urn://x-artefacts-smev-gov-ru/supplementary/commons/1.0.1" targetNamespace="http://common.kvs.pfr.com/1.0.0" elementFormDefault="qualified">
3
+ <xs:import namespace="urn://x-artefacts-smev-gov-ru/supplementary/commons/1.0.1" schemaLocation="smev-supplementary-commons-1.0.1.xsd"/>
4
+ <xs:complexType name="BirthPlaceType">
5
+ <xs:sequence>
6
+ <xs:element name="PlaceType" type="smev:string-50" nillable="false"/>
7
+ <xs:element name="Settlement" type="smev:string-50" nillable="false"/>
8
+ <xs:element name="District" type="smev:string-50" minOccurs="0"/>
9
+ <xs:element name="Region" type="smev:string-50" minOccurs="0"/>
10
+ <xs:element name="Country" type="smev:string-50" minOccurs="0"/>
11
+ </xs:sequence>
12
+ </xs:complexType>
13
+ <xs:complexType name="IdentificationDocumentType">
14
+ <xs:sequence>
15
+ <xs:element name="Type" type="smev:string-200" nillable="false"/>
16
+ <xs:element name="Document" type="smev:NotRestrictedDocumentType" nillable="false"/>
17
+ </xs:sequence>
18
+ </xs:complexType>
19
+ <xs:group name="AllIdentityDocumentType-Group">
20
+ <xs:sequence>
21
+ <xs:choice>
22
+ <xs:group ref="smev:PrimaryIdentityDocument-ModelGroup"/>
23
+ <xs:group ref="smev:WeakIdentityDocument-ModelGroup"/>
24
+ <xs:group ref="smev:TemporaryIdentityDocument-ModelGroup"/>
25
+ <xs:element name="PfrIdentificationDocument" type="tns:IdentificationDocumentType"/>
26
+ </xs:choice>
27
+ </xs:sequence>
28
+ </xs:group>
29
+ </xs:schema>