Lua to XML Converter
Paste Lua tables. Get clean XML back.
What this tool does
If you have ever tried to hand-roll XML out of a Lua table — for an Nginx config, a game save file, a Redis script payload — you know it is tedious. xml2lua goes the other way cleanly, but producing XML from a Lua table still means walking the table yourself and writing string concatenation. Paste the Lua here and you get back well-formed XML in one pass — every key, every nested subtable, every array item preserved.
The tool knows how Lua tables actually behave. A hash-style table ({ name = "Ava", age = 30 }) becomes an element with child elements named after the string keys. An array-style table ({ "a", "b", "c" }) — the kind Lua programmers call a "sequence" — becomes a container element with one child per item. Mixed tables (both string keys and numeric indices in the same table) come through with the hash part as named children and the sequence part as indexed children underneath, so nothing is silently dropped. Booleans (true, false) and numbers stay as their literal text; nil values are emitted as empty self-closing elements rather than disappearing.
A few Lua idioms are handled the way a person would hope. local declarations are stripped so local order = { ... } just uses the table inside. A trailing return order at the end of a module file is recognised and the returned table becomes the document root. Long strings written with [[ ... ]] come through as text content with whitespace preserved. Keys that are not valid XML element names — ["content-type"], [1], ["2024-04"] — are rewritten to a safe tag name so the document still parses. If you are new to the quirks of how Lua treats integer vs string keys, the Programming in Lua book has a useful chapter on it.
How to use it
Three steps. Works the same whether you paste a one-line table or a full module file.
Paste your Lua (or try the sample)
Drop your Lua code into the left editor. A bare table literal, a local t = {...} assignment, or a whole module ending in return t — all fine. Click Load Sample if you want a realistic Order example to play with first.
You do not need to strip comments, remove require() calls, or inline metatables. Just paste. We read the table literal and ignore the rest.
Hit Convert
Click the green Convert button. The tool walks the Lua table — array part, hash part, nested subtables — and builds the XML in one pass. You will see a short loading indicator while it runs.
Copy the XML
The right panel fills with indented, well-formed XML that any standards-compliant parser (including LuaExpat) will accept. Copy it into your config file, test fixture, or documentation.
When this actually comes in handy
Game config files
Your Love2D or Defold project keeps level data as a Lua table, but your level editor or publishing pipeline wants XML. Paste the Lua, copy the XML — no ad-hoc converter script to maintain.
Nginx / OpenResty config payloads
If you build request or response bodies as Lua tables inside an <code>ngx.location.capture</code> call and need XML output, this saves writing a concatenation helper. Nested tables become nested elements cleanly.
Redis Lua script payloads
Redis scripts that return structured tables (for logging, audit trails, or downstream ingestion) sometimes need to be shipped as XML to legacy consumers. Paste the table literal, get XML that drops straight into the pipeline.
Converting between xml2lua and other tooling
Teams that use <code>xml2lua</code> for the XML-to-Lua direction sometimes need the reverse for tests and fixtures. This gives you a quick, visual check of what a Lua table should look like as XML before committing to a hand-written serializer.
Common questions
How are array-style and hash-style tables handled differently?
An array-style table ({ "a", "b", "c" }) becomes a container element with numbered children named after the parent (or a generic <item> tag). A hash-style table ({ name = "Ava" }) becomes an element with named children. A mixed table — both a sequence part and string keys — gets both shapes side by side so nothing is lost.
What about string keys vs integer keys?
String keys become element names directly: { orderId = "ORD-4821" } → <orderId>ORD-4821</orderId>. Integer keys used as a sequence (1, 2, 3, ...) become positional children. Integer keys with gaps, or non-integer numeric keys, are emitted with an index attribute so the mapping is preserved. See the Lua 5.4 reference manual for the underlying semantics.
Does it handle nested tables and mixed types?
Yes — arbitrary nesting, mixed string / integer keys, tables-in-arrays, arrays-in-tables. Nested subtables come through as nested elements with their own children. Booleans print as true/false, numbers stay as their literal text, and nil becomes an empty self-closing element so the shape stays stable across records.
What happens to keys with dashes or reserved characters?
Keys like ["content-type"] or ["2024-04"] are legal in Lua but illegal as raw XML element names. The converter rewrites them to a safe tag (for example content_type) and preserves the original name as an attribute. If strict round-tripping matters, look the output over before using.
Can I paste a whole module file?
Yes. local declarations, require() lines, helper functions, and comments are ignored. If the file ends in return t, the returned table becomes the document root. If there is just a single top-level table literal, that is used instead.
Is my code stored?
The code is sent to the backend for conversion and is not persisted — we do not log the payload. If the script is sensitive, treat it the way you would any online tool: scrub secrets first, then paste.
Other tools you may need
Lua to XML is one piece of the puzzle. These tools pair well with it: