Skip to content

core.base.xml ​

This module provides a lightweight DOM-style XML toolkit that works inside Xmake's sandbox environment. It focuses on predictable data structures, JSON-like usability, and optional streaming so you can parse large XML documents without building the entire tree.

TIP

To use this module, you need to import it first: import("core.base.xml")

The XML module features:

  • DOM-style node structure using plain Lua tables
  • Streaming parser for large files (xml.scan)
  • XPath-like queries (xml.find)
  • Convenient file I/O helpers (xml.loadfile, xml.savefile)
  • Support for comments, CDATA, DOCTYPE, and unquoted attributes
  • Pretty printing with customizable indentation

XML nodes are plain Lua tables with the following structure:

lua
{
    name     = "element-name" | nil,  -- only for element nodes
    kind     = "element" | "text" | "comment" | "cdata" | "doctype" | "document",
    attrs    = { key = value, ... } or nil,
    text     = string or nil,
    children = { child1, child2, ... } or nil,
    prolog   = { comment/doctype nodes before root } or nil
}

xml.decode ​

  • Parse XML string into a document node

Function Prototype ​

API

lua
xml.decode(xml_string: <string>, options?: <table>)

Parameter Description ​

ParameterDescription
xml_stringXML string to parse
optionsOptional table with parsing options

Options ​

OptionDescription
trim_text = trueTrim leading/trailing whitespace from text nodes
keep_whitespace_nodes = trueKeep text nodes that contain only whitespace

Return Value ​

TypeDescription
tableDocument node (root of the XML tree)

Usage ​

lua
import("core.base.xml")

local doc = assert(xml.decode([[
<?xml version="1.0"?>
<root id="1">
  <item id="foo">hello</item>
</root>
]]))

xml.encode ​

  • Encode document node to XML string

Function Prototype ​

API

lua
xml.encode(doc: <table>, options?: <table>)

Parameter Description ​

ParameterDescription
docDocument node to encode
optionsOptional table with encoding options

Options ​

OptionDescription
pretty = trueEnable pretty printing
indentNumber of spaces for indentation (default: 2)
indentcharCharacter to use for indentation (default: " ")

Return Value ​

TypeDescription
stringXML string representation

Usage ​

lua
import("core.base.xml")

local doc = xml.decode("<root><item>hello</item></root>")
local pretty = assert(xml.encode(doc, {pretty = true, indent = 2}))

xml.loadfile ​

  • Load XML document from file

Function Prototype ​

API

lua
xml.loadfile(filepath: <string>, options?: <table>)

Parameter Description ​

ParameterDescription
filepathPath to XML file
optionsOptional table with parsing options (same as xml.decode)

Return Value ​

TypeDescription
tableDocument node

Usage ​

lua
import("core.base.xml")

local plist = assert(xml.loadfile("Info.plist"))

xml.savefile ​

  • Save XML document to file

Function Prototype ​

API

lua
xml.savefile(filepath: <string>, doc: <table>, options?: <table>)

Parameter Description ​

ParameterDescription
filepathPath to save XML file
docDocument node to save
optionsOptional table with encoding options (same as xml.encode)

Return Value ​

TypeDescription
booleanReturns true on success

Usage ​

lua
import("core.base.xml")

local doc = xml.loadfile("Info.plist")
-- ... modify nodes ...
assert(xml.savefile("Info.plist", doc, {pretty = true, indent = 2}))

xml.find ​

  • Find node using XPath-like query

Function Prototype ​

API

lua
xml.find(doc: <table>, xpath: <string>)

Parameter Description ​

ParameterDescription
docDocument node or any node to search from
xpathXPath-like query string

Return Value ​

TypeDescription
table|nilFound node or nil if not found

Usage ​

lua
import("core.base.xml")

local doc = assert(xml.loadfile("config.xml"))

-- Find by path
local element = xml.find(doc, "/root/item")

-- Find by attribute
local item = xml.find(doc, "//item[@id='foo']")

-- Find by text content
local node = xml.find(doc, "//string[text()='value']")

xml.scan ​

  • Stream parse XML and call callback for each node

Function Prototype ​

API

lua
xml.scan(xml_string: <string>, callback: <function>, options?: <table>)

Parameter Description ​

ParameterDescription
xml_stringXML string to parse
callbackFunction called for each node: function(node) -> boolean
optionsOptional table with parsing options (same as xml.decode)

Callback Return Value ​

Return false from the callback to stop scanning immediately.

Usage ​

lua
import("core.base.xml")

local found
xml.scan(plist_text, function(node)
    if node.name == "key" and xml.text_of(node) == "NSPrincipalClass" then
        found = node
        return false -- early terminate
    end
end)

xml.scan walks nodes as they are completed; returning false stops the scan immediately. This is ideal for large files when you only need a few entries.

xml.text_of ​

  • Get text content of a node

Function Prototype ​

API

lua
xml.text_of(node: <table>)

Parameter Description ​

ParameterDescription
nodeNode to extract text from

Return Value ​

TypeDescription
stringText content of the node

Usage ​

lua
import("core.base.xml")

local node = xml.find(doc, "//item[@id='foo']")
local text = xml.text_of(node)  -- Returns "hello"

xml.text ​

  • Create a text node

Function Prototype ​

API

lua
xml.text(text: <string>)

Parameter Description ​

ParameterDescription
textText content

Return Value ​

TypeDescription
tableText node

Usage ​

lua
import("core.base.xml")

local textnode = xml.text("hello")

xml.empty ​

  • Create an empty element node

Function Prototype ​

API

lua
xml.empty(name: <string>, attrs?: <table>)

Parameter Description ​

ParameterDescription
nameElement name
attrsOptional attributes table

Return Value ​

TypeDescription
tableElement node

Usage ​

lua
import("core.base.xml")

local empty = xml.empty("br", {class = "line"})

xml.comment ​

  • Create a comment node

Function Prototype ​

API

lua
xml.comment(text: <string>)

Parameter Description ​

ParameterDescription
textComment text

Return Value ​

TypeDescription
tableComment node

Usage ​

lua
import("core.base.xml")

local comment = xml.comment("generated by xmake")

xml.cdata ​

  • Create a CDATA node

Function Prototype ​

API

lua
xml.cdata(text: <string>)

Parameter Description ​

ParameterDescription
textCDATA text

Return Value ​

TypeDescription
tableCDATA node

Usage ​

lua
import("core.base.xml")

local cdata_node = xml.cdata("if (value < 1) {...}")

xml.doctype ​

  • Create a DOCTYPE node

Function Prototype ​

API

lua
xml.doctype(declaration: <string>)

Parameter Description ​

ParameterDescription
declarationDOCTYPE declaration string

Return Value ​

TypeDescription
tableDOCTYPE node

Usage ​

lua
import("core.base.xml")

local doctype = xml.doctype('plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"')

Complete Example ​

lua
import("core.base.xml")

-- Parse XML string
local doc = assert(xml.decode([[
<?xml version="1.0"?>
<root id="1">
  <item id="foo">hello</item>
</root>
]]))

-- Find and modify nodes
local item = assert(xml.find(doc, "//item[@id='foo']"))
item.attrs.lang = "en"             -- mutate attrs directly
item.children = {xml.text("world")} -- replace existing text node

-- Add comment
table.insert(doc.children, xml.comment("generated by xmake"))

-- Encode with pretty printing
local pretty = assert(xml.encode(doc, {pretty = true}))
assert(xml.savefile("out.xml", doc, {pretty = true}))