libxml and serialization

BlitzMax Modules Forums/Brucey's Modules/libxml and serialization

Is there an example for reading xml files that use serialization?

I'm going to read rss feeds, if anyone has experience doing that I'm looking for an example on that too.

example of rss 2.0 feed

taken from www.hulu.com/feed/show/60/episodes
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/">
  <channel>
    <atom:link type="application/rss+xml" rel="self" href="http://www.hulu.com/feed/show/60/episodes"/>
    <title>Hulu - Episodes for Life</title>
    <link>http://www.hulu.com/feed</link>
    <description>Hulu - Episodes for Life</description>
    <pubDate>Thu, 13 Mar 2008 19:26:44 -0000</pubDate>
    <item>
      <title>Life: Pilot (s1e1)</title>
      <guid isPermaLink="true">http://www.hulu.com/watch/6671/life-pilot</guid>
      <link>http://www.hulu.com/watch/6671/life-pilot</link>
      <description>
        <![CDATA[<img src="http://thumbnails.hulu.com/4/95/3242972_cropped_145x80.jpg" align="right" width="145" height="80" /><p>After serving 12 hard years for a crime he didn't commit, Detective Charlie Crews is back on the LAPD with a new partner and a new zen attitude.</p><p>Added: October 03, 2007<br/>Duration: 43:19<br/>Rating: 4.2 / 5.0<br/></p>]]>
      </description>
      <pubDate>Wed, 03 Oct 2007 05:20:23 -0000</pubDate>
      <media:thumbnail width="145" height="80" url="http://thumbnails.hulu.com/4/95/3242972_cropped_145x80.jpg"/>
      <media:credit>NBC</media:credit>
    </item>
    <item>
      <title>Life: Tear Asunder (s1e2)</title>
      <guid isPermaLink="true">http://www.hulu.com/watch/6681/life-tear-asunder</guid>
      <link>http://www.hulu.com/watch/6681/life-tear-asunder</link>
      <description>
        <![CDATA[<img src="http://thumbnails.hulu.com/4/188/nbc_lif_eps_102_20071003_mezzn_145x80.jpg" align="right" width="145" height="80" /><p>Crews and Reese investigate a bride's murder. Crews realizes that a child may have witnessed the murders for which he was convicted.</p><p>Added: October 04, 2007<br/>Duration: 43:01<br/>Rating: 4.1 / 5.0<br/></p>]]>
      </description>
      <pubDate>Thu, 04 Oct 2007 22:30:30 -0000</pubDate>
      <media:thumbnail width="145" height="80" url="http://thumbnails.hulu.com/4/188/nbc_lif_eps_102_20071003_mezzn_145x80.jpg"/>
      <media:credit>NBC</media:credit>
    </item>
    <item>
      <title>Life: Let Her Go (s1e3)</title>
      <guid isPermaLink="true">http://www.hulu.com/watch/6665/life-let-her-go</guid>
      <link>http://www.hulu.com/watch/6665/life-let-her-go</link>
      <description>
        <![CDATA[<img src="http://thumbnails.hulu.com/4/556/nbc_lff_eps_103_20071010_mezzn_145x80.jpg" align="right" width="145" height="80" /><p>An upscale family man is suspected of killing his wife, and Crews sees his ex-wife for the first time since getting out of jail.</p><p>Added: October 11, 2007<br/>Duration: 42:53<br/>Rating: 4.1 / 5.0<br/></p>]]>
      </description>
      <pubDate>Thu, 11 Oct 2007 04:50:58 -0000</pubDate>
      <media:thumbnail width="145" height="80" url="http://thumbnails.hulu.com/4/556/nbc_lff_eps_103_20071010_mezzn_145x80.jpg"/>
      <media:credit>NBC</media:credit>
    </item>
    <item>
      <title>Life: What They Saw (s1e4)</title>
      <guid isPermaLink="true">http://www.hulu.com/watch/6662/life-what-they-saw</guid>
      <link>http://www.hulu.com/watch/6662/life-what-they-saw</link>
      <description>
        <![CDATA[<img src="http://thumbnails.hulu.com/4/704/nbc_lff_eps_104_20071017_mezzn_145x80.jpg" align="right" width="145" height="80" /><p>When a wealthy man is found murdered in his bed, Crews befriends the only suspect, a homeless thief camping outside the estate.</p><p>Added: October 17, 2007<br/>Duration: 44:03<br/>Rating: 4.3 / 5.0<br/></p>]]>
      </description>
      <pubDate>Wed, 17 Oct 2007 20:50:35 -0000</pubDate>
      <media:thumbnail width="145" height="80" url="http://thumbnails.hulu.com/4/704/nbc_lff_eps_104_20071017_mezzn_145x80.jpg"/>
      <media:credit>NBC</media:credit>
    </item>
    <item>
      <title>Life: The Fallen Woman (s1e5)</title>
      <guid isPermaLink="true">http://www.hulu.com/watch/6661/life-the-fallen-woman</guid>
      <link>http://www.hulu.com/watch/6661/life-the-fallen-woman</link>
      <description>
        <![CDATA[<img src="http://thumbnails.hulu.com/4/976/nbc_lff_eps_105_20071024_mezzn_145x80.jpg" align="right" width="145" height="80" /><p>When an angel falls from the sky, Crews and Reese's murder investigation leads to a slippery Russian gangster.</p><p>Added: October 25, 2007<br/>Duration: 43:08<br/>Rating: 3.9 / 5.0<br/></p>]]>
      </description>
      <pubDate>Thu, 25 Oct 2007 02:40:59 -0000</pubDate>
      <media:thumbnail width="145" height="80" url="http://thumbnails.hulu.com/4/976/nbc_lff_eps_105_20071024_mezzn_145x80.jpg"/>
      <media:credit>NBC</media:credit>
    </item>
    <item>
      <title>Life: Powerless (s1e6)</title>
      <guid isPermaLink="true">http://www.hulu.com/watch/6670/life-powerless</guid>
      <link>http://www.hulu.com/watch/6670/life-powerless</link>
      <description>
        <![CDATA[<img src="http://thumbnails.hulu.com/5/111/nbc_lff_eps_106_20071031_mezzn_145x80.jpg" align="right" width="145" height="80" /><p>Dani comes across a rapist at her AA meeting.</p><p>Added: November 01, 2007<br/>Duration: 43:24<br/>Rating: 4.0 / 5.0<br/></p>]]>
      </description>
      <pubDate>Thu, 01 Nov 2007 16:20:50 -0000</pubDate>
      <media:thumbnail width="145" height="80" url="http://thumbnails.hulu.com/5/111/nbc_lff_eps_106_20071031_mezzn_145x80.jpg"/>
      <media:credit>NBC</media:credit>
    </item>
    <item>
      <title>Life: A Civil War (s1e7)</title>
      <guid isPermaLink="true">http://www.hulu.com/watch/6684/life-a-civil-war</guid>
      <link>http://www.hulu.com/watch/6684/life-a-civil-war</link>
      <description>
        <![CDATA[<img src="http://thumbnails.hulu.com/5/204/nbc_lff_eps_107_20071107_mezzn_145x80.jpg" align="right" width="145" height="80" /><p>The murder of two Iranian American students sparks racial unrest as Crews and Reese race to rescue their kidnapped friend.</p><p>Added: November 08, 2007<br/>Duration: 43:12<br/>Rating: 4.2 / 5.0<br/></p>]]>
      </description>
      <pubDate>Thu, 08 Nov 2007 00:21:06 -0000</pubDate>
      <media:thumbnail width="145" height="80" url="http://thumbnails.hulu.com/5/204/nbc_lff_eps_107_20071107_mezzn_145x80.jpg"/>
      <media:credit>NBC</media:credit>
    </item>
    <item>
      <title>Life: Farthingale (s1e8)</title>
      <guid isPermaLink="true">http://www.hulu.com/watch/6685/life-farthingale</guid>
      <link>http://www.hulu.com/watch/6685/life-farthingale</link>
      <description>
        <![CDATA[<img src="http://thumbnails.hulu.com/5/412/nbc_lff_eps_108_20071114_mezzn_145x80.jpg" align="right" width="145" height="80" /><p>While investigating the murder of a bigomist, Crews is suspected for the murder of policeman Ames.</p><p>Added: November 14, 2007<br/>Duration: 43:05<br/>Rating: 4.2 / 5.0<br/></p>]]>
      </description>
      <pubDate>Wed, 14 Nov 2007 21:11:13 -0000</pubDate>
      <media:thumbnail width="145" height="80" url="http://thumbnails.hulu.com/5/412/nbc_lff_eps_108_20071114_mezzn_145x80.jpg"/>
      <media:credit>NBC</media:credit>
    </item>
    <item>
      <title>Life: Serious Control Issues (s1e9)</title>
      <guid isPermaLink="true">http://www.hulu.com/watch/6674/life-serious-control-issues</guid>
      <link>http://www.hulu.com/watch/6674/life-serious-control-issues</link>
      <description>
        <![CDATA[<img src="http://thumbnails.hulu.com/5/662/nbc_lff_eps_109_20071127_mezzn_145x80.jpg" align="right" width="145" height="80" /><p>While investigating the case of a murdered homeless girl, Reese and Crews stumble across a child who was kidnapped when he was three.</p><p>Added: November 28, 2007<br/>Duration: 44:04<br/>Rating: 4.2 / 5.0<br/></p>]]>
      </description>
      <pubDate>Wed, 28 Nov 2007 22:40:42 -0000</pubDate>
      <media:thumbnail width="145" height="80" url="http://thumbnails.hulu.com/5/662/nbc_lff_eps_109_20071127_mezzn_145x80.jpg"/>
      <media:credit>NBC</media:credit>
    </item>
    <item>
      <title>Life: Dig A Hole (s1e10)</title>
      <guid isPermaLink="true">http://www.hulu.com/watch/6687/life-dig-a-hole</guid>
      <link>http://www.hulu.com/watch/6687/life-dig-a-hole</link>
      <description>
        <![CDATA[<img src="http://thumbnails.hulu.com/5/729/4939851_cropped145x80.jpg" align="right" width="145" height="80" /><p>Charlie and Dani track the killer of a Zen Master who was buried alive ten years prior.</p><p>Added: December 04, 2007<br/>Duration: 43:37<br/>Rating: 4.1 / 5.0<br/></p>]]>
      </description>
      <pubDate>Tue, 04 Dec 2007 03:00:46 -0000</pubDate>
      <media:thumbnail width="145" height="80" url="http://thumbnails.hulu.com/5/729/4939851_cropped145x80.jpg"/>
      <media:credit>NBC</media:credit>
    </item>
    <item>
      <title>Life: Fill It Up (s1e11)</title>
      <guid isPermaLink="true">http://www.hulu.com/watch/6691/life-fill-it-up</guid>
      <link>http://www.hulu.com/watch/6691/life-fill-it-up</link>
      <description>
        <![CDATA[<img src="http://thumbnails.hulu.com/5/755/nbc_lff_eps_111_20071205_mezzn_145x80.jpg" align="right" width="145" height="80" /><p>Hoping to take down Jack Reese, Crews finds the Seybolts' murderer, but doesn't succeed in proving who set him up.</p><p>Added: December 06, 2007<br/>Duration: 43:20<br/>Rating: 4.2 / 5.0<br/></p>]]>
      </description>
      <pubDate>Thu, 06 Dec 2007 03:40:49 -0000</pubDate>
      <media:thumbnail width="145" height="80" url="http://thumbnails.hulu.com/5/755/nbc_lff_eps_111_20071205_mezzn_145x80.jpg"/>
      <media:credit>NBC</media:credit>
    </item>
  </channel>
</rss>


what is "<![CDATA[]]>"?

A CDATA section is Character Data that is not parsed in the same way as the rest of the document.
It means, characters that are normally not allowed in XML (like < and > for example) can appear in the CDATA section.

Assuming RSS feeds use the same structure, I'd start by creating an object that matches that structure.

Then write a little parser which maps the xml onto your object.

say you have a String containing the feed :
Local doc:TxmlDoc = TxmlDoc.parseDoc(text)
Local root:TxmlNode = doc.GetRootElement()

you might then pass the root node into a method of your mapper...
Method map:RSSObject(root:TxmlNode)
  Local channel:TxmlNode = TxmlNode(root.GetFirstChild())

  Local rss:RSSObject = new RSSObject

  For Local part:TxmlNode = eachin channel.getChildren()

    select part.GetName()

      case "title"
         rss.SetTitle(part.GetContent())


      case "item"
         mapItem(rss, part)

    end select

  Next

  return rss
End Method

Method mapItem(rss:RSSObject, parent:TxmlNode)

... etc

  rss.AddItem(item)

End Method



or something like that.

Thanks Brucey!

this is a working rss feed reader example, it has an error on closing, but it works :)
SuperStrict

Framework wx.wxApp
Import wx.wxFrame
Import wx.wxListCtrl
Import wx.wxButton
Import wx.wxPanel
Import wx.wxTextCtrl
Import wx.wxSystemSettings

Import brl.basic
Import brl.blitz
Import brl.retro
Import BaH.libxml

Type rssChannel
  Global _list:TList = New TList
	
	'channel information
	Field Title:String			'title of channel
	Field Description:String	'description of channel
	Field Pubdate:String		'date channel was created?/updated?
	'channel links
	Field lk_Feed:String		'link to the channel's rss feed
	Field lk_Link:String		'link to main feed site
	
	Field chnItems:TList
		
		Method New() 
			chnItems = New TList
		   _list.AddLast(Self) 
			
		End Method
		
		Method SetTitle(_Title:String) 
			Title = _Title
			
		End Method
		
		Method SetDescription(_Desc:String) 
			Description = _Desc
		
		End Method
		
		'fix incoming date for appended timezone data (ex. Thu, 13 Mar 2008 19:26:44 >-0000<)
		Method SetPubdate(pubdateraw:String) 
			Pubdate = pubdateraw
			
		End Method
		
		Method SetLink(Link:String, which:Int) 
		 
			Select which
				Case 0
					lk_Feed = Link
					
				Case 1
					lk_Link = Link
					
			End Select
			
		End Method
		
		Method ReadChannel(root:TxmlNode) 
		  Local channel:TxmlNode = TxmlNode(root.GetFirstChild()) 
		
		   If chnItems.Count() > 0 Then Clear() 
		  
			For Local part:TxmlNode = EachIn channel.getChildren()
			
				Select Lower(part.GetName()) 
				
					Case "title"
						SetTitle(part.getContent()) 
						
					Case "description"
						SetDescription(part.getContent()) 
						
					Case "pubdate"
						SetPubdate(part.getContent()) 
						
					Case "link"
						SetLink(part.getContent(), 1) 
						
					Case "item"
						ReadItem(part) 
						
					Default
						DebugLog("rchn noparse: ~q" + part.getName() + "~q") 
						DebugLog("~t" + part.getName() + " :: " + part.getContent()) 
						
				End Select
			
			Next
		
		End Method
		
		Method ReadItem(parent:TxmlNode) 
		  Local ritem:rssItem = New rssItem
			
			For Local part:TxmlNode = EachIn parent.getChildren() 
			
				Select Lower(part.GetName()) 
				
					Case "title"
						ritem.SetTitle(part.getContent()) 
						
					Case "description"
						ritem.SetDescription(part.getContent()) 
						
					Case "pubdate"
						ritem.SetPubdate(part.getContent()) 
						
					Case "link"
						ritem.SetLink(part.getContent()) 
						
				End Select
			
			Next
			
		   chnItems.AddLast(ritem) 
		   
		End Method
		
		Method Clear() 
		  Local ritem:rssItem
		  
			For ritem = EachIn chnItems
				
				ritem.Clear(Self) 
				
			Next
			
			Title = Null ; Pubdate = Null
			Description = Null
			lk_Feed = Null ; lk_Link = Null
			
		End Method
		
End Type

Type rssItem
	'item information
	Field Title:String			'title of item
	Field Description:String	'description of item
	Field Pubdate:String		'date event occured
	'item links
	Field lk_Link:String		'referring link to event
	
		Method SetTitle(_Title:String) 
			Title = _Title
			
		End Method
		
		Method SetDescription(_Desc:String) 
			Description = _Desc
		
		End Method
		
		'fix incoming date for appended timezone data (Thu, 13 Mar 2008 19:26:44 >-0000<)
		Method SetPubdate(pubdateraw:String) 
			Pubdate = pubdateraw
			
		End Method
		
		Method SetLink(Link:String) 
			lk_Link = Link
			
		End Method
		
		Method Clear(channel:rssChannel) 
			Title = Null
			Description = Null
			Pubdate = Null
			lk_link = Null
			
		  channel.chnItems.Remove(Self) 
		End Method
		
		
		Function Create:rssItem(Title:String, Desc:String, Pubdate:String, lk_Link:String) 
		  Local ritem:rssItem = New rssItem
			
			ritem.Title = Title
			ritem.Description = Desc
			ritem.SetPubdate(Pubdate) 
			ritem.lk_Link = lk_Link
			
		   Return ritem
		   
		End Function
		
End Type

Type Thttp
	Field sock:TSocket
	Field stream:TStream
	Field host:String
	Field agent:String = "BlitzHTTP/1.0"
	Field autoClose:Int
	
		Method Open:Int(host:String, autoClose:Int = False) 
		  Self.sock = CreateTCPSocket()
			 
			If ConnectSocket(Self.sock, HostIp(host), 80) 
				Self.host = host
				Self.stream = CreateSocketStream(Self.sock) 
				Self.autoClose = autoClose
			   Return True
				
			Else
			   Return False
				
			End If
			
		End Method
		
		Method Get:HTTPReturnData(get:String = "") 'def get = ""
		  Local HTRD:HTTPReturnData = New HTTPReturnData, buffer:String, rlnewline:String
			
		   'WriteLine(stream, "GET /" + get + " HTTP/1.0~nHost: " + Self.host + "~nUser-Agent: " + Self.agent + "~n~n") 
		   WriteLine stream, "GET /" + get + " HTTP/1.0" ' GET / gets Default page
		   WriteLine stream, "Host: " + Self.host
		   WriteLine stream, "User-Agent: " + Self.agent
		   WriteLine stream, "Accept: */*"
		   WriteLine stream, ""
		
		  Local cExtType:String, cExt:String, cLength:Int
		   ReadLine(stream)
			While Not Eof(stream)
			  rlnewline = ReadLine(stream)
			  Local spos:Int = Instr(rlnewline, ":")
			'Print "rln" + Lower(Left(rlnewline, spos - 1)) + "rln"
				Select Lower(Left(rlnewline, spos - 1))
					Case "content-type"
					  Local prtmp:String = Mid(rlnewline, spos + 2, Instr(rlnewline, ";") - spos - 2), slpos:Int = Instr(prtmp, "/")
					  cExtType = Left(prtmp, slpos - 1) cExt = Right(prtmp, prtmp.Length - slpos)
						
					Case "content-length"
						cLength = Int(Right(rlnewline, rlnewline.Length - spos - 1))
						
					Case ""
					   Exit
						
				End Select
				
			Wend
			
			While Not Eof(stream) 
			  rlnewline = ReadLine(stream)
				
				buffer:+ rlnewline + "~n"
				
			Wend
			
		  HTRD.Set(Left(buffer, buffer.Length - 1), cExtType, cExt, cLength)
			
		   If autoClose Close() 
		   
		   Return HTRD
		 
			
		End Method
		
		Method Post:String(page:String = "", keys:String[] , values:String[] ) 
		  Local buffer:String
		  Local data:String
		  Local i:Int
			
			For i = 0 To keys.Length - 1
				data:+ UrlEncode(keys[i] ) + "=" + UrlEncode(values[i] ) + "&"
				
			Next
			
		  data = Left(data, data.Length - 1) 
			WriteLine(stream, "POST /" + page + " HTTP/1.0~nHost: " + Self.host + "~nUser-Agent: " + Self.agent + "~nContent-Length: " + data.Length + "~nContent-Type: application/x-www-form-urlencoded~n~n" + data) 
			
			While Not Eof(stream) 
				buffer:+ReadLine(stream) + "~n"
				
			Wend
			
		 If autoClose Close() 
		
		   Return Left(buffer, buffer.Length - 1) 
			
		End Method
		
		Method Close() 
			If Self.stream CloseStream(Self.stream) 
			If Self.sock CloseSocket(Self.sock) 
			
		End Method
	
		Function UrlEncode:String(url:String) 
		  Local buffer:String
		  Local Char:Int
		  Local i:Int
			
			For i = 1 To url.Length
			  Char = Asc(Mid(url, i, 1)) 
				
				If(Char >= 48 And Char <= 57) Or (Char >= 65 And Char <= 90) Or (Char >= 97 And Char <= 122) Or Char = 43 Or Char = 45 Or Char = 46 Or Char = 95
					buffer = buffer + Chr(Char) 
					
				Else
					buffer = buffer + "%" + Right(Hex(Char), 2) 
					
				End If
				
			Next
			
		   Return buffer
		
		End Function
		
		Function UrlDecode:String(url:String) 
		  Local sHex:String = "0123456789ABCDEF"
		  Local buffer:String
		  Local i:Int
			
			For i = 1 To url.Length
				If Mid(url, i, 1) = "%"
					buffer = buffer + Chr(Instr(sHex, Mid(url, i + 1, 1)) Shl 4 + Instr(sHex, Mid(url, i + 2, 1)) - 17) 
				   i:+ 2
					
				Else
					buffer = buffer + Mid(url, i, 1)
					 
				End If
				
			Next
			
		   Return buffer
		
		End Function
	
End Type

Type HTTPReturnData
	Field Content:String
	Field ContLength:Int
	
	Field ExtensionType:String
	Field Extension:String		
		
		Method Set(Cont:String, ExtType:String, Ext:String, CLen:Int)
			Content = Cont
			ContLength = CLen
			Extension = Ext
			ExtensionType = ExtType
			
		End Method
		
		Method SaveContent(File:String, useExt:Int = False)
		 
		 If useExt File:+ "." + Extension
			
			SaveText(Content, File)
			
		End Method
		
		Method ToString:String()
			Return "Content-Type: " + ExtensionType + "/" + Extension + "~nContent-Length: " + ContLength
			
		End Method
		
End Type
	
New MyApp.Run() 

End

Type MyApp Extends wxApp
	Field testframe:MyFrame
	
		Method OnInit:Int() 
			testframe = MyFrame(New MyFrame.Create(Null, - 1, "rss Channel reader", - 1, - 1, 575, 390, wxMINIMIZE_BOX | wxMAXIMIZE_BOX | wxCLOSE_BOX | wxSYSTEM_MENU | wxCAPTION | wxCLIP_CHILDREN)) 
				testframe.Show() 
				
		   Return True
		End Method
		
End Type

Type MyFrame Extends wxFrame
	Field ctrpanel:wxPanel
	
	Field TCtr_rssfeedurl:wxTextCtrl

	Field LCtr_ChannelItems:wxListCtrl
	Field TCtr_rssItemInfo:wxTextCtrl
	
	Field rchan:rssChannel
	
		Method OnInit() 
		   ctrpanel = New wxPanel.Create(Self) 
			rchan = New rssChannel
			
			TCtr_rssfeedurl = New wxTextCtrl.Create(ctrpanel, idTCtr_rssfeedurl, "www.hulu.com/feed/show/60/episodes", 5, 10, 200, 20, wxTE_PROCESS_ENTER) 
			New wxButton.Create(ctrpanel, idbtnrefresh, "Refresh", 210, 10, 64, 24) 
			
			LCtr_ChannelItems = wxListCtrl(New wxListCtrl.Create(ctrpanel, idLCtr_ChannelItems, 5, 55, 200, 300, wxLC_LIST | wxLC_REPORT | wxLC_SINGLE_SEL | wxSUNKEN_BORDER)) 
				'LCtr_ChannelItems.InsertColumn(0, "rss items") 
			TCtr_rssItemInfo = New wxTextCtrl.Create(ctrpanel, idTCtr_rssItemInfo, "", 210, 55, 350, 300, wxTE_MULTILINE) 
			
			RefreshChannel() 
			
			'connect events
			Connect(idbtnrefresh, wxEVT_COMMAND_BUTTON_CLICKED, OnRefreshChannel) 
			Connect(idTCtr_rssfeedurl, wxEVT_COMMAND_TEXT_ENTER, OnRefreshChannel) 
			
			Connect(idLCtr_ChannelItems, wxEVT_COMMAND_LIST_ITEM_SELECTED, OnSelected) 
			
			ConnectAny(wxEVT_CLOSE_WINDOW, OnQuit) 
			
		   Centre() 
		   
		End Method
		
		Method RefreshChannel() 
		  Local feedurl:String = TCtr_rssfeedurl.GetLineText(0) 
		   
		   If Left(feedurl, 7) = "http://" Then feedurl = Right(feedurl, feedurl.Length - 7) 
		   
		  Local firstsl:Int = Instr(feedurl, "/"), sitename:String = Left(feedurl, firstsl - 1), getfile:String = Right(feedurl, feedurl.Length - firstsl) 
		  Local httpg:Thttp = New Thttp, htrd:HTTPReturnData
			If httpg.Open(sitename) 
			  Local doc:TxmlDoc, root:TxmlNode
				rchan.Clear() 
				htrd = httpg.Get(getfile) 
				
				doc = TxmlDoc.parseDoc(htrd.Content) 
				root = doc.GetRootElement() 
				
				rchan.ReadChannel(root) 
					rchan.lk_Feed = "www.hulu.com/feed/show/60/episodes"
					
				LCtr_ChannelItems.ClearAll() 
				
			  Local ritem:rssItem
				For ritem = EachIn rchan.chnItems
				  Local wxl:wxListItem = New wxListItem.Create() 
					wxl.SetData(ritem) wxl.SetText(ritem.Title) 
					LCtr_ChannelItems.InsertItem(wxl) 
					
				Next
				rssLoadInfo(ritem) 
			Else
				wxMessageBox("error: can't obtain url, sitename: ~q" + sitename + "~q getfile: ~q" + getfile + "~q") 
				
			End If
			
		End Method
		
		Function OnRefreshChannel(evt:wxEvent) 
		  Local mfr:MyFrame = MyFrame(evt.parent) 
			mfr.RefreshChannel() 
			
		End Function
		
		Function OnSelected(evt:wxEvent) 
		  Local mfr:MyFrame = MyFrame(evt.parent) 
		  Local lst:wxListCtrl = mfr.LCtr_ChannelItems
		  
			 mfr.rssLoadInfo(rssItem(wxListEvent(evt).GetItem().GetData())) 
			
		End Function
		
		Method rssLoadInfo(item:rssItem)    'load rssitem info into a browser area | currently a textctrl
		   tctr_rssItemInfo.Clear() 
			tctr_rssItemInfo.AppendText(item.Title + " date: " + item.Pubdate + "~n") 
			tctr_rssItemInfo.AppendText(item.lk_Link + "~n" + item.Description) 
			
		End Method
		
		Function OnQuit(event:wxEvent) 
			wxWindow(event.parent).Close(True) 
			
		End Function
	
End Type
'id's
Const idTCtr_rssfeedurl:Int = 101
Const idbtnrefresh:Int = 102
	
Const idLCtr_ChannelItems:Int = 103
Const idTCtr_rssItemInfo:Int = 104


Nice :-)

Just a couple of tweaks to make it happy to run on Mac :

You need to remove wxLC_REPORT from the LCtr_ChannelItems create. Since you already have wxLC_LIST.

You shouldn't connect to wxEVT_CLOSE_WINDOW and then in the event handler called Window.Close(). Either, don't connect at all (it will automagically quit the app when the last window is closed), or instead call Window.Destroy().

:o)

Try using this as the rss feed: http://www.nytimes.com/services/xml/rss/nyt/Technology.xml

Is there a way it can be a normal listbox (going down, instead of going on to the right)?

EDIT: wxHtmlWindow updated version, includes another problem, when displaying the description the image does not show, however in firefox (opening the "test.html" file) shows everything correctly.
SuperStrict

Framework wx.wxApp
Import wx.wxFrame
Import wx.wxListCtrl
Import wx.wxButton
Import wx.wxPanel
Import wx.wxTextCtrl
Import wx.wxHtmlWindow
Import wx.wxSystemSettings

Import brl.basic
Import brl.blitz
Import brl.retro
Import brl.system

Import BaH.libxml

Type rssChannel
  Global _list:TList = New TList
	
	'channel information
	Field Title:String			'title of channel
	Field Description:String	'description of channel
	Field Pubdate:String		'date channel was created?/updated?
	'channel links
	Field lk_Feed:String		'link to the channel's rss feed
	Field lk_Link:String		'link to main feed site
	
	Field chnItems:TList
		
		Method New() 
			chnItems = New TList
		   _list.AddLast(Self) 
			
		End Method
		
		Method SetTitle(_Title:String) 
			Title = _Title
			
		End Method
		
		Method SetDescription(_Desc:String) 
			Description = _Desc
		
		End Method
		
		'fix incoming date for appended timezone data (ex. Thu, 13 Mar 2008 19:26:44 >-0000<)
		Method SetPubdate(pubdateraw:String) 
			Pubdate = pubdateraw
			
		End Method
		
		Method SetLink(Link:String, which:Int) 
		 
			Select which
				Case 0
					lk_Feed = Link
					
				Case 1
					lk_Link = Link
					
			End Select
			
		End Method
		
		Method ReadChannel(root:TxmlNode) 
		  Local channel:TxmlNode = TxmlNode(root.GetFirstChild()) 
		
		   If chnItems.Count() > 0 Then Clear() 
		  
			For Local part:TxmlNode = EachIn channel.getChildren()
			
				Select Lower(part.GetName()) 
				
					Case "title"
						SetTitle(part.getContent()) 
						
					Case "description"
						SetDescription(part.getContent()) 
						
					Case "pubdate"
						SetPubdate(part.getContent()) 
						
					Case "link"
						SetLink(part.getContent(), 1) 
						
					Case "item"
						ReadItem(part) 
						
					Default
						DebugLog("rchn noparse: ~q" + part.getName() + "~q") 
						DebugLog("~t" + part.getName() + " :: " + part.getContent()) 
						
				End Select
			
			Next
		
		End Method
		
		Method ReadItem(parent:TxmlNode) 
		  Local ritem:rssItem = New rssItem
			
			For Local part:TxmlNode = EachIn parent.getChildren() 
			
				Select Lower(part.GetName()) 
				
					Case "title"
						ritem.SetTitle(part.getContent()) 
						
					Case "description"
						ritem.SetDescription(part.getContent()) 
						
					Case "pubdate"
						ritem.SetPubdate(part.getContent()) 
						
					Case "link"
						ritem.SetLink(part.getContent()) 
						
				End Select
			
			Next
			
		   chnItems.AddLast(ritem) 
		   
		End Method
		
		Method Clear() 
		  Local ritem:rssItem
		  
			For ritem = EachIn chnItems
				
				ritem.Clear(Self) 
				
			Next
			
			Title = Null ; Pubdate = Null
			Description = Null
			lk_Feed = Null ; lk_Link = Null
			
		End Method
		
End Type

Type rssItem
	'item information
	Field Title:String			'title of item
	Field Description:String	'description of item
	Field Pubdate:String		'date event occured
	'item links
	Field lk_Link:String		'referring link to event
	
		Method SetTitle(_Title:String) 
			Title = _Title
			
		End Method
		
		Method SetDescription(_Desc:String) 
			Description = _Desc
		
		End Method
		
		'fix incoming date for appended timezone data (Thu, 13 Mar 2008 19:26:44 >-0000<)
		Method SetPubdate(pubdateraw:String) 
			Pubdate = pubdateraw
			
		End Method
		
		Method SetLink(Link:String) 
			lk_Link = Link
			
		End Method
		
		Method Clear(channel:rssChannel) 
			Title = Null
			Description = Null
			Pubdate = Null
			lk_link = Null
			
		  channel.chnItems.Remove(Self) 
		End Method
		
		
		Function Create:rssItem(Title:String, Desc:String, Pubdate:String, lk_Link:String) 
		  Local ritem:rssItem = New rssItem
			
			ritem.Title = Title
			ritem.Description = Desc
			ritem.SetPubdate(Pubdate) 
			ritem.lk_Link = lk_Link
			
		   Return ritem
		   
		End Function
		
End Type

Type Thttp
	Field sock:TSocket
	Field stream:TStream
	Field host:String
	Field agent:String = "BlitzHTTP/1.0"
	Field autoClose:Int
	
		Method Open:Int(host:String, autoClose:Int = False) 
		  Self.sock = CreateTCPSocket()
			 
			If ConnectSocket(Self.sock, HostIp(host), 80) 
				Self.host = host
				Self.stream = CreateSocketStream(Self.sock) 
				Self.autoClose = autoClose
			   Return True
				
			Else
			   Return False
				
			End If
			
		End Method
		
		Method Get:HTTPReturnData(get:String = "") 'def get = ""
		  Local HTRD:HTTPReturnData = New HTTPReturnData, buffer:String, rlnewline:String
			
		   'WriteLine(stream, "GET /" + get + " HTTP/1.0~nHost: " + Self.host + "~nUser-Agent: " + Self.agent + "~n~n") 
		   WriteLine stream, "GET /" + get + " HTTP/1.0" ' GET / gets Default page
		   WriteLine stream, "Host: " + Self.host
		   WriteLine stream, "User-Agent: " + Self.agent
		   WriteLine stream, "Accept: */*"
		   WriteLine stream, ""
		
		  Local cExtType:String, cExt:String, cLength:Int
		   ReadLine(stream)
			While Not Eof(stream)
			  rlnewline = ReadLine(stream)
			  Local spos:Int = Instr(rlnewline, ":")
			'Print "rln" + Lower(Left(rlnewline, spos - 1)) + "rln"
				Select Lower(Left(rlnewline, spos - 1))
					Case "content-type"
					  Local prtmp:String = Mid(rlnewline, spos + 2, Instr(rlnewline, ";") - spos - 2), slpos:Int = Instr(prtmp, "/")
					  cExtType = Left(prtmp, slpos - 1) cExt = Right(prtmp, prtmp.Length - slpos)
						
					Case "content-length"
						cLength = Int(Right(rlnewline, rlnewline.Length - spos - 1))
						
					Case ""
					   Exit
						
				End Select
				
			Wend
			
			While Not Eof(stream) 
			  rlnewline = ReadLine(stream)
				
				buffer:+ rlnewline + "~n"
				
			Wend
			
		  HTRD.Set(Left(buffer, buffer.Length - 1), cExtType, cExt, cLength)
			
		   If autoClose Close() 
		   
		   Return HTRD
		 
			
		End Method
		
		Method Post:String(page:String = "", keys:String[] , values:String[] ) 
		  Local buffer:String
		  Local data:String
		  Local i:Int
			
			For i = 0 To keys.Length - 1
				data:+ UrlEncode(keys[i] ) + "=" + UrlEncode(values[i] ) + "&"
				
			Next
			
		  data = Left(data, data.Length - 1) 
			WriteLine(stream, "POST /" + page + " HTTP/1.0~nHost: " + Self.host + "~nUser-Agent: " + Self.agent + "~nContent-Length: " + data.Length + "~nContent-Type: application/x-www-form-urlencoded~n~n" + data) 
			
			While Not Eof(stream) 
				buffer:+ReadLine(stream) + "~n"
				
			Wend
			
		 If autoClose Close() 
		
		   Return Left(buffer, buffer.Length - 1) 
			
		End Method
		
		Method Close() 
			If Self.stream CloseStream(Self.stream) 
			If Self.sock CloseSocket(Self.sock) 
			
		End Method
	
		Function UrlEncode:String(url:String) 
		  Local buffer:String
		  Local Char:Int
		  Local i:Int
			
			For i = 1 To url.Length
			  Char = Asc(Mid(url, i, 1)) 
				
				If(Char >= 48 And Char <= 57) Or (Char >= 65 And Char <= 90) Or (Char >= 97 And Char <= 122) Or Char = 43 Or Char = 45 Or Char = 46 Or Char = 95
					buffer = buffer + Chr(Char) 
					
				Else
					buffer = buffer + "%" + Right(Hex(Char), 2) 
					
				End If
				
			Next
			
		   Return buffer
		
		End Function
		
		Function UrlDecode:String(url:String) 
		  Local sHex:String = "0123456789ABCDEF"
		  Local buffer:String
		  Local i:Int
			
			For i = 1 To url.Length
				If Mid(url, i, 1) = "%"
					buffer = buffer + Chr(Instr(sHex, Mid(url, i + 1, 1)) Shl 4 + Instr(sHex, Mid(url, i + 2, 1)) - 17) 
				   i:+ 2
					
				Else
					buffer = buffer + Mid(url, i, 1)
					 
				End If
				
			Next
			
		   Return buffer
		
		End Function
	
End Type

Type HTTPReturnData
	Field Content:String
	Field ContLength:Int
	
	Field ExtensionType:String
	Field Extension:String		
		
		Method Set(Cont:String, ExtType:String, Ext:String, CLen:Int)
			Content = Cont
			ContLength = CLen
			Extension = Ext
			ExtensionType = ExtType
			
		End Method
		
		Method SaveContent(File:String, useExt:Int = False)
		 
		 If useExt File:+ "." + Extension
			
			SaveText(Content, File)
			
		End Method
		
		Method ToString:String()
			Return "Content-Type: " + ExtensionType + "/" + Extension + "~nContent-Length: " + ContLength
			
		End Method
		
End Type
	
New MyApp.Run() 

End

Type MyApp Extends wxApp
	Field testframe:MyFrame
	
		Method OnInit:Int() 
			testframe = MyFrame(New MyFrame.Create(Null, - 1, "rss Channel reader", - 1, - 1, 575, 390, wxMINIMIZE_BOX | wxCLOSE_BOX | wxSYSTEM_MENU | wxCAPTION | wxCLIP_CHILDREN)) 
				testframe.Show() 
				
		   Return True
		End Method
		
End Type

Type MyFrame Extends wxFrame
	Field ctrpanel:wxPanel
	
	Field TCtr_rssfeedurl:wxTextCtrl

	Field LCtr_ChannelItems:wxListCtrl
	'Field TCtr_rssItemInfo:wxTextCtrl
	Field Htw_rssItemInfo:wxHtmlWindow
	
	Field rchan:rssChannel
	
		Method OnInit() 
		   ctrpanel = New wxPanel.Create(Self) 
			rchan = New rssChannel
			
			TCtr_rssfeedurl = New wxTextCtrl.Create(ctrpanel, idTCtr_rssfeedurl, "www.hulu.com/feed/show/60/episodes", 5, 17, 400, 20, wxTE_PROCESS_ENTER) 
			New wxButton.Create(ctrpanel, idbtnrefresh, "Refresh", 410, 16, 64, 22) 
			
			LCtr_ChannelItems = wxListCtrl(New wxListCtrl.Create(ctrpanel, idLCtr_ChannelItems, 5, 55, 200, 300, wxLC_LIST | wxLC_SINGLE_SEL | wxSUNKEN_BORDER)) 
				'LCtr_ChannelItems.InsertColumn(0, "rss items") 
			'TCtr_rssItemInfo = New wxTextCtrl.Create(ctrpanel, idTCtr_rssItemInfo, "", 210, 55, 350, 300, wxTE_MULTILINE) 
			Htw_rssItemInfo = New wxHtmlWindow.Create(ctrpanel, idHtw_rssItemInfo, 210, 55, 350, 300) 
				
			RefreshChannel() 
			
			'connect events
			Connect(idbtnrefresh, wxEVT_COMMAND_BUTTON_CLICKED, OnRefreshChannel) 
			Connect(idTCtr_rssfeedurl, wxEVT_COMMAND_TEXT_ENTER, OnRefreshChannel) 
			
			Connect(idLCtr_ChannelItems, wxEVT_COMMAND_LIST_ITEM_SELECTED, OnSelected) 
			Connect(idHtw_rssItemInfo, wxEVT_COMMAND_HTML_LINK_CLICKED, OnrssLink) 
			
			'ConnectAny(wxEVT_CLOSE_WINDOW, OnQuit) 
			
		   Centre() 
		   
		End Method
		
		Method RefreshChannel() 
		  Local feedurl:String = TCtr_rssfeedurl.GetLineText(0) 
		   
		   If Left(feedurl, 7) = "http://" Then feedurl = Right(feedurl, feedurl.Length - 7) 
		   
		  Local firstsl:Int = Instr(feedurl, "/"), sitename:String = Left(feedurl, firstsl - 1), getfile:String = Right(feedurl, feedurl.Length - firstsl) 
		  Local httpg:Thttp = New Thttp, htrd:HTTPReturnData
			If httpg.Open(sitename) 
			  Local doc:TxmlDoc, root:TxmlNode
				rchan.Clear() 
				htrd = httpg.Get(getfile) 
				
				doc = TxmlDoc.parseDoc(htrd.Content) 
				root = doc.GetRootElement() 
				
				rchan.ReadChannel(root) 
					rchan.lk_Feed = "www.hulu.com/feed/show/60/episodes"
					
				LCtr_ChannelItems.ClearAll() 
				
			  Local ritem:rssItem
				For ritem = EachIn rchan.chnItems
				  Local wxl:wxListItem = New wxListItem.Create() 
					wxl.SetData(ritem) wxl.SetText(ritem.Title) 
					LCtr_ChannelItems.InsertItem(wxl) 
					print ritem.Description
				Next
				
			   rssLoadInfo(ritem) 
				
			Else
				wxMessageBox("error: can't obtain url, sitename: ~q" + sitename + "~q getfile: ~q" + getfile + "~q") 
				
			End If
			
		End Method
		
		Function OnRefreshChannel(evt:wxEvent) 
		  Local mfr:MyFrame = MyFrame(evt.parent) 
			mfr.RefreshChannel() 
			
		End Function
		
		Function OnSelected(evt:wxEvent) 
		  Local mfr:MyFrame = MyFrame(evt.parent) 
		  Local lst:wxListCtrl = mfr.LCtr_ChannelItems
		  
			 mfr.rssLoadInfo(rssItem(wxListEvent(evt).GetItem().GetData())) 
			
		End Function
		
		Method rssLoadInfo(item:rssItem)    'load rssitem info into a browser area | currently a textctrl
		   'tctr_rssItemInfo.Clear() 
			'tctr_rssItemInfo.AppendText(item.Title + " date: " + item.Pubdate + "~n") 
			'tctr_rssItemInfo.AppendText(item.lk_Link + "~n" + item.Description)
		  Local pageCont:String = "<html><body>~r~n" + ..
		  		"<a href=~q" + item.lk_Link + "~q>" + item.Title + "</a>~r~n" + ..
				item.Description + ..
				"~r~n</body></html>"
				
			Htw_rssItemInfo.SetPage(pageCont) 
			SaveText(pageCont, "test.html") 
		
		End Method
		
		Function OnrssLink(evt:wxEvent) 
			OpenURL(wxHtmlLinkEvent(evt).GetLinkInfo().GetHref()) 
			
		End Function
		
		'Function OnQuit(event:wxEvent) 
		'	wxWindow(event.parent).Close(True) 
		'	
		'End Function
	
End Type
'id's
Const idTCtr_rssfeedurl:Int = 101
Const idbtnrefresh:Int = 102
	
Const idLCtr_ChannelItems:Int = 103
Const idTCtr_rssItemInfo:Int = 104
Const idHtw_rssItemInfo:Int = 105


Yes this data in the wrong column business vexed me as well. Never really found the solution. This (sort of) works.

[edited to add hscrollbar]

Oh, and you lose the first item, (it's in the invisible header) - so either dummy first item or create the header outside the for-next I guess.

LCtr_ChannelItems = wxListCtrl(New wxListCtrl.Create(ctrpanel, idLCtr_ChannelItems, 5, 55, 200, 300, wxLC_REPORT | wxHSCROLL | wxLC_NO_HEADER | wxLC_SINGLE_SEL | wxSUNKEN_BORDER)) 

Local row:Int
Local ritem:rssItem
For ritem = EachIn rchan.chnItems
  Local wxl:wxListItem = New wxListItem.Create() 
	wxl.SetData(ritem) wxl.SetText(ritem.Title) 
	wxl.SetId(row)
	wxl.SetColumn(0)
	
	If Not row
		LCtr_ChannelItems.InsertColumnItem(0,wxl) 
	Else
		LCtr_ChannelItems.InsertItem(wxl) 
	EndIf
	row :+ 1
	Print ritem.Description
Next
LCtr_ChannelItems.SetColumnWidth( 0, 400 )


This will show them all:
 Local row:Int
			  Local ritem:rssItem, wxl:wxListItem = New wxListItem.Create() 
				wxl.SetData(Null) wxl.SetText("") wxl.SetId(row) wxl.SetColumn(0) 
				LCtr_ChannelItems.InsertColumnItem(0, wxl) 
				
			  row:+1
				For ritem = EachIn rchan.chnItems
				  wxl:wxListItem = New wxListItem.Create() 
					wxl.SetData(ritem) wxl.SetText(ritem.Title) 
					wxl.SetId(row) wxl.SetColumn(0) 
					
					LCtr_ChannelItems.InsertItem(wxl) 
					row:+1
					
					Print ritem.Description
					
				Next


Or even
Local row:Int = 1
LCtr_ChannelItems.InsertColumnItem(0, New wxListItem.Create())

:-) No idea re that other problem though. I'm seeing an image in Leopard? I did read somewhere on the wxWidgets lists that wxHtmlWindow was considered a little flakey. Not what we want to hear I know.

I can't currently test it in Ubuntu, and I don't have a mac.