lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


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>