-- XL: a poor man's XML parser in pure Lua
-- parser stolen from http://lua-users.org/wiki/LuaXml
--
-- example usage:
--
-- require 'xl'
--
-- parser = XL:new()
-- parser:from_file(arg[1])
--
-- find the first 'A' element
-- a = parser:find(parser:root(), 'A')
--
-- Copyright 2009: hans@hpelbers.org
-- This is freeware
XL = {}
function XL:new()
local x = {}
setmetatable(x, self)
self.__index = self
return x
end
function XL._get_attrs(s)
local arg = {}
string.gsub(s, "(%w+)=([\"'])(.-)%2", function (w, _, a)
arg[w] = a
end)
return arg
end
function XL:root()
for _, v in ipairs(self.xml) do
if v.tag then return v end
end
return nil
end
function XL:find(x, t)
r = {}
for _, v in ipairs(x) do
if v.tag and v.tag == t then r[#r+1] = v end
end
return r
end
function XL:from_file(s)
local f=io.open(s)
self:from_string(f:read('*all'))
f:close()
end
function XL:from_string(s)
self.xml = nil -- reset
local stack = {}
local top = {}
table.insert(stack, top)
local ni,c,tag,attr, empty
local i, j = 1, 1
while true do
ni,j,c,tag,attr, empty = string.find(s, "<(%/?)([%w:]+)(.-)(%/?)>", i)
if not ni then break end
local text = string.sub(s, i, ni-1)
if not string.find(text, "^%s*{1}quot;) then
table.insert(top, text)
end
if empty == "/" then -- empty element tag
table.insert(top, {tag=tag, attr=self._get_attrs(attr)})
elseif c == "" then -- start tag
top = {tag=tag, attr=self._get_attrs(attr)}
table.insert(stack, top) -- new level
else -- end tag
local toclose = table.remove(stack) -- remove top
top = stack[#stack]
if #stack < 1 then
error("nothing to close with "..tag)
end
if toclose.tag ~= tag then
error("trying to close "..toclose.tag.." with "..tag)
end
table.insert(top, toclose)
end
i = j+1
end
local text = string.sub(s, i)
if not string.find(text, "^%s*{1}quot;) then
table.insert(stack[#stack], text)
end
if #stack > 1 then
error("unclosed "..stack[stack.n].tag)
end
self.xml = stack[1]
end
XML解析
最新推荐文章于 2024-07-22 23:00:53 发布