added xml parser

This commit is contained in:
Leon van Kammen 2026-06-08 15:54:48 +02:00
parent c50edf4f68
commit 694c998c08
5 changed files with 280 additions and 1 deletions

39
api.md Normal file
View file

@ -0,0 +1,39 @@
## api.parser.xml
```
local xml = api.parser.xml.newParser()
local testXml = '<testOne param="param1value">'
testXml = testXml .. '<testTwo paramTwo="param2value">'
testXml = testXml .. '<testThree>'
testXml = testXml .. 'testThreeValue'
testXml = testXml .. '</testThree>'
testXml = testXml .. '<testThree duplicate="one" duplicate="two">'
testXml = testXml .. 'testThreeValueTwo'
testXml = testXml .. '</testThree>'
testXml = testXml .. '<test_Four something="else">'
testXml = testXml .. 'testFourValue'
testXml = testXml .. '</test_Four>'
testXml = testXml .. '<testFive>'
testXml = testXml .. '<testFiveDeep>'
testXml = testXml .. '<testFiveEvenDeeper>'
testXml = testXml .. '<testSix someParam="someValue"/>'
testXml = testXml .. '</testFiveEvenDeeper>'
testXml = testXml .. '</testFiveDeep>'
testXml = testXml .. '</testFive>'
testXml = testXml .. 'testTwoValue'
testXml = testXml .. '</testTwo>'
testXml = testXml .. '</testOne>'
util.traverseXML( xml:ParseXmlText(testXml), function(node,raw)
print_r(node)
-- {
-- tag = "div",
-- prop = {
-- style = "color:red; display:none"
-- }
-- }
end)
```

35
src/ext/janusxr/main.lua Normal file
View file

@ -0,0 +1,35 @@
local api = ...
local util = api.util
return {
name = "janusxr",
enabled = true,
init = function()
local xml = api.parser.xml.newParser()
local xmlstr = [[
<room use_local_asset="room3">
<object id="foo.glb"/>
<object id="cube"/>
</room>
]]
util.traverseXML( xml:ParseXmlText(xmlstr), function(node,raw)
print_r(node)
end)
end,
renderURI = function(ctx)
-- TODO:
-- janusxr should be an ECS SYSTEM respond to inserted xmls
-- gltf should be a ECS SYSTEM respond to inserted objects
-- browser should insert url response to entity (respond to 404 + autodelete entity e.g.)
--
--local URL = ctx.URL
--local me = api.ext.gltf
--if ctx.succes and URL.extension == 'GLB' or URL.extension == 'GLTF' then
--end
end
}

171
src/lib/xmlSimple.lua Normal file
View file

