xml-toolkit 0.0.4 → 0.0.5
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/lib/MoxyLikeJsonEncoder.js +2 -2
- package/lib/XMLReader.js +70 -17
- package/package.json +1 -1
- package/test/test.js +22 -53
|
@@ -12,9 +12,9 @@ const set = (o, k, nv) => {
|
|
|
12
12
|
|
|
13
13
|
const xform = ({children, attributes}) => {
|
|
14
14
|
|
|
15
|
-
let o = Object.fromEntries (attributes.entries ())
|
|
15
|
+
let o = attributes == null ? {} : Object.fromEntries (attributes.entries ())
|
|
16
16
|
|
|
17
|
-
if (children
|
|
17
|
+
if (children != null) for (const child of children) switch (child.type) {
|
|
18
18
|
|
|
19
19
|
case SAXEvent.TYPES.CHARACTERS: return child.text
|
|
20
20
|
|
package/lib/XMLReader.js
CHANGED
|
@@ -2,8 +2,8 @@ const assert = require ('assert')
|
|
|
2
2
|
const {Transform} = require ('stream')
|
|
3
3
|
const SAXEvent = require ('./SAXEvent.js')
|
|
4
4
|
const XMLNode = require ('./XMLNode.js')
|
|
5
|
+
const XMLLexer = require ('./XMLLexer.js')
|
|
5
6
|
|
|
6
|
-
const OPT_ONCE = Symbol ('_once')
|
|
7
7
|
const OPT_SRC = Symbol ('_src')
|
|
8
8
|
const OPT_SAX = Symbol ('_sax')
|
|
9
9
|
|
|
@@ -23,8 +23,30 @@ const XMLReader = class extends Transform {
|
|
|
23
23
|
if (!('useNamespaces' in options)) options.useNamespaces = true
|
|
24
24
|
assert (options.useNamespaces === true || options.useNamespaces === false, 'options.useNamespaces must be boolean, not ' + typeof options.useNamespaces)
|
|
25
25
|
|
|
26
|
-
|
|
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')
|
|
42
|
+
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
let {collect} = options; delete options.collect
|
|
27
48
|
assert (collect == null || typeof collect === 'function', 'options.collect must be a function, not ' + typeof collect)
|
|
49
|
+
if (collect == null && filterElements != null) collect = filterElements
|
|
28
50
|
|
|
29
51
|
const {filter} = options; delete options.filter
|
|
30
52
|
assert (filter == null || typeof filter === 'function', 'options.filter must be a function, not ' + typeof filter)
|
|
@@ -32,19 +54,14 @@ const XMLReader = class extends Transform {
|
|
|
32
54
|
const {map} = options; delete options.map
|
|
33
55
|
assert (map == null || typeof map === 'function', 'options.map must be a function, not ' + typeof map)
|
|
34
56
|
|
|
35
|
-
const {find} = options; delete options.find
|
|
36
|
-
assert (filter == null || find == null, 'filter & find options cannot be set together')
|
|
37
|
-
assert (find == null || typeof find === 'function', 'options.find must be a function, not ' + typeof find)
|
|
38
|
-
|
|
39
57
|
super (options)
|
|
40
58
|
|
|
41
59
|
this.stripSpace = options.stripSpace
|
|
42
60
|
this.useEntities = options.useEntities
|
|
43
61
|
this.useNamespaces = options.useNamespaces
|
|
44
62
|
this.collect = collect || null
|
|
45
|
-
this.filter = filter ||
|
|
63
|
+
this.filter = filter || null
|
|
46
64
|
this.map = map || null
|
|
47
|
-
this [OPT_ONCE] = find != null
|
|
48
65
|
|
|
49
66
|
if (this.useEntities) this.entityResolver = new (require ('./EntityResolver.js')) ()
|
|
50
67
|
|
|
@@ -57,6 +74,50 @@ const XMLReader = class extends Transform {
|
|
|
57
74
|
this [OPT_SAX] = null
|
|
58
75
|
|
|
59
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
|
|
119
|
+
|
|
120
|
+
}
|
|
60
121
|
|
|
61
122
|
_flush (callback) {
|
|
62
123
|
|
|
@@ -72,7 +133,7 @@ const XMLReader = class extends Transform {
|
|
|
72
133
|
|
|
73
134
|
const v = this [OPT_SAX]; if (v !== null) return v
|
|
74
135
|
|
|
75
|
-
for (const type
|
|
136
|
+
for (const type of Object.values (SAXEvent.TYPES)) if (this.listenerCount (type) !== 0) return this [OPT_SAX] = true
|
|
76
137
|
|
|
77
138
|
return this [OPT_SAX] = false
|
|
78
139
|
|
|
@@ -97,14 +158,6 @@ const XMLReader = class extends Transform {
|
|
|
97
158
|
|
|
98
159
|
}
|
|
99
160
|
|
|
100
|
-
if (this [OPT_ONCE]) {
|
|
101
|
-
|
|
102
|
-
const src = this [OPT_SRC]; if (src !== null) src.unpipe (this)
|
|
103
|
-
|
|
104
|
-
this.destroy ()
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
|
|
108
161
|
}
|
|
109
162
|
|
|
110
163
|
flush_text () {
|
package/package.json
CHANGED
package/test/test.js
CHANGED
|
@@ -57,74 +57,43 @@ async function test_003_emitter_sync (fn) {
|
|
|
57
57
|
|
|
58
58
|
console.log (xml)
|
|
59
59
|
|
|
60
|
-
const lex = new XMLLexer ({
|
|
61
|
-
// maxLength: 40,
|
|
62
|
-
// encoding: 'ascii',
|
|
63
|
-
// stripSpace: true,
|
|
64
|
-
})
|
|
65
|
-
|
|
66
60
|
const sax = new XMLReader ({
|
|
67
61
|
stripSpace: true,
|
|
68
|
-
|
|
69
|
-
find: e => true
|
|
70
|
-
// && e.type === SAXEvent.TYPES.CHARACTERS
|
|
71
|
-
&& e.localName === 'SendRequestRequest'
|
|
72
|
-
&& e.type === SAXEvent.TYPES.END_ELEMENT
|
|
73
|
-
// && e.level === 6
|
|
74
|
-
,
|
|
62
|
+
filterElements: 'SendRequestRequest',
|
|
75
63
|
map: MoxyLikeJsonEncoder ({wrap: 1})
|
|
76
|
-
// useEntities: false,
|
|
77
64
|
})
|
|
78
65
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
66
|
+
/*
|
|
82
67
|
for (let event of [
|
|
83
|
-
'
|
|
84
|
-
'
|
|
85
|
-
'
|
|
86
|
-
'
|
|
87
|
-
'
|
|
88
|
-
'Characters',
|
|
89
|
-
'EndElement',
|
|
90
|
-
'EndDocument',
|
|
68
|
+
'data',
|
|
69
|
+
'close',
|
|
70
|
+
'end',
|
|
71
|
+
'finish',
|
|
72
|
+
// 'EndElement',
|
|
91
73
|
]) sax.on (event, data => {
|
|
92
|
-
|
|
93
|
-
// console.log ([event, data])
|
|
94
|
-
|
|
95
|
-
console.log (JSON.stringify (data, null, 2))
|
|
96
|
-
|
|
97
|
-
/*
|
|
98
|
-
console.log ([event, data, data.name, data.localName, data.namespaceURI])
|
|
99
|
-
|
|
100
|
-
const {attributes} = data; for (const [k, v] of attributes.entries ()) {
|
|
101
|
-
|
|
102
|
-
console.log ([k, attributes.getLocalName (k), attributes.getNamespaceURI (k), v])
|
|
103
|
-
|
|
104
|
-
console.log ([attributes.get ('ns0:foo')])
|
|
105
74
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
console.log ([attributes.get ('foo', 'urn:dom.gosuslugi.ru/common/1.2.0')])
|
|
109
|
-
|
|
110
|
-
}
|
|
111
|
-
*/
|
|
75
|
+
console.log ([JSON.stringify (data, null, 2), event])
|
|
76
|
+
|
|
112
77
|
})
|
|
113
|
-
|
|
78
|
+
*/
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
// sax.process (fs.createReadStream ('test/' + fn))
|
|
114
82
|
|
|
83
|
+
sax.process (xml)
|
|
115
84
|
|
|
85
|
+
//console.log (sax)
|
|
86
|
+
//console.log (sax.isSAX)
|
|
116
87
|
|
|
117
88
|
/*
|
|
118
|
-
|
|
119
|
-
console.log (
|
|
120
|
-
}
|
|
89
|
+
for await (const e of sax) {
|
|
90
|
+
console.log (e)
|
|
91
|
+
}
|
|
121
92
|
*/
|
|
122
|
-
// lexer.on ('data', data => console.log ({data}))
|
|
123
|
-
|
|
124
|
-
// for (let c of xml) lexer.write (c); lexer.end ()
|
|
125
|
-
// for (let c of xml) lexer.write (Buffer.from ([c])); lexer.end ()
|
|
126
93
|
|
|
127
|
-
|
|
94
|
+
const v = await sax.findFirst ()
|
|
95
|
+
|
|
96
|
+
console.log (JSON.stringify (v, null, 2))
|
|
128
97
|
|
|
129
98
|
}
|
|
130
99
|
|