local global = _G; local lxp = lxp; local io = io; local table = table; local pairs = pairs; local assert = assert; local type = type; local setmetatable = setmetatable; local string = string; local error = error; local print = print; -- DEBUGGING module(...) Node = { }; Node.__index = Node; -- create a new node function Node.create(_name, _attributes) local tmp = {}; setmetatable(tmp, Node); tmp._NAME = _name; tmp._ATTRIBUTES = _attributes; return tmp; end -- get a single element by it's name or index function Node:getElement(index) if( type(index) == "string" ) then for i,v in pairs(self) do if( v._NAME == index and i ~= "_ATTRIBUTES" ) then return v; end end return nil; -- not found end if( type(index) == "number" ) then if( index < 1 ) then return nil; end; -- invalid index if( index > #self ) then return nil; end; -- invalid index (not 100% accurate, but quick) local count = 0; for i,v in pairs(self) do if( type(v) == "table" and i ~= "_ATTRIBUTES" ) then count = count + 1; if( count == index ) then return v; end end end return nil; -- not found end return nil; -- invalid index type, return nil end -- get all elements as a table function Node:getElements() local tmp = {}; for i,v in pairs(self) do if( type(v) == "table" and i ~= "_ATTRIBUTES" ) then table.insert(tmp, v); end end return tmp; end -- get the number of elements that are a child of this node function Node:getElementCount() local count = 0; for i,v in pairs(self) do if( type(v) == "table" ) then count = count + 1; end end return count; end function Node:getAttribute(index) if( type(index) == "string" or type(index) == "number") then return self._ATTRIBUTES[index]; end return nil; end function Node:getAttributes() return self._ATTRIBUTES; end function Node:getAttributeCount() return #self._ATTRIBUTES; end -- return _NAME function Node:getName() return self._NAME; end -- return _VALUE function Node:getValue() return self._VALUE; end -- print a debug string of the current node function Node:debug() local str = string.format("Element \'%s\'", self._NAME); print(str); for i,v in pairs(self) do str = string.format(" %s:", i); print(str, v) end str = string.format("\n%s._ATTRIBUTES:", self._NAME); print(str); for i,v in pairs(self._ATTRIBUTES) do str = string.format(" %s:", i); print(str, v); end end function startElement(parser, _name, _attributes) local stack = parser:getcallbacks().stack; local newtab = Node.create(_name, _attributes); table.insert(stack, newtab); end function endElement(parser, _name) local stack = parser:getcallbacks().stack; local element = table.remove(stack); local level = table.getn(stack); table.insert(stack[level], element); end function characterData(parser, str) if( not string.find(str, "%w") ) then return; end local stack = parser:getcallbacks().stack; local element = stack[table.getn(stack)]; local n = table.getn(element); if( element._VALUE ) then element._VALUE = element._value .. str; else element._VALUE = str; end end function open(filename) callbacks = { StartElement = startElement, EndElement = endElement, CharacterData = characterData, _nonstrict = true, stack = {{}}} local p = lxp.new(callbacks); local file = io.open(filename); if( file == nil ) then local err = string.format("Cannot open file \'%s\' for reading.", filename); error(err, 0); end for l in file:lines() do p:parse(l); p:parse("\n"); end p:parse(); p:close(); file:close(); return callbacks.stack[1][1]; end