Load XML from http and parse it

Has anyone done that yet?
I am a flash developer new to this,
My mission:

  • load XML from http and parse the data.

Can someone tell me how to do this? Thanks

Cheers [import]uid: 1995 topic_id: 375 reply_id: 300375[/import]

I hope this works

 local http = require("socket.http")  
 local io = require("io");  
 local ltn12 = require("ltn12")   
  
  
function parseargs(s)  
 local arg = {}  
 string.gsub(s, "(%w+)=([\"'])(.-)%2", function (w, \_, a)  
 arg[w] = a  
 end)  
 return arg  
end  
  
function collect(s)  
  
local stack = {}  
 local top = {}  
 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(s, "", i)  
 if not ni then break end  
 local text = string.sub(s, i, ni-1)  
 if not string.find(text, "^%s\*$") then  
 table.insert(top, text)  
 end  
 if empty == "/" then -- empty element tag  
 table.insert(top, {label=label, xarg=parseargs(xarg), empty=1})  
 elseif c == "" then -- start tag  
 top = {label=label, xarg=parseargs(xarg)}  
 table.insert(stack, top) -- new level  
 else -- end tag  
 local toclose = table.remove(stack) -- remove top  
 top = stack[#stack]  
 if #stack \< 1 then  
 error("nothing to close with "..label)  
 end  
 if toclose.label ~= label then  
 error("trying to close "..toclose.label.." with "..label)  
 end  
 table.insert(top, toclose)  
 end  
 i = j+1  
 end  
 local text = string.sub(s, i)  
 if not string.find(text, "^%s\*$") then  
 table.insert(stack[#stack], text)  
 end  
 if #stack \> 1 then  
 error("unclosed "..stack[stack.n].label)  
 end  
 return stack[1]  
end  
  
b = http.request( "http://weather.yahooapis.com/forecastrss?p=94089") -- **blah blah use your own url**   
  
x = collect(b); **-- parse xml**   
  
print (x);   
local function printTable( t, label, level )  
 if label then print( label ) end  
 level = level or 1  
  
 if t then  
 for k,v in pairs( t ) do  
 local prefix = ""  
 for i=1,level do  
 prefix = prefix .. "\t"  
 end  
  
 print( prefix .. "[" .. tostring(k) .. "] = " .. tostring(v) )  
 if type( v ) == "table" then  
 print( prefix .. "{" )  
 printTable( v, nil, level + 1 )  
 print( prefix .. "}" )  
 end  
 end  
 end  
end  
  
 printTable(x,nil,3);  

[import]uid: 24 topic_id: 375 reply_id: 681[/import]

I can share one very simple way, which I used to read XML yesterday, but there may be a better way.
I parse the XML string using string.match (though I considered using a combo of string.find and string.sub which involves finding the position of a string and using it to parse out the substring)

The following is an XML string (mine is read in from the file system):

<data>
<background id=‘15’/>
<widget id=‘4’/>
</data>

If the string above is a variable called xmlstring then you can grab the id attributes of background and clock with:

local background_id = string.match(xmlstring,"%d",string.find(contents,’<background’))
local widget_id = string.match(xmlstring,"%d",string.find(contents,’<widget’))

The two lines above will grab the first number (%d) following the strings specified (eg. ‘<background’).
background_id should return 15.

For anything more complex you might want to look at some of the Lua libraries from luaforge:

http://luaforge.net/search/?type_of_search=soft&words=xml&Search=Search

I haven’t tried it, but etree Lua library (linked above) makes it look relatively simple dumping XML into a table.

[import]uid: 4418 topic_id: 375 reply_id: 680[/import]

Carlos

That seems to work nicely. How would I pick out particular elements of the xml file, I’d assumed it’s to do with the values passed in printTable( t, label, level ) but this function seems to print the whole file.

Cheers

Gary [import]uid: 4523 topic_id: 375 reply_id: 1286[/import]

Hey, is there a way to skip searching and parsing any data within CDATA tags?

Thanks!

Edit:
Nevermind, edited it myself, seems to work, I’m sure it’s not done very well but if anyone needs it I can post it up. [import]uid: 5708 topic_id: 375 reply_id: 1311[/import]

great, if you can share that would be awesome.

carlos [import]uid: 24 topic_id: 375 reply_id: 1314[/import]

function parseargs(s)
local arg = {}
string.gsub(s, “(%w+)=([”’])(.-)%2", function (w, _, a)
arg[w] = a
end)
return arg
end

function collect(s)

local stack = {}
local top = {}
table.insert(stack, top)
local ni,c,label,xarg, empty
local i, j = 1, 1

local skip = false
local skipvalue
local skipstr

while true do
ni,j,c,label,xarg, empty = string.find(s, “”, i)
if not ni then break end
local text = string.sub(s, i, ni-1)
if string.sub(text,0,9) == “<![CDATA[” then
skip = true
skipvalue = i + string.len(text)
–get start skip value
elseif string.sub(text,-3) == “]]>” then
skipstr = string.sub(s, skipvalue, i-1)
table.insert(top, skipstr)
text=""
skip = false
–get end skip value
end
if not skip == true then
if not string.find(text, “^%s*$”) then
table.insert(top, text)
end
if empty == “/” then – empty element tag
table.insert(top, {label=label, xarg=parseargs(xarg), empty=1})
elseif c == “” then – start tag
top = {label=label, xarg=parseargs(xarg)}
table.insert(stack, top) – new level
else – end tag
local toclose = table.remove(stack) – remove top
top = stack[#stack]
if #stack < 1 then
error("nothing to close with "…label)
end
if toclose.label ~= label then
error("trying to close “…toclose.label…” with "…label)
end
table.insert(top, toclose)
end
end
i = j+1
end
local text = string.sub(s, i)
if not string.find(text, “^%s*$”) then
table.insert(stack[#stack], text)
end
if #stack > 1 then
error("unclosed "…stack[stack.n].label)
end
return stack[1]
end
I just added a small skip function, so if CDATA was found then it stops adding stuff until the closing tag of that is found, then it adds all the data inbetween the two areas into a table, I found a html parser which stripped out all the html code from that which made it appear as plain text from that.

I’m not sure how well that is done, I primarily work in Actionscript, only started on lua yesterday pretty much. [import]uid: 5708 topic_id: 375 reply_id: 1325[/import]