Module LuaXML
A module that maps between Lua and XML without much ado.
LuaXML provides a set of functions for processing XML data in Lua.
It offers a very simple and natural mapping between the XML format and Lua tables,
which allows one to work with and construct XML data just using Lua’s normal
table access and iteration methods (e.g. ipairs()
).
Substatements and tag content are represented as array data having numerical
keys (1 .. n
), attributes use string keys, and tags the numerical index 0
.
This representation makes sure that the structure of XML data is preserved
exactly across read/write cycles (i.e. xml.eval(var:str())
should equal var
again).
To use LuaXML, first import the module - for example like this:
local xml = require("LuaXML")
LuaXML consists of a Lua file (LuaXML.lua
) and a corresponding C module
(LuaXML_lib
) – normally a shared library (.dll
/.so
), although a static
linking is possible as well. Both parts are imported by this call, provided
that they are found in Lua’s package search path.
Functions
append (var, tag) | appends a new subordinate LuaXML object to an existing one. |
children (var, tag, key, value, maxdepth) | iterate subelements (“XML children”) as key – value pairs. |
decode (str) | converts a string from XML encoding. |
encode (str) | converts a string to XML encoding. |
eval (xml, mode) | parses an XML string into a Lua table. |
find (var, tag, key, value) | recursively searches a Lua table for a subelement matching the provided tag and attribute. |
iterate (var, cb, tag, key, value, r, max, d) | iterates a LuaXML object, invoking a callback function for all matching (sub)elements. |
load (filename, mode) | loads XML data from a file and returns it as table. |
match (var, tag, key, value) | match XML entity against given (optional) criteria. |
new (arg, tag) | creates a LuaXML “object”, and optionally sets its tag. |
registerCode (decoded, encoded) | registers a custom code for the conversion between non-standard characters and XML character entities. |
save (var, filename, filemode, cmt, hdr) | saves a Lua var as XML file. |
str (value, indent, tag) | converts any Lua value to an XML string. |
tag (var, tag) | sets or returns tag of a LuaXML object. |
Fields
WS_NORMALIZE | remove “lead in” whitespace before tags |
WS_PRESERVE | preserve all whitespace, even between tags |
WS_TRIM | strip all leading / trailing whitespace |
Functions
- append (var, tag)
-
appends a new subordinate LuaXML object to an existing one.
optionally sets tag
Parameters:
- var the parent LuaXML object
- tag optional string the tag of the appended LuaXML object
Returns:
-
appended LuaXML object, or
nil
in case of errors - children (var, tag, key, value, maxdepth)
-
iterate subelements (“XML children”) as key – value pairs.
This function is meant to be called in a generic
for
loop, similar to whatipairs(var)
would do. However you can easily specify additional criteria to match against here, possibly reducing the overhead needed to test for specific subelements.For the resulting
(k, v)
pairs, note thatk
is just a sequential number in the array of matched child elements, and has no direct relation to the actual “position” (subtag index) within eachv
’s parent object.Parameters:
- var the table (LuaXML object) to work on
- tag optional string XML tag to be matched
- key optional string attribute key to be matched
- value (optional) attribute value to be matched
- maxdepth
optional number
maximum depth allowed, defaults to 1 (only immediate children).
You can pass 0 or
true
to iterate all children recursively.
Returns:
-
Lua iterator function and initial state (Lua-internal use) – suitable
for a
for
loopSee also:
Usage:
local xml = require("LuaXML") local foobar = xml.eval('<foo><a /><b bar="no" /><c bar="yes" /><a /></foo>') -- iterate over those children that have a "bar" attribute: for k, v in foobar:children(nil, "bar") do print(k, v:tag(), v.bar) end -- will print -- 1 b no -- 2 c yes -- require "bar" to be "yes": for k, v in foobar:children(nil, "bar", "yes") do print(k, v:tag(), v.bar) end -- will print -- 1 c yes -- iterate "a" tags: (the first and fourth child will match) for k, v in foobar:children("a") do print(k, v:tag(), v.bar) end -- will print -- 1 a nil -- 2 a nil
- decode (str)
-
converts a string from XML encoding.
This function transforms
str
by replacing any special XML encodings with their “plain text” counterparts.Parameters:
- str string string to be transformed
Returns:
-
string
the decoded string
See also:
Usage:
print((xml.decode("<->")) -- "<->"
- encode (str)
-
converts a string to XML encoding.
This function transforms
str
by replacing any special characters with suitable XML encodings.Parameters:
- str string string to be transformed
Returns:
-
string
the XML-encoded string
See also:
Usage:
print(xml.encode("<->")) -- "<->"
- eval (xml, mode)
-
parses an XML string into a Lua table.
The table will contain a representation of the XML tag, attributes (and their
values), and element content / subelements (either as strings or nested LuaXML
“objects”).
Note: Parsing “wide” strings or Unicode (UCS-2, UCS-4, UTF-16) currently is not supported. If needed, convert such
xml
data to UTF-8 before passing it toeval()
. UTF-8 should be safe to use, and this function will also recognize and ignore a UTF-8 BOM (byte order mark) at the start ofxml
.Parameters:
- xml
string or userdata
the XML to be converted. When passing a userdata type
xml
value, it must point to a C-style (NUL-terminated) string. - mode
optional number
whitespace handling mode, one of the
WS_*
constants – see Fields. defaults to WS_TRIM (compatible to previous LuaXML versions)
Returns:
-
a LuaXML object containing the XML data, or
nil
in case of errors - xml
string or userdata
the XML to be converted. When passing a userdata type
- find (var, tag, key, value)
-
recursively searches a Lua table for a subelement
matching the provided tag and attribute. See the description of match for
the logic involved with testing for
tag
,key
andvalue
.Parameters:
- var the table to be searched in
- tag optional string the XML tag to be found
- key optional string the attribute key (= exact name) to be found
- value (optional) the attribute value to be found
Returns:
-
the first (sub-)table that satisfies the search condition,
or
nil
for no match - iterate (var, cb, tag, key, value, r, max, d)
-
iterates a LuaXML object,
invoking a callback function for all matching (sub)elements.
The iteration starts with the variable
var
itself (= default depth 0). A callback functioncb
gets invoked for each match , depending on the specified criteria. If ther
flag is set, the process will repeat recursively for the subelements ofvar
(at depth + 1). You can limit the scope by setting a maximum depth, or have the callback function explicitly request to stop the iteration (by returningfalse
).Parameters:
- var the table (LuaXML object) to iterate
- cb
function
callback function.
callback(var, depth)
will be called for each matching element.
The function may returnfalse
to request a stop; if its result is any other value (includingnil
), the iteration will continue. - tag optional string XML tag to be matched
- key optional string attribute key to be matched
- value (optional) attribute value to be matched
- r
optional boolean
recursive operation. If
true
, also iterate over the subelements ofvar
- max optional number maximum depth allowed
- d optional number initial depth value, defaults to 0
Returns:
-
The function returns two values: a counter representing the number of elements
that were successfully matched (and processed), and a boolean completion flag.
The latter is
true
for an exhaustive iteration, andfalse
if was stopped from the callback.See also:
- load (filename, mode)
-
loads XML data from a file and returns it as table.
Basically, this is just calling eval on the given file’s content.
Parameters:
- filename string the name and path of the file to be loaded
- mode optional number whitespace handling mode, defaults to WS_TRIM
Returns:
-
a Lua table representing the XML data, or
nil
in case of errors - match (var, tag, key, value)
-
match XML entity against given (optional) criteria.
Passing
nil
for one of thetag
,key
, orvalue
parameters means “don’t care” (i.e. match anything for that particular aspect). So for examplevar:match(nil, "text", nil) -- or shorter, but identical: var:match(nil, "text")
will look for an XML attribute (name) “text” to be present in
var
, but won’t consider its value or the tag ofvar
.Note: If you want to test for a specific attribute
value
, so also have to supply akey
– otherwisevalue
will be ignored.Parameters:
- var
the variable to test, normally a Lua table or LuaXML object. (If
var
is not a table type, the test always fails.) - tag
optional string
If set, has to match the XML tag (i.e. must be equal to the
tag(var, nil)
result) - key optional string If set, a corresponding attribute key needs to be present (exact name match).
- value
(optional)
arbitrary Lua value. If set, the attribute value for
key
has to match it.
Returns:
-
either
nil
for no match; or thevar
argument properly converted to a LuaXML object, equivalent toxml.new(var)
.This allows you to either make direct use of the matched LuaXML object, or to use the return value in a boolean test (
if xml.match(…)
), which is a common Lua idiom.Usage:
-- each of these will either return
x
, ornil
in case of no match x:match("foo") -- test for x:tag() == "foo" x:match(nil, "bar") -- test if x has a "bar" attribute x:match(nil, "foo", "bar") -- test if x has a "foo" attribute that equals "bar" x:match("foobar", "foo", "bar") -- test for "foobar" tag, and attr "foo" == "bar" - var
the variable to test, normally a Lua table or LuaXML object. (If
- new (arg, tag)
-
creates a LuaXML “object”, and optionally sets its tag.
The function either sets the metatable of an existing Lua table, or creates a
new (empty) “object”. If you pass an optional
tag
string, it will be assigned to the result.(It’s also possible to call this as
new(tag)
, which creates a new XML object with the given tag and is equivalent tonew({}, tag)
.)Note that it’s not mandatory to use this function in order to treat a Lua table as LuaXML object. Setting the metatable just allows the usage of a more object-oriented syntax (e.g.
xmlvar:str()
instead ofxml.str(xmlvar)
). XML objects created by load or eval automatically offer the object-oriented syntax.Parameters:
- arg (optional) (1) a table to be converted to a LuaXML object, or (2) the tag of the new LuaXML object
- tag optional string a tag value that will be assigned to the object
Returns:
-
LuaXML object, either newly created or the conversion of
arg
; optionally tagged as requested - registerCode (decoded, encoded)
-
registers a custom code for the conversion between non-standard characters
and XML character entities.
By default, only the most basic entities are known to LuaXML:
" < > '
On top (and independent) of that, the ampersand sign always gets encoded / decoded separately:
&
↔&
. Character codes above 127 are directly converted to an appropriate XML encoding, representing the character number (e.g. 
). If other special encodings are needed, they can be registered using this function.Note: LuaXML now manages these encodings in a (private) standard Lua table. This allows you to replace entries by calling
registerCode()
again, using the samedecoded
and a differentencoded
. Encodings may even be removed later, by explictly registering anil
value:registerCode(decoded, nil)
.Parameters:
- decoded string the character (sequence) to be used within Lua
- encoded string the character entity to be used in XML
See also:
- save (var, filename, filemode, cmt, hdr)
-
saves a Lua var as XML file.
Basically this simply exports the string representation
xml.str(var)
(orvar:str()
), plus a standard header.Parameters:
- var the variable to be saved, normally a table
- filename string the filename to be used. An existing file of the same name gets overwritten.
- filemode optional string the file mode to pass to io.open , defaults to “w”
- cmt
optional string
custom comment to be written at the top of the file (after the header). You may pass an empty string if you don’t want any comment at all, otherwise it should preferably end with at least one newline. Defaults to:
<!-- file «filename», generated by LuaXML -->\n\n
- hdr
optional string
custom header, written before anything else. You may pass an empty string if you don’t want any header at all, otherwise it should preferably end with a newline. Defaults to the standard XML 1.0 declaration:
<?xml version="1.0"?>\n
Usage:
var:save("simple.xml") var:save("no-comment.xml", nil, "") var:save("custom.xml", "a+", "<!-- append mode, no header -->\n", "")
- str (value, indent, tag)
-
converts any Lua value to an XML string.
Parameters:
- value
the value to be converted, normally a table (LuaXML object). However this
function will ‘encapsulate’ other Lua values (of arbitrary type) in a way that
should make them valid XML.
Note: Passing novalue
will cause the function to returnnil
. - indent optional number indentation level for ‘pretty’ output. Mainly for internal use, defaults to 0.
- tag
optional string
the tag to be used in case
value
doesn’t already have an ‘implicit’ tag. Mainly for internal use.
Returns:
-
string
an XML string, or
nil
in case of errors. - value
the value to be converted, normally a table (LuaXML object). However this
function will ‘encapsulate’ other Lua values (of arbitrary type) in a way that
should make them valid XML.
- tag (var, tag)
-
sets or returns tag of a LuaXML object.
This method is just “syntactic sugar” (using a typical Lua term) that allows
the writing of clearer code. LuaXML stores the tag value of an XML statement
at table index 0, hence it can be simply accessed or altered by
var[0]
. However, writingvar:tag()
for access orvar:tag(“newTag”)
for altering may be more self explanatory (and future-proof in case LuaXML’s tag handling should ever change).Parameters:
- var the variable whose tag should be accessed, a LuaXML object
- tag optional string the new tag to be set
Returns:
-
If you have passed a new tag, the function will return
var
(with its tag changed); otherwise the result will be the current tag ofvar
(normally a string).