testxml.lua
local lexer = require 'pl.lexer'
local pretty = require 'pl.pretty'
local append = table.insert
local skipws,expecting = lexer.skipws,lexer.expecting
local function parse_element (tok,tag)
local tbl,t,v,attrib
tbl = {}
tbl.tag = tag t,v = skipws(tok)
while v ~= '/' and v ~= '>' do
if t ~= 'iden' then error('expecting attribute identifier') end
attrib = v
expecting(tok,'=')
v = expecting(tok,'string')
if not tbl.attr then tbl.attr = {} end
tbl.attr[attrib] = v
append(tbl.attr,attrib)
t,v = skipws(tok)
end
if v == '/' then
expecting(tok,'>')
return tbl
end
t,v = tok()
while true do
if t == '<' then
t,v = skipws(tok)
if t == '/' then t,v = tok()
if t == '>' then return tbl end
if t == 'iden' and v == tag then
if tok() == '>' then return tbl end
end
error('expecting end tag '..tag)
else
append(tbl,parse_element(tok,v)) t,v = skipws(tok)
end
else
append(tbl,v) t,v = skipws(tok)
end
end
end
local function parse_xml (tok)
local t = skipws(tok)
local v
while t == '<' do
t,v = tok()
if t == '?' or t == '!' then
repeat t = tok() until t == '>'
t = expecting(tok,'<')
else
return parse_element(tok,v)
end
end
end
local s = [[
<?xml version="1.0" encoding="UTF-8"?>
<sensor name="closure-meter-2" id="7D7D0600006F0D00" loc="100,100,0" device="closure-meter" init="true">
<detector name="closure-meter" phenomenon="closure" units="mm" id="1"
vmin="0" vmax="5000" device="closure-meter" calib="0,0;5000,5000"
sampling_interval="25000" measurement_interval="600000"
/>
</sensor>
]]
local tok = lexer.scan(s,nil,{space=false},{string=true})
local res = parse_xml(tok)
print(pretty.write(res))