xml-toolkit 1.0.25 → 1.0.27

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/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  # node-xml-toolkit
2
- Collection of classes for dealing with XML
2
+ XML parsers (synchronous, streaming), marshaller, SOAP adapters (1.1, 1.2)
3
3
 
4
4
  # Installation
5
5
 
@@ -25,7 +25,7 @@ for (const element of document.detach ().children) {
25
25
  }
26
26
  ```
27
27
 
28
- * [Reading a Record List](https://github.com/do-/node-xml-toolkit/wiki/Use-Case:-Reading-a-Record-List)
28
+ * [Reading a Record List](https://github.com/do-/node-xml-toolkit/wiki/Use-Case:-Reading-a-Record-List), streaming mode
29
29
 
30
30
  ```js
31
31
  const {XMLReader, XMLNode} = require ('xml-toolkit')
@@ -50,7 +50,7 @@ const records = new XMLReader ({
50
50
  // records.on ('data', record => doSomethingWith (record))
51
51
  ```
52
52
 
53
- * [Getting a Single Element](https://github.com/do-/node-xml-toolkit/wiki/Use-Case:-Getting-a-Single-Element)
53
+ * [Getting a Single Element](https://github.com/do-/node-xml-toolkit/wiki/Use-Case:-Getting-a-Single-Element), streaming mode
54
54
 
55
55
  ```js
56
56
  const {XMLReader, XMLNode} = require ('xml-toolkit')
@@ -93,13 +93,13 @@ const xml = xs.stringify (data)
93
93
  */
94
94
  ```
95
95
 
96
- * Invoking a [SOAP 1.1](https://github.com/do-/node-xml-toolkit/wiki/SOAP11) Web Service
96
+ * Invoking a [SOAP 1.1](https://github.com/do-/node-xml-toolkit/wiki/SOAP11) or [SOAP 1.2](https://github.com/do-/node-xml-toolkit/wiki/SOAP12) Web Service
97
97
 
98
98
  ```js
99
99
  const http = require ('http')
100
- const {SOAP11} = require ('xml-toolkit')
100
+ const {SOAP11, SOAP12} = require ('xml-toolkit')
101
101
 
102
- const soap = new SOAP11 ('their.wsdl')
102
+ const soap = new SOAP11 ('their.wsdl') // or SOAP12
103
103
 
104
104
  const {method, headers, body} = soap.http ({RequestElementNameOfTheirs: {amount: '0.01'}})
105
105
 
@@ -107,4 +107,4 @@ const rq = http.request (endpointURL, {method, headers})
107
107
  rq.write (body)
108
108
  ```
109
109
 
110
- More information available in [wiki docs](https://github.com/do-/node-xml-toolkit/wiki).
110
+ For more information, see [wiki docs](https://github.com/do-/node-xml-toolkit/wiki).
package/index.js CHANGED
@@ -8,8 +8,10 @@ for (const name of [
8
8
  'XMLNode',
9
9
  'XMLSchemata',
10
10
  'SOAP11',
11
+ 'SOAP12',
11
12
  'EntityResolver',
12
13
  'XMLIterator',
13
14
  'XMLParser',
15
+ 'SOAPFault',
14
16
 
15
17
  ]) module.exports [name] = require ('./lib/' + name)
package/lib/SOAP11.js CHANGED
@@ -1,12 +1,54 @@
1
1
  const fs = require ('fs')
2
+ const path = require ('path')
2
3
 
3
4
  const XMLSchemata = require ('./XMLSchemata.js')
4
5
  const XMLReader = require ('./XMLReader.js')
5
6
  const XMLNode = require ('./XMLNode.js')
6
- const SOAPHTTP = require ('./SOAPHTTP.js')
7
+ const SOAPFault = require ('./SOAPFault.js')
7
8
 
8
9
  const WSDL = {namespaceURI: 'http://schemas.xmlsoap.org/wsdl/'}
9
10
 
11
+ const _contentType = 'text/xml'
12
+
13
+ let _xs = null
14
+
15
+ const get_xs = () => {
16
+
17
+ if (_xs === null) _xs = new XMLSchemata (path.join (path.dirname (module.filename), 'soap-1.1.xsd'))
18
+
19
+ return _xs
20
+
21
+ }
22
+
23
+ const _fault_xml = ({code, message, actor, detail}) => {
24
+
25
+ if (typeof code === 'string') code = {localName: code, namespaceURI: 'http://schemas.xmlsoap.org/soap/envelope/'}
26
+
27
+ const Fault = {
28
+ faultstring: message,
29
+ faultcode: code,
30
+ faultactor: actor,
31
+ detail
32
+ }
33
+
34
+ return get_xs ().stringify ({Fault})
35
+
36
+ }
37
+
38
+ const _message = (body, header, o) => {
39
+
40
+ if (!Array.isArray (body)) body = [body, {}]
41
+
42
+ if (body [0] instanceof SOAPFault) body [0] = _fault_xml (body [0])
43
+
44
+ let Envelope = {Body: XMLSchemata.any (body)}
45
+
46
+ if (header != null) Envelope.Header = XMLSchemata.any (header)
47
+
48
+ return get_xs ().stringify ({Envelope}, o)
49
+
50
+ }
51
+
10
52
  const SOAP11 = class {
11
53
 
12
54
  constructor (fn) {
@@ -81,33 +123,36 @@ const SOAP11 = class {
81
123
 
82
124
  }
83
125
 
84
- toSOAPHTTP (o) {
85
-
86
- let rq = new SOAPHTTP ('1.1')
126
+ http (body, header) {
87
127
 
88
- for (const elementLocalName in o) {
128
+ if (!Array.isArray (body)) body = [body, {}]
129
+
130
+ const encoding = 'UTF-8'
131
+
132
+ let headers = {'Content-Type': _contentType + '; charset=' + encoding.toLowerCase ()}
133
+
134
+ for (const elementLocalName in body [0]) {
89
135
 
90
136
  const SOAPAction = this.getSoapActionByElementLocalName (elementLocalName)
91
137
 
92
- if (SOAPAction) rq.http.headers.SOAPAction = SOAPAction
138
+ if (SOAPAction) headers.SOAPAction = SOAPAction
93
139
 
94
140
  }
95
141
 
96
- rq.soap.Body.content = this.xs.stringify (o)
97
-
98
- return rq.build ()
142
+ body [0] = this.xs.stringify (body [0])
99
143
 
100
- }
101
-
102
- http (o) {
103
-
104
- return this.toSOAPHTTP (o).http
144
+ return {
145
+ method: 'POST',
146
+ headers,
147
+ body: _message (body, header, {declaration: {encoding}})
148
+ }
105
149
 
106
150
  }
107
151
 
108
152
  }
109
153
 
110
154
  SOAP11.namespaceURI = 'http://schemas.xmlsoap.org/wsdl/soap/'
155
+ SOAP11.contentType = _contentType
111
156
 
112
157
  SOAP11.fromFile = async function (fn, options = {}) {
113
158
 
@@ -127,4 +172,6 @@ SOAP11.fromFile = async function (fn, options = {}) {
127
172
 
128
173
  }
129
174
 
175
+ SOAP11.message = _message
176
+
130
177
  module.exports = SOAP11
package/lib/SOAP12.js ADDED
@@ -0,0 +1,78 @@
1
+ const path = require ('path')
2
+ const XMLSchemata = require ('./XMLSchemata.js')
3
+ const SOAPFault = require ('./SOAPFault.js')
4
+
5
+ let _xs = null
6
+
7
+ const _contentType = 'application/soap+xml'
8
+
9
+ const get_xs = () => {
10
+
11
+ if (_xs === null) _xs = new XMLSchemata (path.join (path.dirname (module.filename), 'soap-1.2.xsd'))
12
+
13
+ return _xs
14
+
15
+ }
16
+
17
+ const _fault_xml = ({code, message, actor, detail}) => {
18
+
19
+ if (typeof code === 'string') code = {localName: code, namespaceURI: 'http://www.w3.org/2003/05/soap-envelope'}
20
+
21
+ const Fault = {
22
+ Reason: {Text: message},
23
+ Code: {Value: code},
24
+ Role: actor,
25
+ Detail: detail
26
+ }
27
+
28
+ return get_xs ().stringify ({Fault})
29
+
30
+ }
31
+
32
+ const _message = (body, header, o) => {
33
+
34
+ if (!Array.isArray (body)) body = [body, {}]
35
+
36
+ if (body [0] instanceof SOAPFault) body [0] = _fault_xml (body [0])
37
+
38
+ let Envelope = {Body: XMLSchemata.any (body)}
39
+
40
+ if (header != null) Envelope.Header = XMLSchemata.any (header)
41
+
42
+ return get_xs ().stringify ({Envelope}, o)
43
+
44
+ }
45
+
46
+ const SOAP12 = class {
47
+
48
+ constructor (fn) {
49
+
50
+ this.definitions = []
51
+
52
+ if (fn) this.xs = new XMLSchemata (fn)
53
+
54
+ }
55
+
56
+ http (body, header) {
57
+
58
+ if (!Array.isArray (body)) body = [body, {}]
59
+
60
+ const encoding = 'UTF-8'
61
+
62
+ body [0] = this.xs.stringify (body [0])
63
+
64
+ return {
65
+ method: 'POST',
66
+ headers: {'Content-Type': _contentType +'; charset=' + encoding.toLowerCase ()},
67
+ body: _message (body, header, {declaration: {encoding}})
68
+ }
69
+
70
+ }
71
+
72
+ }
73
+
74
+ SOAP12.contentType = _contentType
75
+
76
+ SOAP12.message = _message
77
+
78
+ module.exports = SOAP12
@@ -0,0 +1,30 @@
1
+ const XMLSchemata = require ('./XMLSchemata.js')
2
+
3
+ const SOAPFault = class {
4
+
5
+ constructor (message, o) {
6
+
7
+ if (o == null && typeof message === 'object') {
8
+ o = message
9
+ this.message = o.message
10
+ }
11
+ else {
12
+ this.message = message
13
+ }
14
+
15
+ this.code = 'code' in o ? o.code: 'Server'
16
+
17
+ if ('actor' in o) {
18
+ this.actor = o.actor
19
+ }
20
+ else if ('role' in o) {
21
+ this.actor = o.role
22
+ }
23
+
24
+ if ('detail' in o) this.detail = XMLSchemata.any (o.detail)
25
+
26
+ }
27
+
28
+ }
29
+
30
+ module.exports = SOAPFault
@@ -24,6 +24,30 @@ const BOOL = new Map ([
24
24
  ['Y', 'true'],
25
25
  ])
26
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
+ }
50
+
27
51
  const XMLMarshaller = class {
28
52
 
29
53
  constructor (xs, localName, namespaceURI) {
@@ -42,13 +66,15 @@ const XMLMarshaller = class {
42
66
 
43
67
  }
44
68
 
45
- stringify (data, name) {
46
-
69
+ stringify (data, o = {}) {
70
+
47
71
  const {schemaElement} = this, {targetNamespace, attributes, children} = schemaElement
48
72
 
49
- this.buf = ''
73
+ if (typeof o === 'string') o = {localName: o}
50
74
 
51
- this.appendElement (schemaElement, data, this.ns.QName (name || attributes.name, targetNamespace))
75
+ this.buf = 'declaration' in o ? _declaration (o.declaration) : ''
76
+
77
+ this.appendElement (schemaElement, data, this.ns.QName (o.localName || attributes.name, targetNamespace))
52
78
 
53
79
  let xml = this.buf
54
80
 
@@ -344,4 +370,6 @@ const XMLMarshaller = class {
344
370
 
345
371
  }
346
372
 
373
+ XMLMarshaller.declaration = _declaration
374
+
347
375
  module.exports = XMLMarshaller
@@ -85,15 +85,15 @@ const XMLSchemata = class extends Map {
85
85
 
86
86
  }
87
87
 
88
- stringify (o) {
88
+ stringify (data, o) {
89
89
 
90
- assert.strictEqual (typeof o, 'object')
90
+ assert.strictEqual (typeof data, 'object')
91
91
 
92
- assert.strictEqual (Object.keys (o).length, 1)
92
+ assert.strictEqual (Object.keys (data).length, 1)
93
93
 
94
- for (let [localName, content] of Object.entries (o))
94
+ for (let [localName, content] of Object.entries (data))
95
95
 
96
- return this.createMarshaller (localName).stringify (content)
96
+ return this.createMarshaller (localName).stringify (content, o)
97
97
 
98
98
  }
99
99
 
@@ -199,4 +199,20 @@ XMLSchemata.fromFile = async function (fn, options = {}) {
199
199
 
200
200
  }
201
201
 
202
+ XMLSchemata.any = (xml, attributes) => {
203
+
204
+ if (attributes == null && Array.isArray (xml) && xml.length === 2) {
205
+
206
+ attributes = xml [1]
207
+
208
+ xml = xml [0]
209
+
210
+ }
211
+
212
+ if (attributes == null) attributes = {}
213
+
214
+ return {null: {[xml]: attributes}}
215
+
216
+ }
217
+
202
218
  module.exports = XMLSchemata
File without changes
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xml-toolkit",
3
- "version": "1.0.25",
3
+ "version": "1.0.27",
4
4
  "description": "Collection of classes for dealing with XML",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/test/test.js CHANGED
@@ -1,6 +1,6 @@
1
1
  const fs = require ('fs')
2
2
  const assert = require ('assert')
3
- const {XMLReader, SAXEvent, XMLLexer, AttributesMap, XMLNode, XMLSchemata, SOAP11, EntityResolver, XMLIterator, XMLParser} = require ('../')
3
+ const {XMLReader, SAXEvent, XMLLexer, AttributesMap, XMLNode, XMLSchemata, SOAP11, SOAP12, EntityResolver, XMLIterator, XMLParser, SOAPFault} = require ('../')
4
4
 
5
5
  async function test_001_lexer_sync (fn) {
6
6
 
@@ -332,17 +332,15 @@ async function test_006_schemata (fn) {
332
332
 
333
333
  }
334
334
 
335
- async function test_007_wsdl (fn) {
335
+ function test_007_wsdl (fn) {
336
336
 
337
- const soap = await SOAP11.fromFile ('test/20186.wsdl')
338
- const soaps = new SOAP11 ('test/20186.wsdl')
337
+ const soap11 = new SOAP11 ('test/20186.wsdl')
338
+ const soap12 = new SOAP12 ('test/20186.wsdl')
339
339
 
340
340
  const d = {GetForm9Sync: {address: {Region: {Code: 78}}}}
341
341
 
342
- console.log (soap.http (d))
343
- console.log (soaps.http (d))
344
-
345
- // console.log (soap)
342
+ console.log (soap11.http (d))
343
+ console.log (soap12.http (d))
346
344
 
347
345
  }
348
346
 
@@ -455,108 +453,23 @@ for (const element of doc.children) {
455
453
 
456
454
  function test_013_soap () {
457
455
 
458
- const xs11 = new XMLSchemata ('test/soap-1.1.xsd')
456
+ const xs11 = new XMLSchemata ('lib/soap-1.1.xsd')
459
457
 
460
- // console.log (xs.get ('http://schemas.xmlsoap.org/soap/envelope/'))
461
- // console.log (xs.get ('http://schemas.xmlsoap.org/soap/envelope/').getType ('Fault').children[0].children)
462
- // console.log (xs.getType ('Fault'))
458
+ const detail = `
459
+ <PO:order xmlns:PO="http://gizmos.com/orders/">Quantity element does not have a value</PO:order>
460
+ <PO:confirmation xmlns:PO="http://gizmos.com/confirm">Incomplete address: no zip code</PO:confirmation>
461
+ `
463
462
 
464
- /*
465
- console.log (xs.stringify ({
466
- Envelope: {
467
- Body: {null: {'<foo>bar</foo>': {Id: 1}}},
468
- }
469
- }))
470
-
471
-
472
- <faultcode>SOAP-ENV:Client</faultcode>
473
- <faultstring>Message does not have necessary info</faultstring>
474
- <faultactor>http://gizmos.com/order</faultactor>
475
- <detail>
476
- <PO:order xmlns:PO="http://gizmos.com/orders/">Quantity element does not have a value</PO:order>
477
- <PO:confirmation xmlns:PO="http://gizmos.com/confirm">Incomplete address: no zip code</PO:confirmation>
478
- </detail>
479
-
480
-
481
- */
482
-
483
-
484
-
485
- let Fault = {
486
- faultcode: {localName: 'Client', namespaceURI: 'http://schemas.xmlsoap.org/soap/envelope/'},
487
- faultstring: 'Message does not have necessary info',
488
- faultactor: 'http://gizmos.com/order',
489
- detail: {
490
- null: {
491
- [`
492
- <PO:order xmlns:PO="http://gizmos.com/orders/">Quantity element does not have a value</PO:order>
493
- <PO:confirmation xmlns:PO="http://gizmos.com/confirm">Incomplete address: no zip code</PO:confirmation>
494
- `]: {}
495
- }
496
- }
497
- }
498
-
499
- const soap11 = {
500
- Envelope: {
501
- Body: {
502
- null: {
503
- [xs11.stringify ({Fault})]: {}
504
- }
505
- }
506
- }
507
- }
508
-
509
- /*
510
- <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
511
- <env:Header/>
512
- <env:Body>
513
- <env:Fault>
514
- <env:Code>
515
- <env:Value>env:Sender</env:Value>
516
- </env:Code>
517
- <env:Reason>
518
- <env:Text xml:lang="en-US">Message does not have necessary info</env:Text>
519
- </env:Reason>
520
- <env:Role>http://gizmos.com/order</env:Role>
521
- <env:Detail>
522
- <PO:order xmlns:PO="http://gizmos.com/orders/">Quantity element does not have a value</PO:order>
523
- <PO:confirmation xmlns:PO="http://gizmos.com/confirm">Incomplete address: no zip code</PO:confirmation>
524
- </env:Detail>
525
- </env:Fault>
526
- </env:Body>
527
- </env:Envelope>
528
- */
529
-
530
- console.log (xs11.stringify (soap11))
531
- /*
532
- const xs12 = new XMLSchemata ('test/soap-1.2.xsd')
533
-
534
- Fault = {
535
- Code: {Value: 'env:Sender'},
536
- Reason: {Text: 'Message does not have necessary info'},
537
- Role: 'http://gizmos.com/order',
538
- Detail: {
539
- null: {
540
- [`
541
- <PO:order xmlns:PO="http://gizmos.com/orders/">Quantity element does not have a value</PO:order>
542
- <PO:confirmation xmlns:PO="http://gizmos.com/confirm">Incomplete address: no zip code</PO:confirmation>
543
- `]: {}
544
- }
545
- }
546
- }
463
+ const f =
464
+ new SOAPFault ('Message does not have necessary info', {
465
+ code: 'Client',
466
+ actor: 'http://gizmos.com/order',
467
+ detail
468
+ })
547
469
 
548
- const soap12 = {
549
- Envelope: {
550
- Body: {
551
- null: {
552
- [xs12.stringify ({Fault})]: {}
553
- }
554
- }
555
- }
556
- }
470
+ console.log (SOAP11.message (f))
471
+ console.log (SOAP12.message (f))
557
472
 
558
- console.log (xs12.stringify (soap12))
559
- */
560
473
  }
561
474
 
562
475
 
@@ -578,7 +491,7 @@ async function main () {
578
491
  // await test_004_schemata ()
579
492
  // await test_005_schemata ()
580
493
  // await test_006_schemata ()
581
- // await test_007_wsdl ()
494
+ test_007_wsdl ()
582
495
  // await test_008_schemata ()
583
496
 
584
497
  // test_009_schemata ('smev-message-exchange-service-1.1.xsd')
@@ -591,7 +504,7 @@ async function main () {
591
504
  // test_012_parser ('param_types.xml')
592
505
  // test_012_parser ('20040.wsdl')
593
506
 
594
- test_013_soap ()
507
+ // test_013_soap ()
595
508
 
596
509
  }
597
510
 
package/lib/SOAPHTTP.js DELETED
@@ -1,84 +0,0 @@
1
- const zlib = require ('zlib')
2
-
3
- const VER = {
4
-
5
- '1.1': {
6
- contentType : 'text/xml',
7
- namespaceURI : 'http://schemas.xmlsoap.org/soap/envelope/',
8
- },
9
-
10
- '1.2': {
11
- contentType : 'application/soap+xml',
12
- namespaceURI : 'http://www.w3.org/2003/05/soap-envelope',
13
- },
14
-
15
- }
16
-
17
- const SOAPHTTP = class {
18
-
19
- constructor (versionNumber) {
20
-
21
- if (!(versionNumber in VER)) throw new Exception ('Unknown SOAP version: ' + version)
22
-
23
- const {contentType, namespaceURI} = VER [versionNumber]
24
-
25
- this.charset = 'utf-8'
26
-
27
- this.http = {
28
- method : 'POST',
29
- headers : {"Content-Type": contentType},
30
- }
31
-
32
- this.soap = {
33
- Envelope: {attributes: `xmlns:soap="${namespaceURI}"`},
34
- Header: {attributes: '', content: ''},
35
- Body: {attributes: '', content: ''},
36
- }
37
-
38
- }
39
-
40
- el (name) {
41
-
42
- const {attributes, content} = this.soap [name]
43
-
44
- const qName = 'soap:' + name
45
-
46
- let s = '<' + qName
47
-
48
- if (attributes) s += ' ' + attributes
49
-
50
- if (!content) return s + '/>'
51
-
52
- return s + '>' + content + '</' + qName + '>'
53
-
54
- }
55
-
56
- build () {
57
-
58
- this.http.headers ['Content-Type'] += '; charset=' + this.charset
59
-
60
- this.soap.Envelope.content = this.el ('Header') + this.el ('Body')
61
-
62
- this.http.body = '<?xml version="1.0" encoding="' + this.charset + '"?>' + this.el ('Envelope')
63
-
64
- return this
65
-
66
- }
67
-
68
- gzip (options = {}) {
69
-
70
- if (!('level' in options)) options.level = 9
71
-
72
- this.http.body = zlib.gzipSync (this.http.body, options)
73
-
74
- this.http.headers ['Content-Encoding'] = 'gzip'
75
-
76
- this.http.headers ['Content-Length'] = this.http.body.length
77
-
78
- return this
79
-
80
- }
81
-
82
- }
83
-
84
- module.exports = SOAPHTTP