diff options
-rw-r--r-- | lib/xmllib.lua | 135 |
1 files changed, 112 insertions, 23 deletions
diff --git a/lib/xmllib.lua b/lib/xmllib.lua index 1ef0f33..f2b452c 100644 --- a/lib/xmllib.lua +++ b/lib/xmllib.lua @@ -1,4 +1,4 @@ -local xml_remplacements = { +local xml_replacements = { { "&", "&" }, { "<", "<" }, { ">", ">" }, @@ -8,58 +8,144 @@ local attribute_replacements = { { '"', '\\"' }, } -local function generic_escape(str, remplacements) +local function generic_escape(str, replacements) local _, r - for _, r in pairs(xml_replacements) do + for _, r in pairs(replacements) do str = string.gsub(str, r[1], r[2]) end + + return str end local function xml_escape(str) return generic_escape(str, xml_replacements) end -local function attribute_replacements(str) +local function attribute_escape(str) return generic_escape(str, attribute_replacements) end local function process_comment(xm, a) - return "<!-- " .. a .. " -->" + return { + istop = true, + nodes = { + a + }, + type = "comment", + } end -local function process_tag(xm, key, a) - local middle, attrs, attrs_str, k, v, b +local function process_lf(xm) + return { + istop = true, + type = "lf", + } +end + +local function burrow(t) + local k, v - middle = "" - attrs = {} + if type(t) ~= "table" then return end + if type(t.istop) ~= "boolean" then return end + + t.istop = nil +end + +local function clean_tops(t) + local k, v + + for k, v in pairs(t) do + if not v.istop then + t[k] = nil + end + end +end + +local function process_tag(xm, key, a) + local ret, attrs, nodes, has_nodes, has_attrs, k, v, b = { istop = true, key = key }, {}, {}, false, false if type(a) == "table" then for k, v in ipairs(a) do - middle = middle .. v + if type(v) == "table" then + burrow(v) + has_nodes = true + table.insert(nodes, v) + elseif type(v) == "string" then + has_nodes = true + table.insert(nodes, xml_escape(v)) + else + error "Unsupported argument type." + end end for k, v in pairs(a) do if (type(k) == "string") then - attrs[k] = attribute_replacements(xml_replacements(v)) + has_attrs = true + attrs[k] = attribute_escape(xml_escape(v)) end end elseif type(a) == "string" then - middle = xml_escape(a) + has_nodes = true + table.insert(nodes, xml_escape(a)) end + + if (has_nodes) then ret.nodes = nodes end + if (has_attrs) then ret.attrs = attrs end + + table.insert(xm.tops, ret) - if middle ~= "" then - attrs_str = "" - for k, v in pairs(attrs) do - if (v == "") then - attrs_str = " " .. attrs_str .. k - else - attrs_str = " " .. attrs_str .. k .. '="' .. v .. '"' + clean_tops(xm.tops) + + return ret +end + +local function render_attrs(t) + local r, k, v + + if type(t) ~= "table" then return "" end + + for k, v in pairs(t) do + r = r .. " " .. k .. '="' .. v .. '"' + end + + return r +end + +local function do_render_r(v) + local middle, i, n = "" + + if v.type == "comment" then + return "<!-- " .. v.nodes[1] .. " -->" + elseif v.type == "lf" then + return "\n" + elseif type(v.key) == "string" then + if type(v.nodes) == "table" then + for i, n in ipairs(v.nodes) do + if type(n) == "string" then + middle = middle .. n + elseif type(n) == "table" then + middle = middle .. do_render_r(n) + end end + return "<" .. v.key .. render_attrs(v.attrs) .. ">" .. middle .. "</" .. v.key .. ">" + else + return "<" .. v.key .. render_attrs(v.attrs) .. " />" end - return "<" .. key .. attrs_str .. ">" .. middle .. "</" .. key .. ">" else - return "<" .. key .. " />" + error "Inconsistancy in the XML structure." end + + return "" +end + +local function do_render(xm) + local r, i, n = "" + + for i, n in pairs(xm.tops) do + r = r .. do_render_r(n) + end + + return xm.doctype .. "\n" .. r end local xmlmarkup_metatable = { @@ -72,6 +158,10 @@ local xmlmarkup_metatable = { function NewXmlMarkup() local r = { comment = process_comment, + lf = process_lf, + tops = {}, + render = do_render, + doctype = '<?xml version="1.0" encoding="UTF-8"?>', } setmetatable(r, xmlmarkup_metatable) @@ -88,7 +178,6 @@ end xm = NewXmlMarkup() -s = xm:html { xm:head { xm:title "Test" @@ -103,6 +192,6 @@ xm:html { } } -print(s) +print(xm:render()) ]]-- |