--[[
///////////////////////////////////////////////////////////////////////////////////////////
'XMLDocument'
Uses LuaXML-0.0.0, From Paul Chakravarti. Available at http://lua-users.org/wiki/LuaXml .
I've made some modifications to LuaXML so that it's more flexible. Primarily, I added the
ability to parse self-closing tags such as
.
Copyright(c) 2005, FreePlay. To use this, please contact me at FreePlayPSP@gmail.com.
///////////////////////////////////////////////////////////////////////////////////////////
]]--
function parseXML(XMLfile)
local XMLHandle = assert(io.open(XMLfile, "r"))
local XMLData = XMLHandle:read("*all")
io.close(XMLHandle)
return collect(XMLData)
end
function parseargs (s)
local arg = {}
gsub(s, "([%w:]+)=([\"'])(.-)%2", function (w, _, a)
arg[w] = a
end)
return arg
end
function collect (s)
string.gsub(s, "
","\n")
--local logfile = assert(io.open("parse.log", "w"))
local stack = {n=0}
local top = {n=0}
tinsert(stack, top)
local ni,c,label,args, empty
local i, j = 1, 1
while 1 do
ni,j,c,label,args, empty = strfind(s, "<(%/?)([%w:]+)(.-)(%/?)>", j)
if label ~= nil then label = strlower(label) end
--logfile:write("c \""..valOrNil(c).."\" label \""..valOrNil(label).."\" empty \""..valOrNil(empty).."\"\n")
if not ni then break end
local text = strsub(s, i, ni-1)
if not strfind(text, "^%s*$") then
tinsert(top, text)
end
sct = false
if c == "" and empty == "/" and label == "" then -- empty element tag
tinsert(top, {n=0, label=label, args=parseargs(args), empty=1})
elseif c == "" then -- start tag
top = {n=0, label=label, args=parseargs(args)}
tinsert(stack, top) -- new level
if empty == "/" then
--logfile:write("...\n")
local toclose = tremove(stack) -- remove top
top = stack[stack.n]
tinsert(top, toclose)
end
else -- end tag
local toclose = tremove(stack) -- remove top
top = stack[stack.n]
if stack.n < 1 then
--io.close(logfile)
error("nothing to close with "..label)
end
if strlower(toclose.label) ~= strlower(label) then
--logfile:write("!!!\n")
--io.close(logfile)
error("trying to close "..toclose.label.." with "..label)
end
tinsert(top, toclose)
end
i = j + 1
end
local text = strsub(s, i)
--logfile:write("text "..valOrNil(text).."\n")
if not strfind(text, "^%s*$") then
tinsert(stack[stack.n], text)
end
if stack.n > 1 then
--io.close(logfile)
error("unclosed "..stack[stack.n].label)
end
--logfile:write("done\n")
--logfile:close()
return stack[1]
end