Comparison

plugins/storage/xmlparse.lib.lua @ 2678:c5882e2e12b5

mod_storage, plus a bit of SQL and XML.
author Waqas Hussain <waqas20@gmail.com>
date Fri, 19 Feb 2010 22:32:28 +0500
comparison
equal deleted inserted replaced
2677:467568f1117d 2678:c5882e2e12b5
1
2 local st = require "util.stanza";
3
4 -- XML parser
5 local parse_xml = (function()
6 local entity_map = setmetatable({
7 ["amp"] = "&";
8 ["gt"] = ">";
9 ["lt"] = "<";
10 ["apos"] = "'";
11 ["quot"] = "\"";
12 }, {__index = function(_, s)
13 if s:sub(1,1) == "#" then
14 if s:sub(2,2) == "x" then
15 return string.char(tonumber(s:sub(3), 16));
16 else
17 return string.char(tonumber(s:sub(2)));
18 end
19 end
20 end
21 });
22 local function xml_unescape(str)
23 return (str:gsub("&(.-);", entity_map));
24 end
25 local function parse_tag(s)
26 local name,sattr=(s):gmatch("([^%s]+)(.*)")();
27 local attr = {};
28 for a,b in (sattr):gmatch("([^=%s]+)=['\"]([^'\"]*)['\"]") do attr[a] = xml_unescape(b); end
29 return name, attr;
30 end
31 return function(xml)
32 local stanza = st.stanza("root");
33 local regexp = "<([^>]*)>([^<]*)";
34 for elem, text in xml:gmatch(regexp) do
35 if elem:sub(1,1) == "!" or elem:sub(1,1) == "?" then -- neglect comments and processing-instructions
36 elseif elem:sub(1,1) == "/" then -- end tag
37 elem = elem:sub(2);
38 stanza:up(); -- TODO check for start-end tag name match
39 elseif elem:sub(-1,-1) == "/" then -- empty tag
40 elem = elem:sub(1,-2);
41 local name,attr = parse_tag(elem);
42 stanza:tag(name, attr):up();
43 else -- start tag
44 local name,attr = parse_tag(elem);
45 stanza:tag(name, attr);
46 end
47 if #text ~= 0 then -- text
48 stanza:text(xml_unescape(text));
49 end
50 end
51 return stanza.tags[1];
52 end
53 end)();
54 -- end of XML parser
55
56 return parse_xml;