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