xml-toolkit 0.0.3 → 0.0.7

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 CHANGED
@@ -1,6 +1,7 @@
1
- const XMLLexer = require ('./lib/XMLLexer')
2
- const SAXEventEmitter = require ('./lib/SAXEventEmitter')
3
- const SAXEvent = require ('./lib/SAXEvent')
4
- const AttributesMap = require ('./lib/AttributesMap')
1
+ const XMLLexer = require ('./lib/XMLLexer')
2
+ const XMLReader = require ('./lib/XMLReader')
3
+ const SAXEvent = require ('./lib/SAXEvent')
4
+ const AttributesMap = require ('./lib/AttributesMap')
5
+ const MoxyLikeJsonEncoder = require ('./lib/MoxyLikeJsonEncoder')
5
6
 
6
- module.exports = {SAXEventEmitter, XMLLexer, SAXEvent, AttributesMap}
7
+ module.exports = {XMLLexer, XMLReader, SAXEvent, AttributesMap, MoxyLikeJsonEncoder}
@@ -1,35 +1,72 @@
1
+ const CH_COLON = ':'.charCodeAt (0)
2
+
1
3
  const AttributesMap = class extends Map {
2
4
 
3
- constructor (xmlReader) {
5
+ constructor (xmlReader, nsMap = null) {
4
6
 
5
7
  super ()
6
-
8
+
7
9
  this._xmlReader = xmlReader
10
+ this._nsMap = nsMap
11
+
12
+ this.fixText = xmlReader.fixText
13
+
14
+ }
15
+
16
+ getLocalName (name) {
17
+
18
+ return (require ('./XMLNode.js')).getLocalName (name)
19
+
20
+ }
21
+
22
+ getNamespaceURI (name) {
23
+
24
+ return this._nsMap.getNamespaceURI (name)
25
+
26
+ }
27
+
28
+ get (name, namespaceURI = null) {
29
+
30
+ if (namespaceURI === null) return super.get (name)
8
31
 
9
- this.fix = null
10
-
11
- if (xmlReader.useEntities) {
32
+ for (const k of this._nsMap.getQNames (name, namespaceURI)) {
12
33
 
13
- const {entityResolver} = xmlReader
34
+ if (!this.has (k)) continue
14
35
 
15
- this.fix = s => entityResolver.fix (s)
16
-
17
- }
36
+ return this.get (k)
18
37
 
38
+ }
39
+
19
40
  }
20
41
 
21
42
  set (k, v) {
22
43
 
23
- {
24
-
25
- const {fix} = this
26
-
27
- if (fix !== null) v = fix (v)
44
+ const {_nsMap} = this; if (_nsMap !== null) {
45
+
46
+ if (k.slice (0, 5) === 'xmlns') {
47
+
48
+ if (k.length === 5) {
49
+
50
+ _nsMap.set ('', v)
51
+
52
+ return this
53
+
54
+ }
55
+
56
+ if (k.charCodeAt (5) === CH_COLON) {
57
+
58
+ _nsMap.set (k.slice (6), v)
59
+
60
+ return this
61
+
62
+ }
63
+
64
+ }
28
65
 
29
66
  }
30
67
 
31
- return super.set (k, v)
32
-
68
+ return super.set (k, this.fixText (v))
69
+
33
70
  }
34
71
 
35
72
  }
@@ -0,0 +1,41 @@
1
+ const SAXEvent = require ('./SAXEvent.js')
2
+
3
+ const set = (o, k, nv) => {
4
+
5
+ if (!(k in o)) return o [k] = nv
6
+
7
+ const ov = o [k]; if (!Array.isArray (ov)) o [k] = [ov]
8
+
9
+ o [k].push (nv)
10
+
11
+ }
12
+
13
+ const xform = ({children, attributes}) => {
14
+
15
+ let o = attributes == null ? {} : Object.fromEntries (attributes.entries ())
16
+
17
+ if (children != null) for (const child of children) switch (child.type) {
18
+
19
+ case SAXEvent.TYPES.CHARACTERS: return child.text
20
+
21
+ case SAXEvent.TYPES.END_ELEMENT: set (o, child.localName, xform (child))
22
+
23
+ }
24
+
25
+ return o
26
+
27
+ }
28
+
29
+ const MoxyLikeJsonEncoder = function (options = {}) {
30
+
31
+ return function (node) {
32
+
33
+ let result = xform (node)
34
+
35
+ return options.wrap ? {[node.localName]: result} : result
36
+
37
+ }
38
+
39
+ }
40
+
41
+ module.exports = MoxyLikeJsonEncoder
@@ -0,0 +1,48 @@
1
+ const NamespacesMap = class extends Map {
2
+
3
+ constructor (xmlNode) {
4
+
5
+ const {parent} = xmlNode
6
+
7
+ if (parent === null) {
8
+
9
+ super ()
10
+
11
+ }
12
+ else {
13
+
14
+ super (parent.namespacesMap)
15
+
16
+ }
17
+
18
+ }
19
+
20
+ getNamespaceURI (name, useDefault = false) {
21
+
22
+ const pos = name.indexOf (':'), noColon = pos === -1
23
+
24
+ if (noColon && !useDefault) return null
25
+
26
+ const key = noColon ? '' : name.slice (0, pos)
27
+
28
+ if (!this.has (key)) return null
29
+
30
+ return this.get (key)
31
+
32
+ }
33
+
34
+ * getQNames (localName, namespaceURI) {
35
+
36
+ for (let [k, v] of this.entries ())
37
+
38
+ if (v === namespaceURI)
39
+
40
+ yield k === '' ? localName :
41
+
42
+ k + ':' + localName
43
+
44
+ }
45
+
46
+ }
47
+
48
+ module.exports = NamespacesMap
package/lib/SAXEvent.js CHANGED
@@ -1,6 +1,7 @@
1
1
  const assert = require ('assert')
2
2
 
3
3
  const CH_LT = '<'.charCodeAt (0)
4
+ const CH_GT = '>'.charCodeAt (0)
4
5
  const CH_EXCLAMATION = '!'.charCodeAt (0)
5
6
  const CH_QUESTION = '?'.charCodeAt (0)
6
7
  const CH_SLASH = '/'.charCodeAt (0)
@@ -46,7 +47,7 @@ const SAXEvent = class {
46
47
 
47
48
  case CH_QUESTION:
48
49
 
49
- switch (src.slice (2, 5).toLowerCase ()) {
50
+ switch (src.slice (2, 5).toUpperCase ()) {
50
51
 
51
52
  case STR_XML: return START_DOCUMENT
52
53
 
@@ -95,6 +96,20 @@ const SAXEvent = class {
95
96
  }
96
97
 
97
98
  }
99
+
100
+ get xml () {
101
+
102
+ switch (this.type) {
103
+
104
+ case END_DOCUMENT: return ''
105
+
106
+ case END_ELEMENT: return this.isSelfEnclosed ? '' : `</${this.name}>`
107
+
108
+ default: return this.src
109
+
110
+ }
111
+
112
+ }
98
113
 
99
114
  get attributes () {
100
115
 
@@ -106,6 +121,38 @@ const SAXEvent = class {
106
121
 
107
122
  }
108
123
 
124
+ get name () {
125
+
126
+ if (this._afterName === 0) this.findAfterName ()
127
+
128
+ const {src} = this, start = src.charCodeAt (1) === CH_SLASH ? 2 : 1
129
+
130
+ return this.src.slice (start, this._afterName).trim ()
131
+
132
+ }
133
+
134
+ findAfterName () {
135
+
136
+ const {src} = this, {length} = src;
137
+
138
+ for (let i = 1; i < length; i ++) {
139
+
140
+ const c = src.charCodeAt (i)
141
+
142
+ switch (c) {
143
+ case CH_SLASH:
144
+ case CH_GT:
145
+ return this._afterName = i
146
+ }
147
+
148
+ if (c <= 32) return this._afterName = i
149
+
150
+ }
151
+
152
+ this._afterName = length - 1
153
+
154
+ }
155
+
109
156
  writeAttributesToMap (m) {
110
157
 
111
158
  const {src} = this
@@ -149,6 +196,24 @@ const SAXEvent = class {
149
196
 
150
197
  }
151
198
 
199
+ get isStartElement () {
200
+
201
+ return this.type === START_ELEMENT
202
+
203
+ }
204
+
205
+ get isEndElement () {
206
+
207
+ return this.type === END_ELEMENT
208
+
209
+ }
210
+
211
+ get isCharacters () {
212
+
213
+ return this.type === CHARACTERS
214
+
215
+ }
216
+
152
217
  }
153
218
 
154
219
  SAXEvent.TYPES = {
package/lib/XMLNode.js ADDED
@@ -0,0 +1,141 @@
1
+ const SAXEvent = require ('./SAXEvent.js')
2
+ const AttributesMap = require ('./AttributesMap')
3
+ const NamespacesMap = require ('./NamespacesMap')
4
+
5
+ const XML_READER = Symbol ('_xmlReader')
6
+ const ATTRIBUTES = Symbol ('_attributes')
7
+ const TYPE = Symbol ('_type')
8
+ const PARENT = Symbol ('_parent')
9
+ const LEVEL = Symbol ('_level')
10
+ const NS_MAP = Symbol ('_ns_map')
11
+
12
+ const XMLNode = class extends SAXEvent {
13
+
14
+ constructor (src, xmlReader, _type) {
15
+
16
+ super (src)
17
+
18
+ this [TYPE] = _type || super.type
19
+
20
+ this [XML_READER] = xmlReader
21
+ this [PARENT] = null
22
+ this [LEVEL] = 0
23
+
24
+ this.children = null
25
+
26
+ }
27
+
28
+ cloneStart () {
29
+
30
+ let e = new XMLNode (this.src, this [XML_READER], SAXEvent.TYPES.START_ELEMENT)
31
+
32
+ e [PARENT] = this [PARENT]
33
+ e [LEVEL] = this [LEVEL]
34
+ e [ATTRIBUTES] = this [ATTRIBUTES]
35
+ e [NS_MAP] = this [NS_MAP]
36
+
37
+ return e
38
+
39
+ }
40
+
41
+ get level () {
42
+
43
+ return this [LEVEL]
44
+
45
+ }
46
+
47
+ get parent () {
48
+
49
+ return this [PARENT]
50
+
51
+ }
52
+
53
+ get namespacesMap () {
54
+
55
+ return this [NS_MAP]
56
+
57
+ }
58
+
59
+ readNamespaces () {
60
+
61
+ this [NS_MAP] = new NamespacesMap (this)
62
+
63
+ this.readAttributes ()
64
+
65
+ }
66
+
67
+ set parent (_parent) {
68
+
69
+ if (_parent == null) return
70
+
71
+ this [PARENT] = _parent
72
+
73
+ this [LEVEL] = 1 + _parent.level
74
+
75
+ const {children} = _parent; if (children !== null) children.push (this)
76
+
77
+ }
78
+
79
+ get type () {
80
+
81
+ return this [TYPE]
82
+
83
+ }
84
+
85
+ set type (_type) {
86
+
87
+ this [TYPE] = _type
88
+
89
+ }
90
+
91
+ get localName () {
92
+
93
+ return XMLNode.getLocalName (this.name)
94
+
95
+ }
96
+
97
+ get namespaceURI () {
98
+
99
+ return this.namespacesMap.getNamespaceURI (this.name, true)
100
+
101
+ }
102
+
103
+ readAttributes () {
104
+
105
+ const m = new AttributesMap (this [XML_READER], this [NS_MAP])
106
+
107
+ this.writeAttributesToMap (m)
108
+
109
+ this [ATTRIBUTES] = m
110
+
111
+ }
112
+
113
+ get attributes () {
114
+
115
+ if (!(ATTRIBUTES in this)) this.readAttributes ()
116
+
117
+ return this [ATTRIBUTES]
118
+
119
+ }
120
+
121
+ get text () {
122
+
123
+ let s = super.text
124
+
125
+ if (this [TYPE] === SAXEvent.TYPES.CHARACTERS) s = this [XML_READER].fixText (s)
126
+
127
+ return s
128
+
129
+ }
130
+
131
+ }
132
+
133
+ XMLNode.getLocalName = name => {
134
+
135
+ const pos = name.indexOf (':'); if (pos === -1) return name
136
+
137
+ return name.slice (pos + 1)
138
+
139
+ }
140
+
141
+ module.exports = XMLNode
package/lib/XMLReader.js CHANGED
@@ -1,6 +1,11 @@
1
1
  const assert = require ('assert')
2
2
  const {Transform} = require ('stream')
3
3
  const SAXEvent = require ('./SAXEvent.js')
4
+ const XMLNode = require ('./XMLNode.js')
5
+ const XMLLexer = require ('./XMLLexer.js')
6
+
7
+ const OPT_SRC = Symbol ('_src')
8
+ const OPT_SAX = Symbol ('_sax')
4
9
 
5
10
  const XMLReader = class extends Transform {
6
11
 
@@ -15,14 +20,102 @@ const XMLReader = class extends Transform {
15
20
  if (!('useEntities' in options)) options.useEntities = true
16
21
  assert (options.useEntities === true || options.useEntities === false, 'options.useEntities must be boolean, not ' + typeof options.useEntities)
17
22
 
18
- super (options)
23
+ if (!('useNamespaces' in options)) options.useNamespaces = true
24
+ assert (options.useNamespaces === true || options.useNamespaces === false, 'options.useNamespaces must be boolean, not ' + typeof options.useNamespaces)
25
+
26
+ let {filterElements} = options; delete options.filterElements; if (filterElements != null) {
27
+
28
+ assert (!('filter' in options), 'filter and filterElements options cannot be set simultaneously')
29
+
30
+ switch (typeof filterElements) {
31
+
32
+ case 'string':
33
+ const localName = filterElements
34
+ filterElements = e => e.localName === localName
35
+
36
+ case 'function':
37
+ options.filter = e => e.type === SAXEvent.TYPES.END_ELEMENT && filterElements (e)
38
+ break
39
+
40
+ default:
41
+ assert.fail ('options.filterElements must be a string or function')
19
42
 
20
- this.stripSpace = options.stripSpace
21
- this.useEntities = options.useEntities
43
+ }
22
44
 
45
+ }
46
+
47
+ let {collect} = options; delete options.collect
48
+ assert (collect == null || typeof collect === 'function', 'options.collect must be a function, not ' + typeof collect)
49
+ if (collect == null && filterElements != null) collect = filterElements
50
+
51
+ const {filter} = options; delete options.filter
52
+ assert (filter == null || typeof filter === 'function', 'options.filter must be a function, not ' + typeof filter)
53
+
54
+ const {map} = options; delete options.map
55
+ assert (map == null || typeof map === 'function', 'options.map must be a function, not ' + typeof map)
56
+
57
+ super (options)
58
+
59
+ this.stripSpace = options.stripSpace
60
+ this.useEntities = options.useEntities
61
+ this.useNamespaces = options.useNamespaces
62
+ this.collect = collect || null
63
+ this.filter = filter || null
64
+ this.map = map || null
65
+
23
66
  if (this.useEntities) this.entityResolver = new (require ('./EntityResolver.js')) ()
24
67
 
25
68
  this.text = ''
69
+ this.element = null
70
+ this.position = 0n
71
+
72
+ this [OPT_SRC] = null; this.on ('pipe', src => this [OPT_SRC] = src)
73
+
74
+ this [OPT_SAX] = null
75
+
76
+ }
77
+
78
+ async findFirst () {
79
+
80
+ assert (!this.isSAX, 'SAX event subscriber detected, findFirst () cannot be used')
81
+
82
+ return new Promise ((ok, fail) => {
83
+
84
+ this.once ('error', fail)
85
+
86
+ const THE_END = 'finish', nope = () => ok (null)
87
+
88
+ this.on (THE_END, nope)
89
+
90
+ this.on ('data', e => {
91
+
92
+ this.off (THE_END, nope)
93
+
94
+ if (e.type === SAXEvent.TYPES.END_DOCUMENT) return nope ()
95
+
96
+ const src = this [OPT_SRC]; if (src !== null) src.unpipe (this)
97
+
98
+ ok (e)
99
+
100
+ this.destroy ()
101
+
102
+ })
103
+
104
+ })
105
+
106
+ }
107
+
108
+ process (src, lexerOptions = {}) {
109
+
110
+ const lex = new XMLLexer (lexerOptions)
111
+
112
+ lex.once ('error', x => this.destroy (x))
113
+
114
+ lex.pipe (this)
115
+
116
+ if (Buffer.isBuffer (src) || typeof src === 'string') lex.end (src); else src.pipe (lex)
117
+
118
+ return this
26
119
 
27
120
  }
28
121
 
@@ -30,11 +123,42 @@ const XMLReader = class extends Transform {
30
123
 
31
124
  this.flush_text ()
32
125
 
33
- this.push ({type: SAXEvent.TYPES.END_DOCUMENT})
126
+ this.publish (new XMLNode ('', this), SAXEvent.TYPES.END_DOCUMENT)
34
127
 
35
128
  callback ()
36
129
 
37
130
  }
131
+
132
+ get isSAX () {
133
+
134
+ const v = this [OPT_SAX]; if (v !== null) return v
135
+
136
+ for (const type of Object.values (SAXEvent.TYPES)) if (this.listenerCount (type) !== 0) return this [OPT_SAX] = true
137
+
138
+ return this [OPT_SAX] = false
139
+
140
+ }
141
+
142
+ publish (xmlNode, type = null) {
143
+
144
+ if (type !== null) xmlNode.type = type
145
+
146
+ const {filter} = this; if (filter !== null && !filter (xmlNode)) return
147
+
148
+ const {map} = this, value = map === null ? xmlNode : map (xmlNode)
149
+
150
+ if (this.isSAX) {
151
+
152
+ this.emit (xmlNode.type, value)
153
+
154
+ }
155
+ else {
156
+
157
+ this.push (value)
158
+
159
+ }
160
+
161
+ }
38
162
 
39
163
  flush_text () {
40
164
 
@@ -42,41 +166,104 @@ const XMLReader = class extends Transform {
42
166
 
43
167
  if (this.stripSpace) text = text.trim ()
44
168
 
45
- if (text.length !== 0) this.push (new SAXEvent (text))
169
+ if (text.length !== 0) {
170
+
171
+ let e = new XMLNode (text, this, SAXEvent.TYPES.CHARACTERS)
172
+
173
+ e.parent = this.element
174
+
175
+ this.publish (e)
176
+
177
+ }
46
178
 
47
179
  this.text = ''
48
180
 
49
181
  }
182
+
183
+ get fixText () {
184
+
185
+ if (!this.useEntities) return s => s
186
+
187
+ const {entityResolver} = this
188
+
189
+ return s => entityResolver.fix (s)
190
+
191
+ }
50
192
 
51
193
  _transform (chunk, encoding, callback) {
52
194
 
53
- if (chunk.length !== 0) {
195
+ const {length} = chunk; if (length !== 0) {
54
196
 
55
- let e = new SAXEvent (chunk), {type} = e
197
+ let e = new XMLNode (chunk, this), {type} = e, {element} = this
56
198
 
57
199
  switch (type) {
58
200
 
59
201
  case SAXEvent.TYPES.CHARACTERS:
60
-
61
- this.text += this.useEntities ? this.entityResolver.fix (e.text) : e.text
62
- break
63
-
64
202
  case SAXEvent.TYPES.CDATA:
65
203
 
66
204
  this.text += e.text
67
- break
205
+ return callback ()
68
206
 
69
207
  default:
70
208
 
71
209
  this.flush_text ()
72
- this.push (e)
210
+
211
+ }
212
+
213
+ switch (type) {
214
+
215
+ case SAXEvent.TYPES.END_ELEMENT:
216
+
217
+ if (element === null) throw new Error (`Unbalanced end element tag "${chunk}" occured at position ${this.position}`)
218
+
219
+ e = element
220
+
221
+ e.type = type
222
+
223
+ this.element = element.parent
224
+
73
225
  break
74
226
 
227
+ default:
228
+
229
+ e.parent = element
230
+
75
231
  }
76
232
 
77
- if (type === SAXEvent.TYPES.START_ELEMENT && e.isSelfEnclosed) this.push (new SAXEvent ('</>'))
233
+ const isStart = type === SAXEvent.TYPES.START_ELEMENT
78
234
 
79
- }
235
+ if (isStart && this.useNamespaces) e.readNamespaces ()
236
+
237
+ this.publish (isStart ? e.cloneStart () : e)
238
+
239
+ if (isStart) {
240
+
241
+ if (e.isSelfEnclosed) {
242
+
243
+ this.publish (e, SAXEvent.TYPES.END_ELEMENT)
244
+
245
+ }
246
+ else {
247
+
248
+ if (
249
+
250
+ (this.element !== null && this.element.children !== null)
251
+
252
+ ||
253
+
254
+ (this.collect !== null && this.collect (e))
255
+
256
+ ) e.children = []
257
+
258
+ this.element = e
259
+
260
+ }
261
+
262
+ }
263
+
264
+ this.position += BigInt (length)
265
+
266
+ }
80
267
 
81
268
  callback ()
82
269
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xml-toolkit",
3
- "version": "0.0.3",
3
+ "version": "0.0.7",
4
4
  "description": "Collection of classes for dealing with XML",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/test/soap.xml ADDED
@@ -0,0 +1,40 @@
1
+ <?xml version="1.0"?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
2
+ <SOAP-ENV:Header/>
3
+ <SOAP-ENV:Body>
4
+ <SendRequestRequest xmlns="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/1.1" xmlns:ns0="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/basic/1.1">
5
+ <SenderProvidedRequestData Id="Ue7e71ce1-7ce3-4ca5-a689-1a8f2edbb1af">
6
+ <MessageID>3931cda8-3245-11ec-b0bc-000c293433a0</MessageID>
7
+ <ns0:MessagePrimaryContent>
8
+ <ExportDebtRequestsRequest xmlns="urn:dom.gosuslugi.ru/debt-responses/1.0.0" xmlns:ns0="urn:dom.gosuslugi.ru/common/1.2.0">
9
+ <ns0:information-system-id ns0:foo="bar" foo="baz">1f0823b4-9c11-4622-a561-6bae5c0a00ba</ns0:information-system-id>
10
+ <ns0:organization-id>6eef689e-48bb-4eb0-55da-18b6db9909b7</ns0:organization-id>
11
+ <request-id>87c4c940-6ad3-11eb-9439-0242ac130002</request-id>
12
+ </ExportDebtRequestsRequest>
13
+ </ns0:MessagePrimaryContent>
14
+ <TestMessage xmlns:ns1="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/1.1"/>
15
+ </SenderProvidedRequestData>
16
+ <CallerInformationSystemSignature>
17
+ <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
18
+ <ds:SignedInfo>
19
+ <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
20
+ <ds:SignatureMethod Algorithm="urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34102012-gostr34112012-256"/>
21
+ <ds:Reference URI="#Ue7e71ce1-7ce3-4ca5-a689-1a8f2edbb1af">
22
+ <ds:Transforms>
23
+ <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
24
+ <ds:Transform Algorithm="urn://smev-gov-ru/xmldsig/transform"/>
25
+ </ds:Transforms>
26
+ <ds:DigestMethod Algorithm="urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34112012-256"/>
27
+ <ds:DigestValue>XrXb2BlS8uo68tyQ++KE1yPjj5y3TynCaRIpXeL5uPk=</ds:DigestValue>
28
+ </ds:Reference>
29
+ </ds:SignedInfo>
30
+ <ds:SignatureValue>9Th1waEJy83XQxxKD5DXT29g885RhJoYe3ZQ1HrbrQLCEBchCCTJtcThYmNBPL/HzF2gp7KQs3gXrnsj+OBlJQ==</ds:SignatureValue>
31
+ <ds:KeyInfo>
32
+ <ds:X509Data>
33
+ <ds:X509Certificate>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</ds:X509Certificate>
34
+ </ds:X509Data>
35
+ </ds:KeyInfo>
36
+ </ds:Signature>
37
+ </CallerInformationSystemSignature>
38
+ </SendRequestRequest>
39
+ </SOAP-ENV:Body>
40
+ </SOAP-ENV:Envelope>
package/test/test.js CHANGED
@@ -1,6 +1,6 @@
1
1
  const fs = require ('fs')
2
2
  const assert = require ('assert')
3
- const {SAXEventEmitter, SAXEvent, XMLLexer, AttributesMap} = require ('../')
3
+ const {XMLReader, SAXEvent, XMLLexer, AttributesMap, MoxyLikeJsonEncoder} = require ('../')
4
4
 
5
5
  async function test_001_lexer_sync (fn) {
6
6
 
@@ -52,55 +52,51 @@ async function test_003_emitter_sync (fn) {
52
52
 
53
53
  const xml = fs.readFileSync (
54
54
  'test/' + fn
55
- // , 'utf-8'
55
+ , 'utf-8'
56
56
  )
57
57
 
58
58
  console.log (xml)
59
59
 
60
- const lex = new XMLLexer ({
61
- // maxLength: 40,
62
- // encoding: 'ascii',
60
+ const sax = new XMLReader ({
63
61
  // stripSpace: true,
62
+ // filterElements: 'SendRequestRequest',
63
+ // map: MoxyLikeJsonEncoder ({wrap: 1})
64
64
  })
65
65
 
66
- const sax = new SAXEventEmitter ({
67
- stripSpace: true,
68
- // useEntities: false,
69
- })
70
-
71
- lex.pipe (sax)
72
-
73
66
  /*
74
67
  for (let event of [
75
- 'StartDocument',
76
- 'ProcessingInstruction',
77
- 'Comment',
78
- 'DTD',
79
- 'StartElement',
80
- 'Characters',
81
- 'EndElement',
82
- 'EndDocument',
83
- ]) sax.on (event, data => console.log ([event, data]))
84
- */
85
-
86
- sax.on ('StartElement', event => {
68
+ 'data',
69
+ 'close',
70
+ 'end',
71
+ 'finish',
72
+ // 'EndElement',
73
+ ]) sax.on (event, data => {
74
+
75
+ console.log ([JSON.stringify (data, null, 2), event])
87
76
 
88
- console.log ({event})
89
-
90
- const attr = new AttributesMap (sax)
91
-
92
- event.writeAttributesToMap (attr)
93
-
94
- console.log ({attr})
95
-
96
77
  })
78
+ */
97
79
 
98
- // lexer.on ('data', data => console.log ({data}))
99
80
 
100
- // for (let c of xml) lexer.write (c); lexer.end ()
101
- // for (let c of xml) lexer.write (Buffer.from ([c])); lexer.end ()
81
+ // sax.process (fs.createReadStream ('test/' + fn))
82
+
83
+ sax.process (xml)
84
+
85
+ //console.log (sax)
86
+ //console.log (sax.isSAX)
87
+
88
+
89
+ let s = ''
90
+ for await (const e of sax) {
91
+ // s += xml
92
+ console.log ([e.type, e.isStartElement, e.isEndElement , e.isCharacters])
93
+ }
94
+
95
+ //console.log ([xml, s])
96
+
97
+ // const v = await sax.findFirst ()
102
98
 
103
- lex.end (xml)
99
+ // console.log (JSON.stringify (v, null, 2))
104
100
 
105
101
  }
106
102
 
@@ -116,7 +112,8 @@ async function main () {
116
112
  // await test_003_emitter_sync ('E05a.xml')
117
113
  // await test_003_emitter_sync ('param_types.xml')
118
114
  // await test_003_emitter_sync ('not-sa01.xml')
119
- await test_003_emitter_sync ('ent.xml')
115
+ // await test_003_emitter_sync ('ent.xml')
116
+ await test_003_emitter_sync ('soap.xml')
120
117
 
121
118
  }
122
119
 
@@ -1,15 +0,0 @@
1
- const XMLReader = require ('./XMLReader.js')
2
-
3
- const SAXEventEmitter = class extends XMLReader {
4
-
5
- constructor (options = {}) {
6
-
7
- super (options)
8
-
9
- this.on ('data', e => this.emit (e.type, e))
10
-
11
- }
12
-
13
- }
14
-
15
- module.exports = SAXEventEmitter