Quick Links: Download Gideros Studio | Gideros Documentation | Gideros Development Center | Gideros community chat
XML - Gideros Forum

XML

CyberienceCyberience Member
edited February 2013 in Game & application design
Is anyone aware of a plugin for reading XML?
When I type the search in, there is Zero results. I cant be the only one who wants to read XML?

Ill explain the reason.
My app will have start up library, list of assets to be selected. then there is a download of new assets, from the server, XML formatted. if I use delimited, there may be a possibility of needing to add or change the format, so XML will make it easier to manage the database at the client.
Above is only an example, but I have about 30 Representations of Database tables to read/look up etc.
Unless someone has a nice idea?

Your humble Learnerd friend.
REAL programmers type copy con filename.exe
---------------------------------------

Comments

  • Personally I now prefer to use JSON for all of this stuff... but here's some code I had lying around to "do" XML in Gideros.
    -----------------------------------------------------------------------------------------
    -- LUA only XmlParser from Alexander Makeev
    -----------------------------------------------------------------------------------------
    XmlParser = {};
     
    function XmlParser:ToXmlString(value)
    	value = string.gsub (value, "&", "&");		-- '&' -> "&"
    	value = string.gsub (value, "<", "&lt;");		-- '<' -> "&lt;"
    	value = string.gsub (value, ">", "&gt;");		-- '>' -> "&gt;"
    	--value = string.gsub (value, "'", "&apos;");	-- '\'' -> "&apos;"
    	value = string.gsub (value, "\"", "&quot;");	-- '"' -> "&quot;"
    	-- replace non printable char -> "&#xD;"
       	value = string.gsub(value, "([^%w%&%;%p%\t% ])",
           	function (c) 
           		return string.format("&#x%X;", string.byte(c)) 
           		--return string.format("&#x%02X;", string.byte(c)) 
           		--return string.format("&#%02d;", string.byte(c)) 
           	end);
    	return value;
    end
     
    -- -------------------------------------------------------------------------------
    -- build up a table of known converters as using &#dddd; codes > 255 causes issues!
    -- map them to "sensible" valid alternatives!
     
    local xmlConvTable = {}
     
    	xmlConvTable[174] = ""
    	xmlConvTable[338] = "OE"
    	xmlConvTable[339] = "oe"
    	xmlConvTable[352] = "S"
    	xmlConvTable[353] = "s"
    	xmlConvTable[376] = "Y"
    	xmlConvTable[402] = "f"
     
    	xmlConvTable[8211] = "-"
    	xmlConvTable[8212] = "-"
    	xmlConvTable[8216] = "'"
    	xmlConvTable[8217] = "'"
    	xmlConvTable[8218] = ","
    	xmlConvTable[8220] = "'"
    	xmlConvTable[8221] = "'"
    	xmlConvTable[8222] = ","
    	xmlConvTable[8224] = "+"
    	xmlConvTable[8225] = "++"
    	xmlConvTable[8226] = "*"
    	xmlConvTable[8230] = "..."
    	xmlConvTable[8240] = ""
    	xmlConvTable[8364] = ""
    	xmlConvTable[8482] = ""
     
    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) 
    			local hn = tonumber(h,10)
     
    			-- print("HN = ",hn,xmlConvTable[hn])
     
    			if xmlConvTable[hn] == nil then 
    				-- print("XML conv H = "..h,hn)
    				return string.char(hn) 
    			else
    				return xmlConvTable[hn]
    			end
          	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(s)
      local arg = {}
      string.gsub(s, "(%w+)=([\"'])(.-)%2", function (w, _, a)
        	arg[w] = self:FromXmlString(a);
      	end)
      return arg
    end
     
    -- -------------------------------------------------------------------------------
    -- -------------------------------------------------------------------------------
    -- -------------------------------------------------------------------------------
     
    function XmlParser:ParseXmlText(xmlText)
      local stack = {}
      local top = {Name=nil,Value=nil,Attributes={},ChildNodes={}}
      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
          top.Value=(top.Value or "")..self:FromXmlString(text);
        end
     
        if empty == "/" then  -- empty element tag
     
          table.insert(top.ChildNodes, {Name=label,Value=nil,Attributes=self:ParseArgs(xarg),ChildNodes={}})
     
        elseif c == "" then   -- start tag
     
          top = {Name=label, Value=nil, Attributes=self:ParseArgs(xarg), ChildNodes={}}
          table.insert(stack, top)   -- new level
          --log("openTag ="..top.Name);
     
        else  -- end tag
     
          local toclose = table.remove(stack)  -- remove top
          --log("closeTag="..toclose.Name);
          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
          table.insert(top.ChildNodes, toclose)
        end
        i = j+1
      end
     
      local text = string.sub(xmlText, i);
     
      if not string.find(text, "^%s*$") then
     
          stack[#stack].Value=(stack[#stack].Value or "")..self:FromXmlString(text);
     
      end
     
      if #stack > 1 then
     
        error("XmlParser: unclosed "..stack[stack.n].Name)
     
      end
     
      return stack[1].ChildNodes[1];
     
    end
     
    -- -------------------------------------------------------------------------------
    -- -------------------------------------------------------------------------------
    -- -------------------------------------------------------------------------------
     
    function XmlParser:ParseXmlFile(xmlFileName)
    	local hFile,err = io.open(xmlFileName,"r");
    	if (not err) then
    		local xmlText=hFile:read("*a"); -- read file content
    		io.close(hFile);
            return self:ParseXmlText(xmlText),nil;
    	else
    		return nil,err;
    	end
    end
     
    -- -------------------------------------------------------------------------
    -- helper function to get a child of xml node by name
     
    function XmlParser:GetChild(xml, name)
    	for i=1,#xml.ChildNodes do if xml.ChildNodes[i].Name == name then return xml.ChildNodes[i] end end
    end
     
    -- -------------------------------------------------------------------------
    -- helper function to get all children of xml node by name
     
    function XmlParser:GetChildren(xml, name)
    	local result = {}
    	for i=1,#xml.ChildNodes do if xml.ChildNodes[i].Name == name then result[#result + 1] = xml.ChildNodes[i] end end
    	return result
    end
    WhiteTree Games - Home, home on the web, where the bits and bytes they do play!
    #MakeABetterGame! "Never give up, Never NEVER give up!" - Winston Churchill
  • techdojotechdojo Guru
    edited February 2013 Accepted Answer
    Also as I'm in a good mood (last day at work tomorrow) here is some code to process a twitter feed using the above
    -- -----------------------------------------
     
    tweetComplete = function(self,event)
     
        removeTweetHandlers(self)
     
        -- print("TWEET STRING = ",string.len(event.data))
        -- print(event.data)
     
        -- 1. Read the XML structure.
        -- 2. Get the title tag
        -- 3. Add it to scroll view
        -- 4. Extract a URL (starts with http://)
        -- 5. Turn the entry into a button to follow the link
     
        local xml = XmlParser:ParseXmlText(event.data)
     
        local channel = XmlParser:GetChild(xml,"channel")
        local items = XmlParser:GetChildren(channel,"item")
        local tweet,title
        local str,link,fs1,fe1,fs2,fe2
        local name = SETTINGS.data.twitterTag..": "
        local numTweets = #items
        local label,style
     
        if numTweets > 15 then numTweets = 15 end
     
        -- print("Found "..#items.." entries")
     
        for i=1,numTweets do
     
            tweet = items[i]
            title = XmlParser:GetChild(tweet,"title")	-- print("TWEET "..i.." : "..title.Value)
     
            str = sgsub(title.Value,name,"")
            link = nil
     
            fs1,fe1 = sfind(str,"<a href="http://",1" target="_blank" rel="nofollow">http://",1</a>)
     
            -- print("TWEET "..i.." : "..str)
     
            if fs1 then
                fs2,fe2 = sfind(str," ",fe1)
                if not fs2 then fs2 = slen(str)+1 end
                link = ssub(str,fs1,fs2-1)
                -- print("LINK = [["..link.."]]")
            end
     
            -- Render 
            -- label = widget.newLabel({style="tweet",x=20,y=self.tweetY,text=str})
     
            if link then style = "link" else style = "centered" end
     
            label = widget.newText({ 
                style=style, x=160, y=self.tweetY, lineSpacing=18, w=270, text=str, 
            addTouchListeners = true, onRelease = pressTweet, userData = link })
     
            self.tweetY = self.tweetY + label:getHeight() + 30
     
            self.scroll:addChild(label)
            self.scroll:addChild(widget.newRect(100,self.tweetY-10,120,1,0xFFFFFF))
     
     
        end
     
        channel,items,tweet,title,label = nil,nil,nil,nil,nil
        collectgarbage("collect")
     
    	-- Resize the tweetBox
    	local tbh = self.tweetY - self.tweetBoxPos[1] - 180
     
    	self.tweetBox:resize(self.tweetBoxPos[1],self.tweetBoxPos[2],280,tbh)
     
        self.tweetY = self.tweetY + 40
     
        addWebsiteButton(self,self.tweetY)
     
        self.scroll:updateLimits()
        self.scroll:addScrollbar(0xFFFFFF)
     
        showActivityIcon(false)
     
    end
     
    -- -------------------------------------------------------------------------
    -- Public interface to this screen class...
     
    -- Called when the scene is first created.
     
    function TweetView:init( data )	
        --print("SceneTemplate:init - background = "..data.background)
     
        -- Create the scrollview with all the basic elements in
        self.scroll = widget.newScrollView()
     
        self:addChild(self.scroll)
        self:addChild(widget.newHeader({onPress=pressTop, userData=self}))
     
        -- Create the template to hold the page of info...
     
    	local ypos = 50
     
    	self.scroll:addChild(widget.newImage({style="usCodes",x=160,y=ypos})); ypos = ypos + 20
    	self.scroll:addChild(widget.newImage3x3({x=20,y=ypos,w=280,h=40}));   
    	self.scroll:addChild(widget.newLabel({style="codeDisplay",x=160,y=ypos+25,
    		text = SETTINGS.data.numUSGames.." Games, "..SETTINGS.data.numUSCodes.." Codes"}))
    	ypos = ypos + 10 + 40
     
    	self.scroll:addChild(widget.newImage({style="euCodes",x=160,y=ypos})); ypos = ypos + 20
    	self.scroll:addChild(widget.newImage3x3({x=20,y=ypos,w=280,h=40}));    
    		self.scroll:addChild(widget.newLabel({style="codeDisplay",x=160,y=ypos+25,
    		text = SETTINGS.data.numEUGames.." Games, "..SETTINGS.data.numEUCodes.." Codes"}))
    	ypos = ypos + 10 + 40
     
    	self.scroll:addChild(widget.newImage({style="tweetHeader",x=160,y=ypos})); ypos = ypos + 20
     
    	self.tweetBoxPos = {20,ypos}
    	self.tweetBox = widget.newImage3x3({x=20,y=ypos,w=280,h=120})
     
    	self.scroll:addChild(self.tweetBox); ypos = ypos + 2
     
        self.website = nil 		-- add the button when we know how big the tweets are!
     
        -- Add in the tweets at the bottom...
        self.tweetY = ypos
     
        self.scroll:updateLimits()
        -- self.scroll:pauseControl(true)
     
        -- Get the current twitter feed as an RSS stream...
        showActivityIcon(true)
     
        self.connection = UrlLoader.new()
        self.connection:addEventListener(Event.COMPLETE,tweetComplete,self)
        self.connection:addEventListener(Event.ERROR,tweetError,self)
     
        local url = SETTINGS.data.twitterURL..SETTINGS.data.twitterTag
     
        -- print("Attempt to load content from : "..url)
     
        self.connection:load(url)
     
    end
    You'll have to ignore all the extra stuff, it's basically my widget UI library / scene manager code that I use for making non-game Gideros apps, the important stuff is the UrlLoader onComplete listener function that get's called when the request is complete.
    WhiteTree Games - Home, home on the web, where the bits and bytes they do play!
    #MakeABetterGame! "Never give up, Never NEVER give up!" - Winston Churchill
Sign In or Register to comment.