Hallucinate some xml helper functions in lua
This commit is contained in:
87
processor/luahelper-test-xml.lua
Normal file
87
processor/luahelper-test-xml.lua
Normal file
@@ -0,0 +1,87 @@
|
||||
dofile("luahelper.lua")
|
||||
-- Test cases for XML helper functions
|
||||
|
||||
-- Mock XML structure for testing
|
||||
local testXML = {
|
||||
_tag = "root",
|
||||
_attr = {version = "1.0"},
|
||||
_children = {
|
||||
{
|
||||
_tag = "item",
|
||||
_attr = {name = "sword", damage = "10", weight = "5.5"},
|
||||
_text = "Iron Sword"
|
||||
},
|
||||
{
|
||||
_tag = "item",
|
||||
_attr = {name = "shield", defense = "8"},
|
||||
_children = {
|
||||
{
|
||||
_tag = "material",
|
||||
_attr = {type = "steel", durability = "100"}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
_tag = "container",
|
||||
_children = {
|
||||
{_tag = "item", _attr = {name = "potion", healing = "20"}},
|
||||
{_tag = "item", _attr = {name = "scroll"}}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print("=== XML Helper Functions Tests ===\n")
|
||||
|
||||
-- Test findElements
|
||||
print("1. Find all 'item' elements:")
|
||||
local items = findElements(testXML, "item")
|
||||
print(" Found " .. #items .. " items")
|
||||
for i, item in ipairs(items) do
|
||||
print(" - " .. (item._attr.name or "unnamed"))
|
||||
end
|
||||
|
||||
-- Test getNumAttr and setNumAttr
|
||||
print("\n2. Get/Set numeric attributes:")
|
||||
local sword = items[1]
|
||||
local damage = getNumAttr(sword, "damage")
|
||||
print(" Sword damage: " .. tostring(damage))
|
||||
setNumAttr(sword, "damage", damage * 2)
|
||||
print(" After doubling: " .. sword._attr.damage)
|
||||
|
||||
-- Test modifyNumAttr
|
||||
print("\n3. Modify numeric attribute:")
|
||||
modifyNumAttr(sword, "weight", function(val) return val * 1.5 end)
|
||||
print(" Sword weight modified: " .. sword._attr.weight)
|
||||
|
||||
-- Test filterElements
|
||||
print("\n4. Filter elements with 'healing' attribute:")
|
||||
local healingItems = filterElements(testXML, function(elem)
|
||||
return hasAttr(elem, "healing")
|
||||
end)
|
||||
print(" Found " .. #healingItems .. " healing items")
|
||||
|
||||
-- Test visitElements
|
||||
print("\n5. Visit all elements:")
|
||||
local count = 0
|
||||
visitElements(testXML, function(elem, depth, path)
|
||||
count = count + 1
|
||||
if depth <= 2 then
|
||||
print(" " .. string.rep(" ", depth) .. elem._tag .. " @ " .. path)
|
||||
end
|
||||
end)
|
||||
print(" Total elements visited: " .. count)
|
||||
|
||||
-- Test getText and setText
|
||||
print("\n6. Text content:")
|
||||
print(" Original text: " .. (getText(sword) or "none"))
|
||||
setText(sword, "Modified Sword")
|
||||
print(" New text: " .. getText(sword))
|
||||
|
||||
-- Test hasAttr and getAttr
|
||||
print("\n7. Check attributes:")
|
||||
print(" Sword has 'damage': " .. tostring(hasAttr(sword, "damage")))
|
||||
print(" Sword has 'magic': " .. tostring(hasAttr(sword, "magic")))
|
||||
print(" Sword name: " .. (getAttr(sword, "name") or "none"))
|
||||
|
||||
print("\n=== Tests Complete ===")
|
||||
@@ -350,3 +350,184 @@ function isArray(t)
|
||||
end
|
||||
|
||||
modified = false
|
||||
|
||||
-- ============================================================================
|
||||
-- XML HELPER FUNCTIONS
|
||||
-- ============================================================================
|
||||
|
||||
--- Find all elements with a specific tag name (recursive search)
|
||||
--- @param root table The root XML element (with _tag, _attr, _children fields)
|
||||
--- @param tagName string The tag name to search for
|
||||
--- @return table Array of matching elements
|
||||
function findElements(root, tagName)
|
||||
local results = {}
|
||||
|
||||
local function search(element)
|
||||
if element._tag == tagName then
|
||||
table.insert(results, element)
|
||||
end
|
||||
if element._children then
|
||||
for _, child in ipairs(element._children) do
|
||||
search(child)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
search(root)
|
||||
return results
|
||||
end
|
||||
|
||||
--- Visit all elements recursively and call a function on each
|
||||
--- @param root table The root XML element
|
||||
--- @param callback function Function to call with each element: callback(element, depth, path)
|
||||
function visitElements(root, callback)
|
||||
local function visit(element, depth, path)
|
||||
callback(element, depth, path)
|
||||
if element._children then
|
||||
for i, child in ipairs(element._children) do
|
||||
local childPath = path .. "/" .. child._tag .. "[" .. i .. "]"
|
||||
visit(child, depth + 1, childPath)
|
||||
end
|
||||
end
|
||||
end
|
||||
visit(root, 0, "/" .. root._tag)
|
||||
end
|
||||
|
||||
--- Get numeric value from XML element attribute
|
||||
--- @param element table XML element with _attr field
|
||||
--- @param attrName string Attribute name
|
||||
--- @return number|nil The numeric value or nil if not found/not numeric
|
||||
function getNumAttr(element, attrName)
|
||||
if not element._attr then return nil end
|
||||
local value = element._attr[attrName]
|
||||
if not value then return nil end
|
||||
return tonumber(value)
|
||||
end
|
||||
|
||||
--- Set numeric value to XML element attribute
|
||||
--- @param element table XML element with _attr field
|
||||
--- @param attrName string Attribute name
|
||||
--- @param value number Numeric value to set
|
||||
function setNumAttr(element, attrName, value)
|
||||
if not element._attr then
|
||||
element._attr = {}
|
||||
end
|
||||
element._attr[attrName] = tostring(value)
|
||||
end
|
||||
|
||||
--- Modify numeric attribute by applying a function
|
||||
--- @param element table XML element
|
||||
--- @param attrName string Attribute name
|
||||
--- @param func function Function that takes current value and returns new value
|
||||
--- @return boolean True if modification was made
|
||||
function modifyNumAttr(element, attrName, func)
|
||||
local current = getNumAttr(element, attrName)
|
||||
if current then
|
||||
setNumAttr(element, attrName, func(current))
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
--- Find all elements matching a predicate function
|
||||
--- @param root table The root XML element
|
||||
--- @param predicate function Function that takes element and returns true/false
|
||||
--- @return table Array of matching elements
|
||||
function filterElements(root, predicate)
|
||||
local results = {}
|
||||
visitElements(root, function(element)
|
||||
if predicate(element) then
|
||||
table.insert(results, element)
|
||||
end
|
||||
end)
|
||||
return results
|
||||
end
|
||||
|
||||
--- Get text content of an element
|
||||
--- @param element table XML element
|
||||
--- @return string|nil The text content or nil
|
||||
function getText(element)
|
||||
return element._text
|
||||
end
|
||||
|
||||
--- Set text content of an element
|
||||
--- @param element table XML element
|
||||
--- @param text string Text content to set
|
||||
function setText(element, text)
|
||||
element._text = text
|
||||
end
|
||||
|
||||
--- Check if element has an attribute
|
||||
--- @param element table XML element
|
||||
--- @param attrName string Attribute name
|
||||
--- @return boolean True if attribute exists
|
||||
function hasAttr(element, attrName)
|
||||
return element._attr and element._attr[attrName] ~= nil
|
||||
end
|
||||
|
||||
--- Get attribute value as string
|
||||
--- @param element table XML element
|
||||
--- @param attrName string Attribute name
|
||||
--- @return string|nil The attribute value or nil
|
||||
function getAttr(element, attrName)
|
||||
if not element._attr then return nil end
|
||||
return element._attr[attrName]
|
||||
end
|
||||
|
||||
--- Set attribute value
|
||||
--- @param element table XML element
|
||||
--- @param attrName string Attribute name
|
||||
--- @param value any Value to set (will be converted to string)
|
||||
function setAttr(element, attrName, value)
|
||||
if not element._attr then
|
||||
element._attr = {}
|
||||
end
|
||||
element._attr[attrName] = tostring(value)
|
||||
end
|
||||
|
||||
-- ============================================================================
|
||||
-- JSON HELPER FUNCTIONS
|
||||
-- ============================================================================
|
||||
|
||||
--- Recursively visit all values in a JSON structure
|
||||
--- @param data table JSON data (nested tables)
|
||||
--- @param callback function Function called with (value, key, parent)
|
||||
function visitJSON(data, callback)
|
||||
local function visit(obj, key, parent)
|
||||
callback(obj, key, parent)
|
||||
if type(obj) == "table" then
|
||||
for k, v in pairs(obj) do
|
||||
visit(v, k, obj)
|
||||
end
|
||||
end
|
||||
end
|
||||
visit(data, nil, nil)
|
||||
end
|
||||
|
||||
--- Find all values in JSON matching a predicate
|
||||
--- @param data table JSON data
|
||||
--- @param predicate function Function that takes (value, key, parent) and returns true/false
|
||||
--- @return table Array of matching values
|
||||
function findInJSON(data, predicate)
|
||||
local results = {}
|
||||
visitJSON(data, function(value, key, parent)
|
||||
if predicate(value, key, parent) then
|
||||
table.insert(results, value)
|
||||
end
|
||||
end)
|
||||
return results
|
||||
end
|
||||
|
||||
--- Modify all numeric values in JSON matching a condition
|
||||
--- @param data table JSON data
|
||||
--- @param predicate function Function that takes (value, key, parent) and returns true/false
|
||||
--- @param modifier function Function that takes current value and returns new value
|
||||
function modifyJSONNumbers(data, predicate, modifier)
|
||||
visitJSON(data, function(value, key, parent)
|
||||
if type(value) == "number" and predicate(value, key, parent) then
|
||||
if parent and key then
|
||||
parent[key] = modifier(value)
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
Reference in New Issue
Block a user