forked from danielwhelansb/xml-object-stream
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.coffee
70 lines (47 loc) · 1.77 KB
/
index.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
expat = require 'node-expat'
events = require 'events'
exports.parse = (readStream, options = {}) ->
options.stripNamespaces ?= true
parser = new expat.Parser("UTF-8")
emitter = new events.EventEmitter()
readStream.on 'data', (data) -> parser.parse data.toString()
readStream.on 'end', -> process.nextTick -> emitter.emit 'end'
readStream.on 'error', (err) -> emitter.emit 'error', err
readStream.on 'close', -> emitter.emit 'close'
# parse EVERYTHING inside of them.
each = (nodeName, eachNode) ->
eachNodeDelayed = (node) ->
process.nextTick ->
eachNode node
currentNode = null
parser.on 'error', (err) ->
emitter.emit 'error', err
parser.on 'startElement', (name, attrs) ->
if options.stripNamespaces then name = stripNamespace name
if name is nodeName or currentNode
currentNode = {$name: name, $:attrs, $parent: currentNode}
parser.on 'text', (text) ->
return if not currentNode?
currentNode.$text ?= ""
currentNode.$text += text
# ok, we only want to collect things if we are under a current node
parser.on 'endElement', (name) ->
return if not currentNode?
if currentNode.$name is nodeName
if currentNode.$parent
throw new Error "Top-level node should not have a parent. Possible memory leak"
eachNodeDelayed currentNode
parent = currentNode.$parent
if parent?
delete currentNode.$parent
parent.$children ?= []
parent.$children.push currentNode
parent[currentNode.$name] = currentNode
currentNode = parent
return {
each: each
on: (e, cb) -> emitter.on e, cb
pause: -> readStream.pause()
resume: -> readStream.resume()
}
stripNamespace = (name) -> name.replace /^.*:/, ""