Converting Simple XML to Lua Tables with XSLT

An idea came up recently in a thread on about scripting where someone made the statement that Lua tables would be more convenient for storing data than would XML. I don't have any idea as to the veracity of that statement, but I do know two things:

  1. There are more tools to work with XML than there are Lua
  2. Parsing XML in Lua sounds dumb

I've never even written any code in Lua and I'm perfectly comfortable making that second statement. Why does it sound dumb? Because Lua is a script interpreter. Then again, parsing XML in Javascript sounds dumb to me for the same reason, but I've done it all the same.

Since I was looking for an excuse to try out Lua and I don't have a great big project that I want to hook it up with right now, I thought that maybe I'd see about going from my preferred data intermediary (XML) to the poster's suggestion (tables in Lua).

Some Background
Lua is a C-like scripting language that's become popular in game development. Part of the reason for the popularity of Lua is its free open source license. Another part of the popularity comes from the easy interaction with a C or C++ project. Apparently it's also easier to program in than C.

XSLT is the extensible stylesheet transform language. XSLT can be used for processing data that's stored as XML and turning it in to other XML formats, HTML or text. I've talked about XSLT here before.

Some Work
I started by downloading the Lua source and building it. After that I had a lua executable. Running Lua interactively gives a simple shell. Using that I can type in a Lua expression and see the result. So I poked around a bit and flipped through the manual.

I wrote up an XML file that lists some items you might find in a hardware store. The file contains lists of items. Each list is represented by an <items /> element. This element has a category attribute. Inside the <items /> element are <item /> elements. Each item has a name, a price and a quantity (the number the hardware store has in stock) as attributes.

Some Results
Here's what my XML looks like:

<?xml version="1.0" ?>
    <items category="tools">
        <item name="hammer" price="10" quantity="5" />
        <item name="saw" price="15" quantity="4" />
        <item name="screwdriver" price="4" quantity="12" />
        <item name="measuring tape" price="9" quantity="3" />
        <item name="pliers" price="10" quantity="5" />
        <item name="wrench" price="10" quantity="5" />
    <items category="fasteners">
        <item name="nails" price=".1" quantity="1500" />
        <item name="screws" price=".2" quantity="1200" />
        <item name="staples" price=".05" quantity="2000" />

So now, to transform this simple XML list into a simple nested table in Lua source code, I apply this XSLT file (which I came up with through the help of Sal Mangano's XSLT Cookbook):

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="2.0" xmlns:xsl="">
<xsl:output method="text"
        omit-xml-declaration = "yes"
        encoding = "UTF-8"
<xsl:template match="itemslist">
        <xsl:apply-templates />

<xsl:template match="items">
    <xsl:apply-templates >
        <xsl:with-param name="category" select="@category" />

<xsl:template match="item">
    <xsl:param name="category" />
    <xsl:text>{["category"]="</xsl:text> <xsl:value-of select="$category" /> <xsl:text>", </xsl:text>
    <xsl:text>["name"]="</xsl:text> <xsl:value-of select="@name" /> <xsl:text>", </xsl:text>
    <xsl:text>["price"]=</xsl:text> <xsl:value-of select="@price" /> <xsl:text>, </xsl:text>
    <xsl:text> ["quantity"]=</xsl:text> <xsl:value-of select="@quantity" /> <xsl:text> }</xsl:text>
    <xsl:text>, </xsl:text>

The XSLT simply contains three templates.

  1. <itemslist> The root node. When this node is found, the beginning of a variable assignment is emitted "items=". The apply-templates statement causes other templates (in the XSLT) to be used to match other nodes (in the XML source). After all the nodes have been processed, the closing "}" is emitted.
  2. <items> A list of things in our store. The category attribute of this node is passed on by the with-param element to any templates that are called by apply-templates.
  3. <item /> The item template produces a line of text that declares a Lua table row for the item. The @name, @price, and @quantity statements are replaced by the values of each of those attributes for the item being processed. The $category statement gets the value of the category parameter that was passed from the items template.

Here's what the generated Lua file looks like:


        {["category"]="tools", ["name"]="hammer", ["price"]=10,  ["quantity"]=5 },
        {["category"]="tools", ["name"]="saw", ["price"]=15,  ["quantity"]=4 },
        {["category"]="tools", ["name"]="screwdriver", ["price"]=4,  ["quantity"]=12 },
        {["category"]="tools", ["name"]="measuring tape", ["price"]=9,  ["quantity"]=3 },
        {["category"]="tools", ["name"]="pliers", ["price"]=10,  ["quantity"]=5 },
        {["category"]="tools", ["name"]="wrench", ["price"]=10,  ["quantity"]=5 },

        {["category"]="fasteners", ["name"]="nails", ["price"]=.1,  ["quantity"]=1500 },
        {["category"]="fasteners", ["name"]="screws", ["price"]=.2,  ["quantity"]=1200 },
        {["category"]="fasteners", ["name"]="staples", ["price"]=.05,  ["quantity"]=2000 },


The only test I ran on this file was the single line
for i in items do print(items[i].name) end

so if it doesn't work in some other way, leave me a comment and teach me some more Lua.

So if you want to get some XML data into your Lua script without having to actually parse the XML yourself, you could use code like this. Note that this kind of code generation only makes sense if you were going to load up most of XML data structure into a Lua object anyway. If you have a monstrous XML file and only want to use a few lines of it, then this is going to be horrendously inefficient. In that case you're far better off parsing the XML in your application and giving Lua an access function to get the data that it needs.

Your rating: None Average: 4 (2 votes)

XSLT tranformations via a browser is only worth doing if the data doesn't change at run-time, and very frequently, otherwise an XML Parser is a better solution.
Or else every time the data changes you have to load your browser, save the file as Lua, stop the program from running, then re-run.

A browser's not the only way to use XSLT. For example, if you have a C++ app that uses Lua for scripting then you could use an XSLT library for C++ to transform data from XML to something easy for Lua to digest.

I don't think XML and XSLT are always the right solution, just that there are definitely cases where it makes sense. In many cases a hardcoded transform using an XML parser in the host application (in C++, Java, or whatever) would make more sense, but XSLT can be more flexible for applications where needs change over time.

Rendering XML via XSLT in the browser to produce Lua code then stuffing that into a Lua interpreter would be terrible process to repeat, I agree.