local function xml_escape(str) return string.gsub(str, "&", "&") end local function process_comment(table, a) return "" end local function process_tag(table, key, a) local middle, options, options_str, k, v, b middle = "" options = {} if type(a) == "table" then for k, v in ipairs(a) do middle = middle .. v end for k, v in pairs(a) do if (type(k) == "string") then options[k] = string.gsub(v, '"', '\\"') end end elseif type(a) == "string" then middle = xml_escape(a) end if middle ~= "" then options_str = "" for k, v in pairs(options) do if (v == "") then options_str = " " .. options_str .. k else options_str = " " .. options_str .. k .. '="' .. v .. '"' end end return "<" .. key .. options_str .. ">" .. middle .. "" else return "<" .. key .. " />" end end local xmlmarkup_metatable = { __index = function(table, key) local k = key return function(t, a) return process_tag(t, k, a) end end } function NewXmlMarkup() local r = { comment = process_comment, } setmetatable(r, xmlmarkup_metatable) return r end --[[ xm = NewXmlMarkup() s = xm:html { xm:head { xm:title "Test" }, xm:body { bgcolor = "#ffeedd", "Normal test", xm:br(), xm:b "Bold test.", xm:comment "Hi there...", } } print(s) ]]--