--- -- Txml to xml conversion. -- -- This modules transforms a Txml object in an XML string. COnsider that -- tag_name or a property name can contain __ -- that will be converted to -- the corresponding escape_namespace parameter.

-- {tag_name = "html__a", xmlns__www="http://.../"}

-- will be converted to

-- <html:a xmlns:www="http://.../">

-- You may prefer writing

-- {tag_name = "html:a", xmlns__www="http://.../"}

-- that is mostrly the same, -- but there is no way to write

-- {tag_name = "html:a", xmlns:www="http://.../"}

-- in LUA, so use the __ for attributes. See the xml2table -- documentation for more infos about Txml. local Private = {} --============================================================================-- -- This is part of FreePOPs (http://www.freepops.org) released under GNU/GPL --============================================================================-- function Private.escape(s,unescape) --print("Parameters",s,unescape) if unescape == true then return s end return (string.gsub(s,[[([><"'&])]],function(x) if x == ">" then return ">" elseif x == "<" then return "<" elseif x == '"' then return """ elseif x == "'" then return "'" elseif x == "&" then return "&" end end)) end Private.Valid_Tables = [[ Valid tables are {\"pcdata\"} and {tag_name="body",color="red", {tag_name...},{tag_name...},...} and {tag_name="body",{"pcdata"}"} ]] function Private.errorize(err,t) return "Invalid Table ("..err.."): " .. (t.tag_name or t[1] or "nil") .. "\n" .. Private.Valid_Tables end function Private.escape_ns(s,c) if c then return (string.gsub(s,"__",c)) else return s end end function Private.table2xml_aux(t,oc,c,indent,unescape) if t == nil then return true end local c_p = string.rep(" ",indent) -- sanity checks local name = t.tag_name local data = t[1] local data1 = t[2] local son = nil if type(data) == "table" then son = data.tag_name end if name == nil and data == nil then local err = "Each table must contain a \"data\" alone ".. "or a 'tag_name' field" return nil,Private.errorize(err,t) end if name == nil and son ~= nil then local err = "A pcdata field can't have sons" return nil,Private.errorize(err,t) end if data1 and not son then local err = "Only one pcdata son is allowed" return nil,Private.errorize(err,t) end if name == nil and not data then local err = "No tag_name, no data" return nil,Private.errorize(err,t) end -- serializing if data ~= nil and name == nil and not son then -- we have a pcdata field oc:write(Private.escape(data,unescape)) return true else -- the parameter table local pt = {} table.foreach(t,function(k,v) if k ~= "tag_name" and type(k) ~= "number" then k = Private.escape_ns(k,c) table.insert(pt,' '..k..'="'.. Private.escape(v,unescape)..'"') end end) name = Private.escape_ns(name,c) if not data then -- we have a oc:write(c_p.."<"..name..table.concat(pt).." />\n") else -- we have a ... oc:write(c_p.."<"..name..table.concat(pt)..">") if son then oc:write("\n") end table.foreachi(t,function(_,v) local f,err = Private.table2xml_aux(v,oc,c, indent+2,unescape) if f == nil then return nil,err end end) if son then oc:write(c_p) end oc:write("\n") end return true end end --==========================================================================-- -- extern function --==========================================================================-- module("table2xml") --- -- Txml2xml conversion. -- @param encoding string the encoding, default is iso-8859-1. -- @param escape_namespace string ":" is the good one, -- if not provided no namespacing escaping is done, read no -- __ are converted. -- @param unescape boolean true to not escape XML entities -- @return string an XML string. function table2xml(t,escape_namespace,encoding,unescape) local s = nil local fake_file = {s={}} function fake_file.write(self,...) table.insert(self.s,table.concat(arg)) end function fake_file.to_string(self) return table.concat(self.s) end --print("Parameters",t,escape_namespace,encoding,unescape) fake_file:write('\n') local f,err = Private.table2xml_aux(t,fake_file,escape_namespace,0,unescape) if f == nil then print("ERROR: " .. err) end return fake_file:to_string() end