|
1 local s_find, s_gsub, s_match = string.find, string.gsub, string.match; |
|
2 local t_concat, t_insert = table.concat, table.insert; |
|
3 |
|
4 local pairs = require "util.iterators".sorted_pairs; |
|
5 |
|
6 local escape_table = { ["'"] = "'", ["\""] = """, ["<"] = "<", [">"] = ">", ["&"] = "&" }; |
|
7 local function xml_escape(str) return (s_gsub(str, "['&<>\"]", escape_table)); end |
|
8 |
|
9 local function _dostring(t, buf, self, _xml_escape, parentns) |
|
10 local nsid = 0; |
|
11 local name = t.name |
|
12 t_insert(buf, "<"..name); |
|
13 for k, v in pairs(t.attr) do |
|
14 if s_find(k, "\1", 1, true) then |
|
15 local ns, attrk = s_match(k, "^([^\1]*)\1?(.*)$"); |
|
16 nsid = nsid + 1; |
|
17 t_insert(buf, " xmlns:ns"..nsid.."='".._xml_escape(ns).."' ".."ns"..nsid..":"..attrk.."='".._xml_escape(v).."'"); |
|
18 elseif not(k == "xmlns" and v == parentns) then |
|
19 t_insert(buf, " "..k.."='".._xml_escape(v).."'"); |
|
20 end |
|
21 end |
|
22 local len = #t; |
|
23 if len == 0 then |
|
24 t_insert(buf, "/>"); |
|
25 else |
|
26 t_insert(buf, ">"); |
|
27 for n=1,len do |
|
28 local child = t[n]; |
|
29 if child.name then |
|
30 self(child, buf, self, _xml_escape, t.attr.xmlns); |
|
31 else |
|
32 t_insert(buf, _xml_escape(child)); |
|
33 end |
|
34 end |
|
35 t_insert(buf, "</"..name..">"); |
|
36 end |
|
37 end |
|
38 |
|
39 return { |
|
40 enable = function () |
|
41 local stanza_mt = require "util.stanza".stanza_mt; |
|
42 stanza_mt._unsorted_tostring = stanza_mt.__tostring; |
|
43 function stanza_mt.__tostring(t) |
|
44 local buf = {}; |
|
45 _dostring(t, buf, _dostring, xml_escape, nil); |
|
46 return t_concat(buf); |
|
47 end; |
|
48 end; |
|
49 disable = function () |
|
50 local stanza_mt = require "util.stanza".stanza_mt; |
|
51 if stanza_mt._unsorted_tostring then |
|
52 stanza_mt.__tostring = stanza_mt._unsorted_tostring; |
|
53 end |
|
54 end; |
|
55 }; |
|
56 |