import("core.base.xml")
function test_decode_basic(t)
local doc = xml.decode([[- foo
]])
t:are_equal(doc.kind, "element")
t:are_equal(doc.name, "root")
t:are_equal(doc.attrs.id, "1")
t:are_equal(#doc.children, 2)
t:are_equal(doc.children[1].name, "item")
t:are_equal(xml.text_of(doc.children[1]), "foo")
t:are_equal(doc.children[1].attrs, nil)
t:are_equal(doc.children[2].attrs.id, "2")
end
function test_decode_unquoted_attrs(t)
local doc = xml.decode("")
t:are_equal(doc.attrs.flag, "true")
t:are_equal(doc.attrs.count, "42")
t:are_equal(doc.attrs.path, "/tmp/file")
t:are_equal(doc.children[1].attrs.data, "abc")
end
function test_decode_mixed_attrs(t)
local xmltext = [[]]
local doc = xml.decode(xmltext)
t:are_equal(doc.attrs.a, "1 2")
t:are_equal(doc.attrs.b, "foo & bar")
t:are_equal(doc.attrs.c, "bare")
t:are_equal(doc.attrs["data-id"], "abc123")
t:are_equal(doc.attrs["ns:flag"], "true")
t:are_equal(doc.attrs["dashed-name"], "hello-world")
end
function test_encode_basic(t)
local doc = xml.new({
name = "root",
attrs = {id = "1"},
children = {
xml.new({name = "item", children = {xml.text("foo")}}),
xml.new({name = "item", attrs = {id = "2"}})
}
})
local compact = xml.encode(doc)
t:are_equal(compact, '- foo
')
local pretty = xml.encode(doc, {pretty = true, indent = 2})
local expected = table.concat({
'',
' - foo
',
' ',
''
}, "\n")
t:are_equal(pretty, expected)
end
function test_encode_special_nodes(t)
t:are_equal(xml.encode(xml.comment("note")), "")
t:are_equal(xml.encode(xml.cdata("a < b")), "")
t:are_equal(xml.encode(xml.doctype("note SYSTEM \"note.dtd\"")), "")
t:are_equal(xml.encode(xml.empty("br")), "
")
end
function test_decode_special_nodes(t)
local doc = xml.decode([=[]=])
t:are_equal(doc.children[1].kind, "comment")
t:are_equal(doc.children[1].text, "note")
t:are_equal(doc.children[2].kind, "cdata")
t:are_equal(doc.children[2].text, "a < b")
t:are_equal(doc.children[3].name, "child")
local nodes = xml.decode([=[]=])
t:are_equal(nodes.kind, "element")
t:are_equal(nodes.name, "root")
t:are_equal(nodes.prolog[1].kind, "doctype")
end
function test_load_save(t)
local tmpdir = os.tmpdir()
local filepath = path.join(tmpdir, "xml_test.xml")
local doc = xml.new({
name = "root",
attrs = {id = "1"},
children = {xml.text("hello")}
})
assert(xml.savefile(filepath, doc, {pretty = true}))
local reloaded = xml.loadfile(filepath)
t:are_equal(reloaded.name, "root")
t:are_equal(xml.text_of(reloaded), "hello")
os.tryrm(filepath)
end
function test_plist_sample(t)
local plist = [[
CFBundleDevelopmentRegion
$(DEVELOPMENT_LANGUAGE)
CFBundleExecutable
$(EXECUTABLE_NAME)
CFBundleIdentifier
$(PRODUCT_BUNDLE_IDENTIFIER)
NSHumanReadableCopyright
Copyright © 2020 tboox. All rights reserved.
NSSupportsAutomaticTermination
]]
local doc = xml.decode(plist)
t:are_equal(doc.name, "plist")
t:are_equal(doc.attrs.version, "1.0")
t:are_equal(doc.prolog[1].kind, "doctype")
local dict = xml.find(doc, "plist/dict")
t:are_equal(dict.kind, "element")
local first_key = dict.children[1]
t:are_equal(first_key.name, "key")
t:are_equal(xml.text_of(first_key), "CFBundleDevelopmentRegion")
local first_value = dict.children[2]
t:are_equal(first_value.name, "string")
t:are_equal(xml.text_of(first_value), "$(DEVELOPMENT_LANGUAGE)")
local last_flag = dict.children[#dict.children]
t:are_equal(last_flag.name, "true")
end
function test_scan_stop(t)
local plist = [[
CFBundleExecutable
$(EXECUTABLE_NAME)
NSPrincipalClass
NSApplication
]]
local found
xml.scan(plist, function(node)
if node.name == "key" and xml.text_of(node) == "NSPrincipalClass" then
found = node
return false
end
end)
t:are_equal(found ~= nil, true)
t:are_equal(xml.text_of(found), "NSPrincipalClass")
end
function test_find_xpath(t)
local doc = xml.decode([[
- foo
- bar
]])
local second = xml.find(doc, "root/items/item[2]")
t:are_equal(second.attrs.id, "b")
local descendant = xml.find(doc, "//item[@id='c']")
t:are_equal(descendant.attrs.id, "c")
local value = xml.find(doc, "//value[text()='bar']")
t:are_equal(xml.text_of(value), "bar")
end
function test_find_update(t)
local doc = xml.decode("- foo
")
local target = xml.find(doc, "//item[@id='a']")
t:are_not_equal(target, nil)
target.attrs.lang = "en"
target.children = {xml.text("bar")}
local new_item = xml.new({name = "item", attrs = {id = "c"}, children = {xml.text("baz")}})
table.insert(doc.children, new_item)
local encoded = xml.encode(doc)
t:are_equal(encoded, '- bar
- baz
')
end
function test_decode_trim_text(t)
local doc = xml.decode(" foo ")
t:are_equal(xml.text_of(doc), " foo ")
local trimmed = xml.decode(" foo ", {trim_text = true})
t:are_equal(xml.text_of(trimmed), "foo")
local formatted = "\n \n"
local default = xml.decode(formatted)
t:are_equal(#default.children, 1)
local keep_ws = xml.decode(formatted, {keep_whitespace_nodes = true})
t:are_equal(#keep_ws.children, 3)
t:are_equal(keep_ws.children[1].kind, "text")
end