diff --git a/api.md b/api.md
new file mode 100644
index 0000000..5354f11
--- /dev/null
+++ b/api.md
@@ -0,0 +1,39 @@
+
+
+## api.parser.xml
+
+```
+local xml = api.parser.xml.newParser()
+local testXml = ''
+testXml = testXml .. ''
+testXml = testXml .. ''
+testXml = testXml .. 'testThreeValue'
+testXml = testXml .. ''
+testXml = testXml .. ''
+testXml = testXml .. 'testThreeValueTwo'
+testXml = testXml .. ''
+testXml = testXml .. ''
+testXml = testXml .. 'testFourValue'
+testXml = testXml .. ''
+testXml = testXml .. ''
+testXml = testXml .. ''
+testXml = testXml .. ''
+testXml = testXml .. ''
+testXml = testXml .. ''
+testXml = testXml .. ''
+testXml = testXml .. ''
+testXml = testXml .. 'testTwoValue'
+testXml = testXml .. ''
+testXml = testXml .. ''
+
+
+util.traverseXML( xml:ParseXmlText(testXml), function(node,raw)
+ print_r(node)
+-- {
+-- tag = "div",
+-- prop = {
+-- style = "color:red; display:none"
+-- }
+-- }
+end)
+```
diff --git a/src/ext/janusxr/main.lua b/src/ext/janusxr/main.lua
new file mode 100644
index 0000000..457d939
--- /dev/null
+++ b/src/ext/janusxr/main.lua
@@ -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 = [[
+
+
+
+
+ ]]
+ 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
+}
diff --git a/src/lib/xmlSimple.lua b/src/lib/xmlSimple.lua
new file mode 100644
index 0000000..fea233d
--- /dev/null
+++ b/src/lib/xmlSimple.lua
@@ -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, "&", "&"); -- '&' -> "&"
+ value = string.gsub(value, "<", "<"); -- '<' -> "<"
+ value = string.gsub(value, ">", ">"); -- '>' -> ">"
+ value = string.gsub(value, "\"", """); -- '"' -> """
+ value = string.gsub(value, "([^%w%&%;%p%\t% ])",
+ function(c)
+ return string.format("%X;", string.byte(c))
+ end);
+ return value;
+ end
+
+ function XmlParser:FromXmlString(value)
+ value = string.gsub(value, "([%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, """, "\"");
+ value = string.gsub(value, "'", "'");
+ value = string.gsub(value, ">", ">");
+ value = string.gsub(value, "<", "<");
+ value = string.gsub(value, "&", "&");
+ 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
+
diff --git a/src/main.lua b/src/main.lua
index 37cd572..f02a55a 100644
--- a/src/main.lua
+++ b/src/main.lua
@@ -1,7 +1,10 @@
local util = require("util")
api = {
- json = require("json"),
+ parser = {
+ json = require("json"),
+ xml = require("xmlSimple"),
+ },
browser = require("browser"),
url = require("url"),
util = require("util"),
diff --git a/src/util.lua b/src/util.lua
index c12167b..200bc66 100644
--- a/src/util.lua
+++ b/src/util.lua
@@ -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