|
On Aug 22, 2016 6:59 PM, "Roberto Ierusalimschy" <roberto@inf.puc-rio.br> wrote:
>
> > In Prosody we have a library called util.stanza which deals with
> > building and traversing XML trees. They have the following basic structure:
> >
> > { name = 'x', attr = { foo = 'bar' }, tags = { ... }, ... }
>
> I like this format. It is quite similar to what my original
> quick-and-dirty XML parser in Lua did (except that it used 'label'
> instead of 'name', 'args' instead of 'attr', and does not have 'tags').
>
> -- Roberto
You could save one level of tables if you stored attributes directly in the table, not in "attrs", and used a key like "xml" to denote the tag (AFAIK you can't have an attribute named "xml", which prevents collision with any other attributes).
But from Marc's response, he's actually looking for the other way, e.g. Lua -> XML. Here is a quick dirty function which would do a very straightforward translation, but at the same time supporting obscure things like tables as keys, and it's very easy to recreate it back. As to whether it's comfortable, beauty is in the eye of the beholder.
function toxml(v)
local buf, seen = {}, {}
local function add(s) buf[#buf+1] = s end
local function dump(o)
local t = type(o)
if t == 'nil' then add('<nil/>')
elseif t == 'boolean' or t == 'number' or t == 'string' then
-- correct XML quoting left as an exercise for the user
add(string.format('<%s>%s</%s>', t, tostring(o), t))
elseif t == 'table' then
assert(not seen[o], 'cycle detected')
seen[o] = true
add('<table>')
for k, v in pairs(o) do
add('<e><k>'); dump(k); add('</k><v>'); dump(v); add('</v></e>')
end
add('</table>')
else error('not implemented:' .. t) end
end
dump(v)
return table.concat(buf)
end
print(toxml({1, '2', false, nil, {hello='world', [{math.pi}]=true}}))
-->
<table><e><k><number>1</number></k><v><number>1</number></v></e><e><k><number>2</number></k><v><string>2</string></v></e><e><k><number>3</number></k><v><boolean>false</boolean></v></e><e><k><number>5</number></k><v><table><e><k><string>hello</string></k><v><string>world</string></v></e><e><k><table><e><k><number>1</number></k><v><number>3.1415926535898</number></v></e></table></k><v><boolean>true</boolean></v></e></table></v></e></table>