A standalone XML module that converts between XML text and a Lua node model.
xml.encode(node [, options])→ XML text from a node table. Alias:xml.stringify.- Setting
options.pretty = trueindents with two spaces. Settingoptions.indent = Nindents withNspaces.
- Setting
xml.decode(text)→ The root node table. Alias:xml.parse. Raises on invalid input.
The node model round-trips losslessly:
{
name = "tag", -- Element name
attributes = { k = "v" }, -- Present only when the element has attributes
children = { <node>, ... }, -- Child elements, in document order
text = "...", -- Concatenated direct text, when present
}Element names are sanitized and text is escaped on encode. The parser does not load external entities or expand DTD entities, and node conversion is depth-capped.
-- Parse and stringify are aliases of decode and encode.
local xml = require("xml")
local node = xml.parse('<user id="1"><name>Lua</name></user>')
print(node.name, node.attributes.id, node.children[1].text)
print(xml.stringify({ name = "ok", text = "done" }))-- Build a document from the node model and parse it back.
local xml = require("xml")
local doc = xml.encode({
name = "catalog",
children = {
{
name = "book",
attributes = { id = "1" },
children = { { name = "title", text = "Varn" } },
},
},
}, { pretty = true })
print(doc)
local node = xml.decode(doc)
print(node.name, node.children[1].attributes.id, node.children[1].children[1].text)-- Text and attribute specials are escaped and invalid names are sanitized.
local xml = require("xml")
-- Special characters in text and attributes are escaped on encode.
print(xml.encode({ name = "msg", attributes = { note = 'a & b "c"' }, text = "x < y > z" }))
-- An invalid element name is sanitized so it cannot break the document.
print(xml.encode({ name = "bad name!", text = "ok" }))
-- Escaped values round-trip back to their original form.
local back = xml.decode(xml.encode({ name = "n", text = "a < b & c" }))
print(back.text)-- Indent sets the indentation width in spaces.
local xml = require("xml")
local node = { name = "root", children = { { name = "item", text = "value" } } }
print(xml.encode(node, { indent = 4 }))-- Parse a document, walk its nodes, and re-encode it.
local xml = require("xml")
local original = '<note priority="high"><to>Lua</to><from>C++</from><body>hello & bye</body></note>'
local node = xml.decode(original)
print("root:", node.name, "priority:", node.attributes.priority)
for _, child in ipairs(node.children) do
print(child.name, "=", child.text)
end
print(xml.encode(node))Parsing and serialization use the pugixml C++ library.