tags:

views:

423

answers:

3

I'm writing a Lua application that generates an Atom feed. Right now, I'm generating XML "by hand" -- writing strings to files.

This doesn't seem like the best way, although it may be. I am getting nervous about having the escaping exactly right. Has anyone done anything like this in Lua before?

Should I stick with generating "by hand"? Or write a wrapper for an existing C library?

(Perl, by comparison, seems to have a plethora of options.)

+1  A: 

There are various data persistence libraries for Lua as well, many are described at the Lua user's wiki. The page on XML has information that could help.

The nice folks over at the Kepler project have generators for HTML which can be used for generating valid XML.

There is also cosmo which is a generalized template framework that can be used to generate XML (among other things).

Edit:

I understand the concern for templates not necessarily providing guarantees that the output remains well formed. I'm pretty sure that the authors of Cosmo would be unhappy if a well-formed template ever produced a mal-formed document, but there is still the issue of properly quoting the content. In the contexts where I've used it, this hasn't been an issue for me, but I also haven't been working from untrusted source text.

There are also projects posted at LuaForge that may be useful:

  • Lua Element Tree maps an XML document to and from a tree of tables. It uses Expat for reading, and claims to generate valid XML when writing.

  • LuaSOAP Includes XML generation and parsing sufficient for SOAP transactions. If you decide to write your own generator, this might be a good starting point for a limited dialect such as RSS or ATOM.

Also, I know I've seen a project that implemented a complete DOM for HTML documents and supported both parsing and document generation, but I can't remember its name or locate it today at LuaForge.

Edit 2: Here's another package that I hadn't noticed before, even though it is included in Lua for Windows: LuaXML. It maps between XML and nest of Lua tables, and can both read and write XML.

RBerteig
Thanks for the response. Unfortunately, templating systems (like Cosmo) aren't any safer or easier than generating by hand -- I'd like something that might help me generate well-formed XML. Something that can guarantee well-formedness would be even better. I also don't see any XML generation libraries on lua-users.org or as part of Kepler -- luaexpat (http://www.keplerproject.org/luaexpat/) is just for parsing and the libxml2 bindings seem to have vanished.
adrian
I added a couple of links to LuaForge projects that also approach your needs. I haven't spotted a perfect solution, however.
RBerteig
Thanks for the specifics! I'll definitely investigate both of these.
adrian
+2  A: 

I've generated XML by hand too. I created an API that looks like:

function XmlElement(tag, text, attr)
    ...
end

function XmlSubelement(root, tag, text, attr)
    ...
end

Then to use it:

local root = XmlElement("Level0")
XmlSubelement(root, "Level1", "some text")
XmlSubelement(root, "Level1", "some more text")

local s = root:tostring()

I don't have the code any longer, but it fit on one screen including the quoting.

uroc
Thanks; that's a good suggestion. I may end up going this route or just writing a binding to a C library like GenX.
adrian
A: 

I've now got one more answer to my question: I've written Lua bindings for Tim Bray's C XML generator, Genx.

Here's its homepage; here's the project on Bitbucket. It's an incomplete binding right now, but it works for simple tasks:

require 'genx'
d = genx.new(io.stdout)

d:startElement('farm')

d:startElement('crop')
d:attribute('type', 'fruit')
d:text('Apricots')
d:endElement()

d:startElement('crop')
d:attribute('type', 'vegetable')
d:text('Zucchini')
d:endElement()

d:endElement()

Produces:

<farm><crop type="fruit">Apricots</crop><crop type="vegetable">Zucchini</crop></farm>

Personally, I find this kind of "streaming" interface slightly nicer to work with than a tree-based interface for generation.

adrian