77 lines
2.5 KiB
Lua
77 lines
2.5 KiB
Lua
local XMLNode = {
|
|
new = function(tag)
|
|
return {
|
|
tag = tag,
|
|
value = nil,
|
|
attributes = {},
|
|
children = {},
|
|
|
|
addChild = function(self, child)
|
|
table.insert(self.children, child)
|
|
end,
|
|
|
|
addAttribute = function(self, tag, value)
|
|
self.attributes[tag] = value
|
|
end
|
|
}
|
|
end
|
|
}
|
|
|
|
local parseAttributes = function(node, s)
|
|
-- Parse "" style string attributes
|
|
local _, _ = string.gsub(s, "(%w+)=([\"'])(.-)%2", function(attribute, _, value)
|
|
node:addAttribute(attribute, "\"" .. value .. "\"")
|
|
end)
|
|
-- Parse {} style computed attributes
|
|
local _, _ = string.gsub(s, "(%w+)={(.-)}", function(attribute, expression)
|
|
node:addAttribute(attribute, expression)
|
|
end)
|
|
end
|
|
|
|
local XMLParser = {
|
|
parseText = function(xmlText)
|
|
local stack = {}
|
|
local top = XMLNode.new()
|
|
table.insert(stack, top)
|
|
local ni, c, label, xarg, empty
|
|
local i, j = 1, 1
|
|
while true do
|
|
ni, j, c, label, xarg, empty = string.find(xmlText, "<(%/?)([%w_:]+)(.-)(%/?)>", i)
|
|
if not ni then break end
|
|
local text = string.sub(xmlText, i, ni - 1);
|
|
if not string.find(text, "^%s*$") then
|
|
local lVal = (top.value or "") .. text
|
|
stack[#stack].value = lVal
|
|
end
|
|
if empty == "/" then -- empty element tag
|
|
local lNode = XMLNode.new(label)
|
|
parseAttributes(lNode, xarg)
|
|
top:addChild(lNode)
|
|
elseif c == "" then -- start tag
|
|
local lNode = XMLNode.new(label)
|
|
parseAttributes(lNode, xarg)
|
|
table.insert(stack, lNode)
|
|
top = lNode
|
|
else -- end tag
|
|
local toclose = table.remove(stack) -- remove top
|
|
|
|
top = stack[#stack]
|
|
if #stack < 1 then
|
|
error("XMLParser: nothing to close with " .. label)
|
|
end
|
|
if toclose.tag ~= label then
|
|
error("XMLParser: trying to close " .. toclose.tag .. " with " .. label)
|
|
end
|
|
top:addChild(toclose)
|
|
end
|
|
i = j + 1
|
|
end
|
|
local text = string.sub(xmlText, i);
|
|
if #stack > 1 then
|
|
error("XMLParser: unclosed " .. stack[#stack].tag)
|
|
end
|
|
return top.children
|
|
end
|
|
}
|
|
|
|
return XMLParser |