xml-toolkit 0.0.1

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 do-
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,4 @@
1
+ # node-xml-toolkit
2
+ Collection of classes for dealing with XML
3
+
4
+ This is a project template. The actual code is yet to be written.
package/index.js ADDED
@@ -0,0 +1,5 @@
1
+ const XMLLexer = require ('./lib/XMLLexer')
2
+ const SAXEventEmitter = require ('./lib/SAXEventEmitter')
3
+ const SAXEvent = require ('./lib/SAXEvent')
4
+
5
+ module.exports = {SAXEventEmitter, XMLLexer, SAXEvent}
@@ -0,0 +1,166 @@
1
+ const assert = require ('assert')
2
+
3
+ const CH_LT = '<'.charCodeAt (0)
4
+ const CH_EXCLAMATION = '!'.charCodeAt (0)
5
+ const CH_QUESTION = '?'.charCodeAt (0)
6
+ const CH_SLASH = '/'.charCodeAt (0)
7
+ const CH_MINUS = '-'.charCodeAt (0)
8
+
9
+ const STR_XML = 'XML'
10
+ const STR_CDATA = '[CDATA['
11
+ const STR_DOCTYPE = 'DOCTYPE'
12
+
13
+ const START_DOCUMENT = 'StartDocument'
14
+ const PROCESSING_INSTRUCTION = 'ProcessingInstruction'
15
+ const COMMENT = 'Comment'
16
+ const DTD = 'DTD'
17
+ const START_ELEMENT = 'StartElement'
18
+ const CHARACTERS = 'Characters'
19
+ const END_ELEMENT = 'EndElement'
20
+ const END_DOCUMENT = 'EndDocument'
21
+ const CDATA = 'CDATA'
22
+
23
+ const SAXEvent = class {
24
+
25
+ constructor (src) {
26
+
27
+ this.src = src
28
+
29
+ this._afterName = 0
30
+
31
+ }
32
+
33
+ get type () {
34
+
35
+ const {src} = this
36
+
37
+ switch (src.charCodeAt (0)) {
38
+
39
+ case CH_LT:
40
+
41
+ switch (src.charCodeAt (1)) {
42
+
43
+ case CH_SLASH:
44
+
45
+ return END_ELEMENT
46
+
47
+ case CH_QUESTION:
48
+
49
+ switch (src.slice (2, 5).toLowerCase ()) {
50
+
51
+ case STR_XML: return START_DOCUMENT
52
+
53
+ default: return PROCESSING_INSTRUCTION
54
+
55
+ }
56
+
57
+ case CH_EXCLAMATION:
58
+
59
+ if (src.charCodeAt (2) === CH_MINUS) return COMMENT
60
+
61
+ switch (src.slice (2, 9)) {
62
+
63
+ case STR_CDATA: return CDATA
64
+
65
+ case STR_DOCTYPE: return DTD
66
+
67
+ default: return null
68
+
69
+ }
70
+
71
+ default: return START_ELEMENT
72
+
73
+ }
74
+
75
+ break
76
+
77
+ default:
78
+
79
+ return CHARACTERS
80
+
81
+ }
82
+
83
+ }
84
+
85
+ get text () {
86
+
87
+ const {src} = this
88
+
89
+ switch (src.charCodeAt (0)) {
90
+
91
+ case CH_LT: return src.slice (9, -3)
92
+
93
+ default: return src
94
+
95
+ }
96
+
97
+ }
98
+
99
+ get attributes () {
100
+
101
+ const m = new Map ()
102
+
103
+ this.writeAttributesToMap (m)
104
+
105
+ return m
106
+
107
+ }
108
+
109
+ writeAttributesToMap (m) {
110
+
111
+ const {src} = this
112
+
113
+ let start = this._afterName; while (true) {
114
+
115
+ const eq = src.indexOf ('=', start); if (eq === -1) break
116
+
117
+ const q = src.indexOf (src.charAt (eq + 1), eq + 2); if (q === -1) break
118
+
119
+ let k = src.slice (start, eq)
120
+
121
+ if (start === 0) {
122
+
123
+ let p = k.length - 2; while (p !== 0 && k.charCodeAt (p) <= 32) p --
124
+
125
+ k = k.slice (this._afterName = p)
126
+
127
+ }
128
+ else {
129
+
130
+ k = k.trim ()
131
+
132
+ }
133
+
134
+ m.set (k, src.slice (eq + 2, q))
135
+
136
+ start = q + 1
137
+
138
+ }
139
+
140
+ return m
141
+
142
+ }
143
+
144
+ get isSelfEnclosed () {
145
+
146
+ const {src} = this
147
+
148
+ return src.charCodeAt (src.length - 2) === CH_SLASH
149
+
150
+ }
151
+
152
+ }
153
+
154
+ SAXEvent.TYPES = {
155
+ START_DOCUMENT,
156
+ PROCESSING_INSTRUCTION,
157
+ COMMENT,
158
+ DTD,
159
+ START_ELEMENT,
160
+ CHARACTERS,
161
+ END_ELEMENT,
162
+ END_DOCUMENT,
163
+ CDATA,
164
+ }
165
+
166
+ module.exports = SAXEvent
@@ -0,0 +1,42 @@
1
+ const assert = require ('assert')
2
+ const {Writable} = require ('stream')
3
+ const SAXEvent = require ('./SAXEvent.js')
4
+
5
+ const SAXEventEmitter = class extends Writable {
6
+
7
+ constructor (options = {}) {
8
+
9
+ options.decodeStrings = false
10
+
11
+ super (options)
12
+
13
+ this.on ('finish', () => this.emit (SAXEvent.TYPES.END_DOCUMENT))
14
+
15
+ }
16
+
17
+ _write (chunk, encoding, callback) {
18
+
19
+ if (chunk.length !== 0) {
20
+
21
+ let e = new SAXEvent (chunk), {type} = e
22
+
23
+ if (type === SAXEvent.TYPES.CDATA) {
24
+ e = new SAXEvent (e.text)
25
+ type = SAXEvent.TYPES.CHARACTERS
26
+ }
27
+
28
+ this.emit (type, e)
29
+
30
+ if (type === SAXEvent.TYPES.TYPE_START_ELEMENT && e.isSelfEnclosing ()) {
31
+ this.emit (SAXEvent.TYPES.TYPE_END_ELEMENT, e)
32
+ }
33
+
34
+ }
35
+
36
+ callback ()
37
+
38
+ }
39
+
40
+ }
41
+
42
+ module.exports = SAXEventEmitter
@@ -0,0 +1,292 @@
1
+ const assert = require ('assert')
2
+ const {Transform} = require ('stream')
3
+ const {StringDecoder} = require('string_decoder')
4
+
5
+ const ST_TEXT = 0
6
+ const ST_LT = 1
7
+ const ST_LT_X = 2
8
+ const ST_TAG = 3
9
+ const ST_TAG_X = 4
10
+
11
+ const CH_EXCLAMATION = '!'.charCodeAt (0)
12
+ const CH_QUESTION = '?'.charCodeAt (0)
13
+ const CH_MINUS = '-'.charCodeAt (0)
14
+ const CH_SQUARE = '['.charCodeAt (0)
15
+ const CH_GT = '>'.charCodeAt (0)
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')
22
+
23
+ const S_ENCODING = Symbol ('encoding')
24
+
25
+ const XMLLexer = class extends Transform {
26
+
27
+ constructor (options = {}) {
28
+
29
+ options.readableObjectMode = true
30
+ options.decodeStrings = false
31
+
32
+ let encoding = options.encoding; delete options.encoding
33
+ if (encoding == null) encoding = 'utf8'
34
+
35
+ let maxLength = options.maxLength; delete options.maxLength
36
+ if (maxLength == null) maxLength = 1 << 20
37
+
38
+ assert (Number.isInteger (maxLength), 'maxLength must be integer, not ' + maxLength)
39
+ assert (maxLength > 0, 'maxLength must be positive, not ' + maxLength)
40
+
41
+ if (!('stripSpace' in options)) options.stripSpace = false
42
+ assert (options.stripSpace === true || options.stripSpace === false, 'options.stripSpace must be boolean, not ' + typeof options.stripSpace)
43
+
44
+ super (options)
45
+
46
+ this.decoder = new StringDecoder ('utf8')
47
+
48
+ this.stripSpace = options.stripSpace
49
+ this.body = ''
50
+ this.start = 0
51
+ this.setState (ST_TEXT)
52
+ this.beforeBody = 0n
53
+
54
+ this [S_ENCODING] = encoding
55
+ this.maxLength = maxLength
56
+
57
+ }
58
+
59
+ isClosing (pos) {
60
+
61
+ const {awaited} = this, {length} = awaited; if (length === 0) return true
62
+
63
+ let from = pos - length; if (from < this.start) return false
64
+
65
+ if (this.body.charCodeAt (from) !== awaited [0]) return false
66
+
67
+ if (length === 2 && this.body.charCodeAt (from + 1) !== awaited [1]) return false
68
+
69
+ return true
70
+
71
+ }
72
+
73
+ setState (state, awaited = null) {
74
+
75
+ switch (state) {
76
+
77
+ case ST_TAG:
78
+ case ST_TAG_X:
79
+ assert (awaited != null, 'ST_TAG[_X]: awaited is mandatory')
80
+ break
81
+
82
+ default:
83
+ assert (awaited === null, 'not ST_TAG[_X]: awaited must be null')
84
+ this.position = 0
85
+ break
86
+
87
+ }
88
+
89
+ this.state = state
90
+ this.awaited = awaited
91
+
92
+ }
93
+
94
+ parse () {
95
+
96
+ outer: while (true) {
97
+
98
+ const {start, body} = this
99
+
100
+ switch (this.state) {
101
+
102
+ case ST_TEXT:
103
+
104
+ {
105
+
106
+ const pos = body.indexOf ('<', start); switch (pos) {
107
+
108
+ case -1:
109
+ return
110
+
111
+ case 0:
112
+ this.setState (ST_LT)
113
+ break
114
+
115
+ default:
116
+ this.publishTo (pos - 1)
117
+ this.setState (ST_LT)
118
+
119
+ }
120
+
121
+ }
122
+
123
+ break
124
+
125
+ case ST_LT:
126
+
127
+ {
128
+
129
+ const pos = start + 1; if (pos >= body.length) return null
130
+
131
+ switch (body.charCodeAt (pos)) {
132
+
133
+ case CH_EXCLAMATION:
134
+ this.setState (ST_LT_X)
135
+ break
136
+
137
+ case CH_QUESTION:
138
+ this.setState (ST_TAG, CL_PI)
139
+ break
140
+
141
+ default:
142
+ this.setState (ST_TAG, CL_DEAFULT)
143
+ break
144
+ }
145
+
146
+ }
147
+
148
+
149
+ break
150
+
151
+ case ST_LT_X:
152
+
153
+ {
154
+
155
+ const pos = start + 2; if (pos >= body.length) return null
156
+
157
+ switch (body.charCodeAt (pos)) {
158
+
159
+ case CH_MINUS:
160
+ this.setState (ST_TAG, CL_COMMENT)
161
+ break
162
+
163
+ default:
164
+ this.setState (ST_TAG_X, CL_DEAFULT)
165
+ this.position = pos
166
+ break
167
+
168
+ }
169
+
170
+ }
171
+
172
+ break
173
+
174
+ case ST_TAG:
175
+
176
+ let pos = start; while (true) {
177
+
178
+ pos = body.indexOf ('>', pos + 1); if (pos === -1) return
179
+
180
+ if (!this.isClosing (pos)) continue
181
+
182
+ this.publishTo (pos)
183
+
184
+ this.setState (ST_TEXT)
185
+
186
+ continue outer
187
+
188
+ }
189
+
190
+ case ST_TAG_X:
191
+
192
+ for (let pos = this.position + 1; pos < body.length; pos ++) {
193
+
194
+ switch (body.charCodeAt (pos)) {
195
+
196
+ case CH_SQUARE:
197
+
198
+ switch (this.awaited) {
199
+
200
+ case CL_DEAFULT:
201
+ this.awaited = CL_SQ_1
202
+ break
203
+
204
+ case CL_SQ_1:
205
+ this.awaited = CL_SQ_2
206
+ break
207
+
208
+ }
209
+
210
+ this.position = pos
211
+ break
212
+
213
+ case CH_GT:
214
+ if (!this.isClosing (pos)) break
215
+ this.publishTo (pos)
216
+ this.setState (ST_TEXT)
217
+ continue outer
218
+
219
+ }
220
+
221
+ }
222
+
223
+ return
224
+
225
+ default:
226
+ throw new Error ('Invalid state: ' + this.state)
227
+
228
+ }
229
+
230
+ }
231
+
232
+ }
233
+
234
+ publishTo (pos) {
235
+
236
+ let lexeme = this.body.slice (this.start, ++ pos)
237
+
238
+ this.start = pos
239
+
240
+ if (this.stripSpace) lexeme = lexeme.trim ()
241
+
242
+ if (lexeme.length !== 0) this.push (lexeme)
243
+
244
+ }
245
+
246
+ _flush (callback) {
247
+
248
+ this.publishTo (this.body.length - 1)
249
+
250
+ callback ()
251
+
252
+ }
253
+
254
+ getPosition () {
255
+
256
+ let {beforeBody, start} = this
257
+
258
+ return start === 0 ? beforeBody : beforeBody + BigInt (start)
259
+
260
+ }
261
+
262
+ checkMaxLength () {
263
+
264
+ const {body, maxLength} = this, size = body.length - this.start;
265
+
266
+ if (size <= maxLength) return
267
+
268
+ const s = body.slice (0, size - 1), dump = JSON.stringify ([s])
269
+
270
+ this.destroy (new Error (`The fragment ${dump} at position ${this.getPosition ()} exceeds maxLength=${maxLength}`))
271
+
272
+ }
273
+
274
+ _transform (chunk, encoding, callback) {
275
+
276
+ if (Buffer.isBuffer (chunk)) chunk = this.decoder.write (chunk)
277
+
278
+ this.body = this.body.slice (this.start) + chunk
279
+ this.start = 0
280
+
281
+ this.parse ()
282
+
283
+ if (this.start > 0) this.beforeBody += BigInt (this.start)
284
+ this.checkMaxLength ()
285
+
286
+ callback ()
287
+
288
+ }
289
+
290
+ }
291
+
292
+ module.exports = XMLLexer
package/package.json ADDED
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "xml-toolkit",
3
+ "version": "0.0.1",
4
+ "description": "Collection of classes for dealing with XML",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "node test/test.js"
8
+ },
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/do-/node-xml-toolkit.git"
12
+ },
13
+ "keywords": [
14
+ "xml sax stax"
15
+ ],
16
+ "author": "Dmitry Ovsyanko",
17
+ "license": "MIT",
18
+ "bugs": {
19
+ "url": "https://github.com/do-/node-xml-toolkit/issues"
20
+ },
21
+ "homepage": "https://github.com/do-/node-xml-toolkit#readme"
22
+ }
package/test/E05a.xml ADDED
@@ -0,0 +1,5 @@
1
+ <!-- CDATA sections may occur in Mixed content. -->
2
+ <!DOCTYPE foo [
3
+ <!ELEMENT foo (#PCDATA|foo)*>
4
+ ]>
5
+ <foo>a <![CDATA[cdata section]]> in mixed content</foo>
@@ -0,0 +1,10 @@
1
+ <?xml version='1.0' standalone='no'?>
2
+
3
+ <!DOCTYPE root SYSTEM "sa.dtd">
4
+
5
+ <root>
6
+ <child>
7
+ The whitespace before and after this element keeps
8
+ this from being standalone.
9
+ </child>
10
+ </root>
@@ -0,0 +1,30 @@
1
+ <?xml version='1.0' standalone='no'?>
2
+
3
+ <!DOCTYPE attributes SYSTEM "../valid/sa.dtd" [
4
+ <!ENTITY internal " number99">
5
+ ]>
6
+
7
+ <!-- sync with ../invalid/not-sa02.xml -->
8
+
9
+ <!--
10
+ lots of normalized/defaulted attributes
11
+ keep this from being standalone
12
+
13
+ XXX not the best basis for negative tests!!
14
+ -->
15
+
16
+ <attributes
17
+ notation = " nonce "
18
+ nmtoken = " this-gets-normalized "
19
+ nmtokens = " this
20
+ also gets normalized "
21
+ id = " &internal; "
22
+ idref = " &internal;
23
+ "
24
+ idrefs = " &internal; &internal; &internal;"
25
+ entity = " unparsed-1 "
26
+ entities = "unparsed-1
27
+ unparsed-2
28
+ "
29
+ cdata = "nothing happens to this one!"
30
+ />
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="utf-8"?><PARAMTYPES><PARAMTYPE ID="1" NAME="ИФНС ФЛ" DESC="ИФНС ФЛ" CODE="IFNSFL" ISACTIVE="true" UPDATEDATE="2018-06-15" STARTDATE="2011-11-01" ENDDATE="2079-06-06" /><PARAMTYPE ID="2" NAME="ИФНС ЮЛ" DESC="ИФНС ЮЛ" CODE="IFNSUL" ISACTIVE="true" UPDATEDATE="2018-06-15" STARTDATE="2011-11-01" ENDDATE="2079-06-06" /><PARAMTYPE ID="3" NAME="ИНН ФЛ ТЕР УЧ" DESC="Территориальный участок ИФНС ЮЛ" CODE="territorialifnsflcode" ISACTIVE="true" UPDATEDATE="2018-06-15" STARTDATE="2011-11-01" ENDDATE="2079-06-06" /><PARAMTYPE ID="4" NAME="ИФНС ЮЛ ТЕР УЧ" DESC="Территориальный участок ИФНС ФЛ" CODE="territorialifnsulcode" ISACTIVE="true" UPDATEDATE="2018-06-15" STARTDATE="2011-11-01" ENDDATE="2079-06-06" /><PARAMTYPE ID="5" NAME="Почтовый индекс" DESC="Информация о почтовом индексе" CODE="PostIndex" ISACTIVE="true" UPDATEDATE="2018-06-15" STARTDATE="2011-11-01" ENDDATE="2079-06-06" /><PARAMTYPE ID="6" NAME="ОКАТО" DESC="ОКАТО" CODE="OKATO" ISACTIVE="true" UPDATEDATE="2018-06-19" STARTDATE="2011-11-01" ENDDATE="2079-06-06" /><PARAMTYPE ID="7" NAME="OKTMO" DESC="OKTMO" CODE="OKTMO" ISACTIVE="true" UPDATEDATE="2018-06-19" STARTDATE="2011-11-01" ENDDATE="2079-06-06" /><PARAMTYPE ID="8" NAME="Кадастровый номер" DESC="Кадастровый номер" CODE="CadastrNum" ISACTIVE="true" UPDATEDATE="2018-06-19" STARTDATE="2011-11-01" ENDDATE="2079-06-06" /><PARAMTYPE ID="10" NAME="Код КЛАДР" DESC="Код адресного объекта одной строкой с признаком актуальности" CODE="CODE" ISACTIVE="true" UPDATEDATE="2018-06-21" STARTDATE="2011-11-01" ENDDATE="2079-06-06" /><PARAMTYPE ID="11" NAME="Код КЛАДР без признака актуальности" DESC="Код адресного объекта одной строкой без признака актуальности" CODE="PLAINCODE" ISACTIVE="true" UPDATEDATE="2018-06-21" STARTDATE="2011-11-01" ENDDATE="2079-06-06" /><PARAMTYPE ID="12" NAME="Код региона" DESC="Код региона" CODE="REGIONCODE" ISACTIVE="true" UPDATEDATE="2018-06-21" STARTDATE="2011-11-01" ENDDATE="2079-06-06" /><PARAMTYPE ID="13" NAME="Реестровый номер" DESC="Реестровый номер адресного объекта" CODE="ReestrNum" ISACTIVE="true" UPDATEDATE="2018-11-12" STARTDATE="2011-11-01" ENDDATE="2079-06-06" /><PARAMTYPE ID="14" NAME="Признак присвоения адреса" DESC="Признак в каком делении присвоен адрес, муниципальном/административном" CODE="DivisionType" ISACTIVE="true" UPDATEDATE="2018-12-14" STARTDATE="2011-11-01" ENDDATE="2079-06-06" /><PARAMTYPE ID="15" NAME="Порядковый номер" DESC="Порядковый номер обьекта в рамках родителя" CODE="Counter" ISACTIVE="true" UPDATEDATE="2018-12-14" STARTDATE="2011-11-01" ENDDATE="2079-06-06" /><PARAMTYPE ID="16" NAME="Официальное наименование" DESC="Официальное наименование объекта(Региона)" CODE="Official" ISACTIVE="true" UPDATEDATE="2019-12-04" STARTDATE="2019-12-04" ENDDATE="2079-06-06" /></PARAMTYPES>
package/test/test.js ADDED
@@ -0,0 +1,105 @@
1
+ const fs = require ('fs')
2
+ const assert = require ('assert')
3
+ const {SAXEventEmitter, SAXEvent, XMLLexer} = require ('../')
4
+
5
+ async function test_001_lexer_sync (fn) {
6
+
7
+ const xml = fs.readFileSync (
8
+ 'test/' + fn
9
+ // , 'utf-8'
10
+ )
11
+
12
+ console.log (xml)
13
+
14
+ const lexer = new XMLLexer ({
15
+ // maxLength: 40,
16
+ // encoding: 'ascii',
17
+ })
18
+
19
+ lexer.on ('data', data => console.log (new SAXEvent (data).attributes))
20
+
21
+ // for (let c of xml) lexer.write (c); lexer.end ()
22
+ // for (let c of xml) lexer.write (Buffer.from ([c])); lexer.end ()
23
+
24
+ lexer.end (xml)
25
+
26
+ }
27
+
28
+ async function test_002_lexer_stream (fn) {
29
+
30
+ const is = fs.createReadStream ('test/' + fn, {
31
+ // encoding: 'utf8',
32
+ })
33
+
34
+ const lexer = new XMLLexer ({
35
+ // maxLength: 40,
36
+ // encoding: 'ascii',
37
+ })
38
+
39
+ is.pipe (lexer)
40
+
41
+ for await (const i of lexer)
42
+ // if (/^<PARAMTYPE /.test (i))
43
+ {
44
+ console.log ({i})
45
+
46
+ }
47
+
48
+ }
49
+
50
+
51
+ async function test_003_emitter_sync (fn) {
52
+
53
+ const xml = fs.readFileSync (
54
+ 'test/' + fn
55
+ // , 'utf-8'
56
+ )
57
+
58
+ console.log (xml)
59
+
60
+ const lex = new XMLLexer ({
61
+ // maxLength: 40,
62
+ // encoding: 'ascii',
63
+ stripSpace: true,
64
+ })
65
+
66
+ const sax = new SAXEventEmitter ({})
67
+
68
+ lex.pipe (sax)
69
+
70
+ for (let event of [
71
+ 'StartDocument',
72
+ 'ProcessingInstruction',
73
+ 'Comment',
74
+ 'DTD',
75
+ 'StartElement',
76
+ 'Characters',
77
+ 'EndElement',
78
+ 'EndDocument',
79
+ ]) sax.on (event, data => console.log ([event, data]))
80
+
81
+ // lexer.on ('data', data => console.log ({data}))
82
+
83
+ // for (let c of xml) lexer.write (c); lexer.end ()
84
+ // for (let c of xml) lexer.write (Buffer.from ([c])); lexer.end ()
85
+
86
+ lex.end (xml)
87
+
88
+ }
89
+
90
+ async function main () {
91
+
92
+ // await test_001_lexer_sync ('E05a.xml')
93
+ // await test_001_lexer_sync ('not-sa01.xml')
94
+ // await test_001_lexer_sync ('not-sa02.xml')
95
+ await test_001_lexer_sync ('param_types.xml')
96
+ // await test_002_lexer_stream ('E05a.xml')
97
+ // await test_002_lexer_stream ('param_types.xml')
98
+ // await test_002_lexer_stream ('not-sa02.xml')
99
+ // await test_003_emitter_sync ('E05a.xml')
100
+ // await test_003_emitter_sync ('param_types.xml')
101
+ // await test_003_emitter_sync ('not-sa01.xml')
102
+
103
+ }
104
+
105
+ main ()