-
Notifications
You must be signed in to change notification settings - Fork 2
/
xmltojson.js
93 lines (81 loc) · 2.6 KB
/
xmltojson.js
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
var xml = require('node-xml')
, writeFile = require('fs').writeFileSync
, write = function(file, obj) { writeFile(file, JSON.stringify(obj, null, 2)) }
, ret = {}
, parser = new xml.SaxParser(parse)
, state = []
, acceptText = ['fieldref', 'bit', 'value', 'type']
, namedFields = ['request', 'reply', 'struct', 'event', 'enum', 'error', 'errorcopy', 'eventcopy', 'xidunion', 'union', 'xidtype', 'typedef']
, acceptFields = ['request', 'reply', 'struct', 'event', 'enum', 'error', 'errorcopy', 'eventcopy', 'union']
function parse(cb) {
var cur = ret
, curList = []
cb.onStartElementNS(function(elem, attrs){
var parent = state[state.length - 1]
attrs = attrsToHash(attrs)
state.push(elem)
cur = namedFields.indexOf(elem) != -1 ? doPrimaryField(elem, attrs, cur, ret)
: acceptFields.indexOf(parent) != -1 ? doFieldType(elem, attrs, cur, ret)
: doSubField(elem, attrs, cur, ret)
curList.push(cur)
})
cb.onEndElementNS(function(elem) {
curList.pop()
cur = curList[curList.length - 1]
state.pop()
})
cb.onCharacters(function(chars){
if (chars = chars.trim()) text.give(chars, cur)
})
cb.onEndDocument(function() {
ret = ret.xcb
write('xProtocol.json', ret)
})
}
function attrsToHash(attrs) {
var ret = {}
attrs.forEach(function(val) {
ret[val[0]] = val[1]
})
return ret
}
var text = (function(){
var obj, k
return { receive: function recieveText(cur, key) {
obj = cur
k = key
return cur
}
, give: function giveText(str, cur) {
if (!obj || cur != obj) return //should still be on the field that is accepting text
if (obj[k]) {
if (Array.isArray(obj[k])) return obj[k].push(str)
if (typeof obj[k] == 'string') return obj[k] = [obj[k], str]
else return console.log('oh no this isn\'t correct this field already has an object set.', obj, k)
}
obj[k] = str
}}
})()
function doFieldType(elem, attrs, cur, ret) {
var field = !cur.field ? cur.field = [] : cur.field
attrs.fieldType = elem
field.push(attrs)
return attrs
}
function doSubField(elem, attrs, cur, ret) {
if (acceptText.indexOf(elem) != -1) return text.receive(cur, elem)
if (cur[elem]) console.log('overwriting?', elem, 'currently:', cur[elem], state)
cur[elem] = attrs
if (elem == 'op') {
attrs.operation = attrs.op
delete attrs.op
}
return cur[elem]
}
function doPrimaryField(elem, attrs, cur, ret) {
var obj = !cur[elem] ? cur[elem] = {} : cur[elem]
, name = elem == 'typedef' ? attrs.newname : attrs.name
delete attrs.name
return name ? (obj[name] = attrs) : obj
}
parser.parseFile('xproto.xml')