do not use ids anymore
[lqt.git] / new / xml.lua
blob30ba439d589595e8d9d5f84b50119252ee5024aa
1 #!/usr/bin/lua
3 local parseargs, collect, strip_escapes
5 strip_escapes = function (s)
6 s = string.gsub(s, '>', '>')
7 s = string.gsub(s, '&lt;', '<')
8 return s
9 end
12 function parseargs(s)
13 local arg = {}
14 string.gsub(s, "([%w_]+)=([\"'])(.-)%2", function (w, _, a)
15 arg[strip_escapes(w)] = strip_escapes(a)
16 end)
17 return arg
18 end
20 function collect(s)
21 local stack = {}
22 local index = {}
23 local top = {}
24 table.insert(stack, top)
25 local ni,c,label,xarg, empty
26 local i, j = 1, 1
27 while true do
28 ni,j,c,label,xarg, empty = string.find(s, "<(%/?)(%w+)(.-)(%/?)>", j)
29 if not ni then break end
30 local text = string.sub(s, i, ni-1)
31 if not string.find(text, "^%s*$") then
32 table.insert(top, text)
33 end
34 if empty == "/" then -- empty element tag
35 table.insert(top, {label=label, xarg=parseargs(xarg), empty=1})
36 elseif c == "" then -- start tag
37 top = {label=label, xarg=parseargs(xarg)}
38 table.insert(stack, top) -- new level
39 else -- end tag
40 local toclose = table.remove(stack) -- remove top
41 top = stack[#stack]
42 if #stack < 1 then
43 error("nothing to close with "..label)
44 end
45 if toclose.label ~= label then
46 error("trying to close "..toclose.label.." with "..label)
47 end
48 table.insert(top, toclose)
49 toclose.parent = top
50 toclose.index = #top
51 index[toclose] = true
52 end
53 i = j+1
54 end
55 local text = string.sub(s, i)
56 if not string.find(text, "^%s*$") then
57 table.insert(stack[#stack], text)
58 end
59 if #stack > 1 then
60 error("unclosed "..stack[stack.n].label)
61 end
62 return stack[1], idindex
63 end
65 return collect