util.stanza, util.xml, util.xmppstream: Add support for tracking defined namespaces and their prefix (stanza.namespaces), knowing/preserving prefix names is required for some applications (thanks daurnimator)
authorMatthew Wild <mwild1@gmail.com>
Tue, 08 Dec 2015 23:15:42 +0000
changeset 6981 30c96a5db360
parent 6980 450db0b83fe9
child 6991 329d5fb8a9d3
util.stanza, util.xml, util.xmppstream: Add support for tracking defined namespaces and their prefix (stanza.namespaces), knowing/preserving prefix names is required for some applications (thanks daurnimator)
util/stanza.lua
util/xml.lua
util/xmppstream.lua
--- a/util/stanza.lua	Sun Dec 06 02:43:01 2015 +0100
+++ b/util/stanza.lua	Tue Dec 08 23:15:42 2015 +0000
@@ -40,8 +40,8 @@
 local stanza_mt = { __type = "stanza" };
 stanza_mt.__index = stanza_mt;
 
-local function stanza(name, attr)
-	local stanza = { name = name, attr = attr or {}, tags = {} };
+local function stanza(name, attr, namespaces)
+	local stanza = { name = name, attr = attr or {}, namespaces = namespaces, tags = {} };
 	return setmetatable(stanza, stanza_mt);
 end
 local stanza = stanza;
@@ -54,8 +54,8 @@
 	return self:tag("body", attr):text(text);
 end
 
-function stanza_mt:tag(name, attrs)
-	local s = stanza(name, attrs);
+function stanza_mt:tag(name, attr, namespaces)
+	local s = stanza(name, attr, namespaces);
 	local last_add = self.last_add;
 	if not last_add then last_add = {}; self.last_add = last_add; end
 	(last_add[#last_add] or self):add_direct_child(s);
@@ -333,7 +333,12 @@
 local function clone(stanza)
 	local attr, tags = {}, {};
 	for k,v in pairs(stanza.attr) do attr[k] = v; end
-	local new = { name = stanza.name, attr = attr, tags = tags };
+	local old_namespaces, namespaces = stanza.namespaces;
+	if old_namespaces then
+		namespaces = {};
+		for k,v in pairs(old_namespaces) do namespaces[k] = v; end
+	end
+	local new = { name = stanza.name, attr = attr, namespaces = namespaces, tags = tags };
 	for i=1,#stanza do
 		local child = stanza[i];
 		if child.name then
--- a/util/xml.lua	Sun Dec 06 02:43:01 2015 +0100
+++ b/util/xml.lua	Tue Dec 08 23:15:42 2015 +0000
@@ -14,6 +14,17 @@
 		--luacheck: ignore 212/self
 		local handler = {};
 		local stanza = st.stanza("root");
+		local namespaces = {}
+		function handler:StartNamespaceDecl(prefix, url)
+			if prefix ~= nil then
+				namespaces[prefix] = url
+			end
+		end
+		function handler:EndNamespaceDecl(prefix)
+			if prefix ~= nil then
+				namespaces[prefix] = nil
+			end
+		end
 		function handler:StartElement(tagname, attr)
 			local curr_ns,name = tagname:match(ns_pattern);
 			if name == "" then
@@ -34,7 +45,11 @@
 					end
 				end
 			end
-			stanza:tag(name, attr);
+			local n = {}
+			for prefix, url in pairs(namespaces) do
+				n[prefix] = url
+			end
+			stanza:tag(name, attr, n);
 		end
 		function handler:CharacterData(data)
 			stanza:text(data);
--- a/util/xmppstream.lua	Sun Dec 06 02:43:01 2015 +0100
+++ b/util/xmppstream.lua	Tue Dec 08 23:15:42 2015 +0000
@@ -196,6 +196,29 @@
 		end
 	end
 
+	if stream_callbacks.track_namespaces then
+		local namespaces = {}
+		function xml_handlers:StartNamespaceDecl(prefix, url)
+			if prefix ~= nil then
+				namespaces[prefix] = url
+			end
+		end
+		function xml_handlers:EndNamespaceDecl(prefix)
+			if prefix ~= nil then
+				namespaces[prefix] = nil
+			end
+		end
+		local old_startelement = xml_handlers.StartElement
+		function xml_handlers:StartElement(tagname, attr)
+			old_startelement(self, tagname, attr)
+			local n = {}
+			for prefix, url in pairs(namespaces) do
+				n[prefix] = url
+			end
+			stanza.namespaces = n
+		end
+	end
+
 	local function restricted_handler(parser)
 		cb_error(session, "parse-error", "restricted-xml", "Restricted XML, see RFC 6120 section 11.1.");
 		if not parser.stop or not parser:stop() then