scansion/ordered_serializer.lua

Thu, 23 Mar 2023 15:30:32 +0000

author
Matthew Wild <mwild1@gmail.com>
date
Thu, 23 Mar 2023 15:30:32 +0000
changeset 178
e547ddf8b64d
parent 174
662bd8c5ae28
permissions
-rw-r--r--

Remove dependency on util.iterators

I mistakenly thought it was bundled with verse.

local s_find, s_gsub, s_match = string.find, string.gsub, string.match;
local t_concat, t_insert = table.concat, table.insert;

local pairs = require "scansion.helpers".sorted_pairs;

local escape_table = { ["'"] = "&apos;", ["\""] = "&quot;", ["<"] = "&lt;", [">"] = "&gt;", ["&"] = "&amp;" };
local function xml_escape(str) return (s_gsub(str, "['&<>\"]", escape_table)); end

local function _dostring(t, buf, self, _xml_escape, parentns)
	local nsid = 0;
	local name = t.name
	t_insert(buf, "<"..name);
	for k, v in pairs(t.attr) do
		if s_find(k, "\1", 1, true) then
			local ns, attrk = s_match(k, "^([^\1]*)\1?(.*)$");
			nsid = nsid + 1;
			t_insert(buf, " xmlns:ns"..nsid.."='".._xml_escape(ns).."' ".."ns"..nsid..":"..attrk.."='".._xml_escape(v).."'");
		elseif not(k == "xmlns" and v == parentns) then
			t_insert(buf, " "..k.."='".._xml_escape(v).."'");
		end
	end
	local len = #t;
	if len == 0 then
		t_insert(buf, "/>");
	else
		t_insert(buf, ">");
		for n=1,len do
			local child = t[n];
			if child.name then
				self(child, buf, self, _xml_escape, t.attr.xmlns);
			else
				t_insert(buf, _xml_escape(child));
			end
		end
		t_insert(buf, "</"..name..">");
	end
end

return {
	enable = function ()
		local stanza_mt = require "util.stanza".stanza_mt;
		stanza_mt._unsorted_tostring = stanza_mt.__tostring;
		function stanza_mt.__tostring(t)
			local buf = {};
			_dostring(t, buf, _dostring, xml_escape, nil);
			return t_concat(buf);
		end;
	end;
	disable = function ()
		local stanza_mt = require "util.stanza".stanza_mt;
		if stanza_mt._unsorted_tostring then
			stanza_mt.__tostring = stanza_mt._unsorted_tostring;
		end
	end;
};

mercurial