@ -0,0 +1,171 @@
module(..., package.seeall)
---------------------------------------------------------------------------------
---------------------------------------------------------------------------------
--
-- xml.lua - XML parser for use with the Corona SDK.
-- https://github.com/Cluain/Lua-Simple-XML-Parser
--
-- version: 1.2
--
-- CHANGELOG:
--
-- 1.2 - Created new structure for returned table
-- 1.1 - Fixed base directory issue with the loadFile() function.
--
-- NOTE: This is a modified version of Alexander Makeev's Lua-only XML parser
-- found here: http://lua-users.org/wiki/LuaXml
--
---------------------------------------------------------------------------------
---------------------------------------------------------------------------------
function newParser()
XmlParser = {};
function XmlParser:ToXmlString(value)
value = string.gsub(value, "&", "&amp;"); -- '&' -> "&amp;"
value = string.gsub(value, "<", "&lt;"); -- '<' -> "&lt;"
value = string.gsub(value, ">", "&gt;"); -- '>' -> "&gt;"
value = string.gsub(value, "\"", "&quot;"); -- '"' -> "&quot;"
value = string.gsub(value, "([^%w%&%;%p%\t% ])",
function(c)
return string.format("&#x%X;", string.byte(c))
end);
return value;
end
function XmlParser:FromXmlString(value)
value = string.gsub(value, "&#x([%x]+)%;",
function(h)
return string.char(tonumber(h, 16))
end);
value = string.gsub(value, "&#([0-9]+)%;",
function(h)
return string.char(tonumber(h, 10))
end);
value = string.gsub(value, "&quot;", "\"");
value = string.gsub(value, "&apos;", "'");
value = string.gsub(value, "&gt;", ">");
value = string.gsub(value, "&lt;", "<");
value = string.gsub(value, "&amp;", "&");
return value;
end
function XmlParser:ParseArgs(node, s)
string.gsub(s, "(%w+)=([\"'])(.-)%2", function(w, _, a)
node:addProperty(w, self:FromXmlString(a))
end)
end
function XmlParser:ParseXmlText(xmlText)
local stack = {}
local top = newNode()
table.insert(stack, top)
local ni, c, label, xarg, empty
local i, j = 1, 1
while true do
ni, j, c, label, xarg, empty = string.find(xmlText, "<(%/?)([%w_:]+)(.-)(%/?)>", i)
if not ni then break end
local text = string.sub(xmlText, i, ni - 1);
if not string.find(text, "^%s*$") then
local lVal = (top:value() or "") .. self:FromXmlString(text)
stack[#stack]:setValue(lVal)
end
if empty == "/" then -- empty element tag
local lNode = newNode(label)
self:ParseArgs(lNode, xarg)
top:addChild(lNode)
elseif c == "" then -- start tag
local lNode = newNode(label)
self:ParseArgs(lNode, xarg)
table.insert(stack, lNode)
top = lNode
else -- end tag
local toclose = table.remove(stack) -- remove top
top = stack[#stack]
if #stack < 1 then
error("XmlParser: nothing to close with " .. label)
end
if toclose:name() ~= label then
error("XmlParser: trying to close " .. toclose.name .. " with " .. label)
end
top:addChild(toclose)
end
i = j + 1
end
local text = string.sub(xmlText, i);
if #stack > 1 then
error("XmlParser: unclosed " .. stack[#stack]:name())
end
return top
end
function XmlParser:loadFile(xmlFilename, base)
if not base then
base = system.ResourceDirectory
end
local path = system.pathForFile(xmlFilename, base)
local hFile, err = io.open(path, "r");
if hFile and not err then
local xmlText = hFile:read("*a"); -- read file content
io.close(hFile);
return self:ParseXmlText(xmlText), nil;
else
print(err)
return nil
end
end
return XmlParser
end
function newNode(name)
local node = {}
node.___value = nil
node.___name = name
node.___children = {}
node.___props = {}
function node:value() return self.___value end
function node:setValue(val) self.___value = val end
function node:name() return self.___name end
function node:setName(name) self.___name = name end
function node:children() return self.___children end
function node:numChildren() return #self.___children end
function node:addChild(child)
if self[child:name()] ~= nil then
if type(self[child:name()].name) == "function" then
local tempTable = {}
table.insert(tempTable, self[child:name()])
self[child:name()] = tempTable
end
table.insert(self[child:name()], child)
else
self[child:name()] = child
end
table.insert(self.___children, child)
end
function node:properties() return self.___props end
function node:numProperties() return #self.___props end
function node:addProperty(name, value)
local lName = "@" .. name
if self[lName] ~= nil then
if type(self[lName]) == "string" then
local tempTable = {}
table.insert(tempTable, self[lName])
self[lName] = tempTable
end
table.insert(self[lName], value)
else
self[lName] = value
end
table.insert(self.___props, { name = name, value = self[name] })
end
return node
end

View file

@ -1,7 +1,10 @@
local util = require("util")
api = {
parser = {
json = require("json"),
xml = require("xmlSimple"),
},
browser = require("browser"),
url = require("url"),
util = require("util"),

View file

@ -75,6 +75,19 @@ function util.dump(value, indent, seen)
end
end
function util.count(self)
local i = 0
if self == nil then return i end
if type(self) == 'table' then
for _, _ in pairs(self) do
i = i + 1
end
return i
else
return #self
end
end
function util.traverse(arr, cb, key)
if key == nil then key = 'children' end
foreach( arr, function(k,child)
@ -89,6 +102,24 @@ function util.traverse(arr, cb, key)
end)
end
function util.traverseXML( parsedXml, cb)
util.traverse( parsedXml,
function(node)
local struct = { tag = '?', prop = {} }
if node['name'] ~= nil then struct['tag'] = node:name() end
foreach( node['___props'], function(k,v)
local val = node[ '@' .. v['name'] ]
if type(val) == "table" then
foreach( val, function(k,v) val = v end) -- pick last
end
struct['prop'][ v['name'] ] = val
end)
cb(struct,raw)
end,
'___children'
)
end
util.call = function(fn,a,b,c,d,e,f)
return function(k,v)
if v ~= nil and v[fn] then