1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
|
-----------------------------------------------------------------------------------------
-- LUA only XmlParser from Alexander Makeev
-----------------------------------------------------------------------------------------
XmlParser = {};
function XmlParser:ToXmlString(value)
value = string.gsub (value, "&", "&"); -- '&' -> "&"
value = string.gsub (value, "<", "<"); -- '<' -> "<"
value = string.gsub (value, ">", ">"); -- '>' -> ">"
--value = string.gsub (value, "'", "'"); -- '\'' -> "'"
value = string.gsub (value, "\"", """); -- '"' -> """
-- replace non printable char -> "
"
value = string.gsub(value, "([^%w%&%;%p%\t% ])",
function (c)
return string.format("&#x%X;", string.byte(c))
--return string.format("&#x%02X;", string.byte(c))
--return string.format("&#%02d;", string.byte(c))
end);
return value;
end
function XmlParser:FromXmlString(value)
value = string.gsub(value, "&#x([%x]+)%;",
function(h)
return string.char(tonumber(h,16))
end);
value = string.gsub(value, "&#([0-9]+)%;",
function(h)
return string.char(tonumber(h,10))
end);
value = string.gsub (value, """, "\"");
value = string.gsub (value, "'", "'");
value = string.gsub (value, ">", ">");
value = string.gsub (value, "<", "<");
value = string.gsub (value, "&", "&");
return value;
end
function XmlParser:ParseArgs(s)
local arg = {}
string.gsub(s, "(%w+)=([\"'])(.-)%2", function (w, _, a)
arg[w] = self:FromXmlString(a);
end)
return arg
end
function XmlParser:ParseXmlText(xmlText)
local stack = {}
local top = { Name = nil, Value = nil, Attributes = {}, ChildNodes = {} }
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
top.Value = (top.Value or "")..self:FromXmlString(text);
end
if empty == "/" then -- empty element tag
table.insert(top.ChildNodes, { Name = label, Value = nil, Attributes = self:ParseArgs(xarg), ChildNodes = {}})
elseif c == "" then -- start tag
top = {Name=label, Value=nil, Attributes=self:ParseArgs(xarg), ChildNodes={}}
table.insert(stack, top) -- new level
else -- end tag
local toclose = table.remove(stack) -- remove top
top = stack[#stack]
if #stack < 1 then
error("XmlParser: nothing to close with "..label)
elseif toclose.Name ~= label then
error("XmlParser: trying to close "..toclose.Name.." with "..label)
else
table.insert(top.ChildNodes, toclose)
end
end
i = j+1
end
local text = string.sub(xmlText, i);
if not string.find(text, "^%s*$") then
stack[#stack].Value=(stack[#stack].Value or "")..self:FromXmlString(text);
end
if #stack > 1 then
error("XmlParser: unclosed "..stack[stack.n].Name)
end
return stack[1].ChildNodes[1];
end
function XmlParser:ParseXmlFile(xmlFileName)
local hFile,err = io.open(xmlFileName,"r");
if (not err) then
local xmlText=hFile:read("*a"); -- read file content
io.close(hFile);
return self:ParseXmlText(xmlText),nil;
else
return nil,err;
end
end
|