RSS-Leser
Programmet vårt skal abonnere på et antall RSS-filer. Vi lager en klasse "feedlist" for å administrere en slik liste med adresser til RSS-filer.
Hvert feed er beskrevet med en instans av klassen "feed". Den samme klassen brukes også til å ta vare på et Item (en nyhetsrefreanse).
feed
class feed : Object
{
protected String m_title;
protected String m_description;
protected Uri m_link;
protected XmlDocument m_xmldoc;
// constructor based on strings
public feed(string t, string u, string d)
{
title = t;
link = new Uri(u);
description = d;
}
// constructor based on feed-node from XML
public feed(XmlNode nod)
{
this.title = String.Empty;
this.link = null;
this.description = String.Empty;
if (nod.HasChildNodes)
foreach (XmlNode p in nod.ChildNodes)
if (p.GetType() == typeof(XmlElement))
{
if (p.LocalName.CompareTo("title") == 0)
this.title = p.InnerText;
if (p.LocalName.CompareTo("link") == 0)
this.link = new Uri(p.InnerText);
if (p.LocalName.CompareTo("description") == 0)
this.description = p.InnerText;
}
}
public string title
{
get { return m_title; }
set { m_title = value; }
}
public Uri link
{
get { return m_link; }
set { m_link = value; }
}
public string description {
get { return m_description; }
set { m_description = value; }
}
public XmlDocument xmldoc{
set { m_xmldoc = value; }
get {
// done already ?
if (m_xmldoc != null)
return m_xmldoc;
// get it
try
{
m_xmldoc = new XmlDocument();
m_xmldoc.Load(link.ToString());
return m_xmldoc;
}
catch (Exception ex)
{
return null;
}
}
}
// will need this as feeds appear in listboxes
public override string ToString(){return title;}
// prepare a feed-node as string
public String GetPacked()
{
return String.Format(@"
<title>{0}</title>
<link>{1}</link>
<description>{2}</description>",
title, link.ToString(), description);
}
}
feedlist
class feedlist:Object
{
// keep up a number of feeds, which sleeps on a file
private ArrayList FeedList;
private string filename;
public feedlist(String filename)
{
FeedList = new ArrayList();
this.filename = filename;
LoadFeeds();
// something to get started with if we have not loaded anything:
if (FeedList.Count == 0)
FeedList.Add(new feed(
"Wired News",
"http://www.wired.com/news_drop/netcenter/netcenter.rdf",
"Tech review"));
}
public ArrayList getFeedList(){ return FeedList;}
public void LoadFeeds()
{
// load as XML
XmlDocument doc = new XmlDocument();
try
{
doc.Load(filename);
XmlNodeList list = doc.GetElementsByTagName("feed");
foreach(XmlNode n in list)
FeedList.Add(new feed(n));
}
catch (Exception ex)
{
MessageBox.Show(
"Kan ikke laste opp kildefila: "+ex.Message,
"Feilmelding",
MessageBoxButtons.OK);
return;
}
}
public void SaveFeeds()
{
// save as text in XML-format
FileStream s = null;
StreamWriter w = null;
try
{
s = new FileStream(filename, FileMode.Truncate);
s.Position = 0;
w = new StreamWriter(s);
w.WriteLine("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
w.WriteLine("<feeds>");
for (int i = 0; i < FeedList.Count; i++)
w.WriteLine("<feed>"+
((feed)FeedList[i]).GetPacked()+
"</feed>");
w.WriteLine("</feeds>");
w.Flush();
}
catch (Exception e)
{
MessageBox.Show(
"Kan ikke spare kildefila: "+e.Message,
"feilmelding",
MessageBoxButtons.OK);
return;
}
finally
{
if (w != null)
w.Close();
}
}
}
FeedForm
Når vi skal endre et feed eller lage et nytt feed, gjør vi dette via en dialogboks: "FeedForm".
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace RSS
{
public partial class FeedForm : Form
{
public Uri link;
public String title;
public FeedForm(String t, String l)
{
InitializeComponent();
this.textBoxTitle.Text = t;
this.textBoxLink.Text = l;
}
private void buttonOK_Click(object sender, EventArgs e)
{
// is data ok
try
{
link = new Uri(this.textBoxLink.Text);
if ((this.textBoxTitle.Text==null)||
(this.textBoxTitle.Text.Length == 0))
title = this.textBoxLink.Text;
else
title = this.textBoxTitle.Text;
this.DialogResult=DialogResult.OK;
this.Hide();
}
catch(Exception ex){
DialogResult result;
result = MessageBox.Show(this,
"Kildens adresse (URL) ser ikke bra ut, korrigere ?",
"D�rlig lenke",
MessageBoxButtons.YesNo);
if (result == DialogResult.Yes)
return;
this.DialogResult = DialogResult.Cancel;
this.Hide();
}
}
}
}
Selve logikken er plassert på "Form" klassen:
Form
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.IO;
namespace RSS
{
public partial class Form1 : Form
{
// will be based on a list of feeds
feedlist theFeeds;
public Form1()
{
InitializeComponent();
// establish list of feeds and fill left listbox, feedlist
theFeeds =
new feedlist(Path.Combine(Application.StartupPath, "..\\..\\feeds.xml"));
if (theFeeds == null)
return;
for(int i=0;i<theFeeds.getFeedList().Count;i++)
listBoxFeeds.Items.Add(theFeeds.getFeedList()[i]);
// set up a welcome message in webbrowser
webBrowser1.DocumentText = Properties.Resources.startpage;
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
// store list of feeds
theFeeds.SaveFeeds();
}
private void FillUpItemlist(feed f)
{
// fill up listBoxItems with items from a selected feed
XmlDocument doc = f.xmldoc;
if (doc == null)
{
DialogResult result;
result = MessageBox.Show(this,
"Denne kilden er ikke tilgjengelig",
"Finner ikke kilden",
MessageBoxButtons.OK);
return;
}
// extract the items and fill up: listBoxItems
XmlNodeList list = doc.GetElementsByTagName("item");
listBoxItems.Items.Clear();
for (int nix = 0; nix < list.Count; nix++)
{
String strTitle = null;
String strLink = null;
String strDesc = null;
XmlNode p = list.Item(nix);
if (p.HasChildNodes)
{
foreach (XmlNode c in p.ChildNodes)
{
if (c.GetType() == typeof(XmlElement))
{
if (c.LocalName.CompareTo("title") == 0)
strTitle = c.InnerText;
if (c.LocalName.CompareTo("link") == 0)
strLink = c.InnerText;
if (c.LocalName.CompareTo("description") == 0)
strDesc = c.InnerText;
}
}
}
listBoxItems.Items.Add(new feed(strTitle, strLink, strDesc));
}
}
// get all items from this feed
private void listBoxFeeds_MouseClick(object sender, MouseEventArgs e)
{
// we have clicked on a listitem, which one ?
int ix = listBoxFeeds.IndexFromPoint(e.X, e.Y);
if (ix != -1)
{
// get all items in the actual feed
feed f = (feed)listBoxFeeds.Items[ix];
FillUpItemlist(f);
}
String tmp = listBoxFeeds.SelectedItem.ToString();
webBrowser1.DocumentText = "<html><body><h2>" + tmp + "</h2></body></html>";
}
// produce description of selected item in webbrowser
private void listBoxItems_MouseClick(object sender, MouseEventArgs e)
{
// we have clicked on a listitem, which one ?
int ix = listBoxItems.IndexFromPoint(e.X, e.Y);
if (ix != -1)
{
// get information from the actual feeditem
feed f = (feed)listBoxItems.Items[ix];
String description = f.description;
String title = f.title;
Uri link = f.link;
// produce HTML
String htmlS=
String.Format(Properties.Resources.skeleton,title,description,link);
webBrowser1.DocumentText = htmlS;
}
}
// we have a right-click in itemlist
private void contextMenuStrip1_ItemClicked(object sender,
ToolStripItemClickedEventArgs e)
{
//Which feed is selected ?
feed theFeed=(feed)listBoxFeeds.SelectedItem;
// what do we want to do with it ?
if (e.ClickedItem == this.renameToolStripMenuItem)
{
// change
FeedForm ff =
new FeedForm(theFeed.title,theFeed.link.ToString());
ff.ShowDialog(this);
if (ff.DialogResult == DialogResult.OK)
{
theFeeds.getFeedList().Remove(theFeed);
theFeeds.getFeedList().Add(
new feed(ff.title,ff.link.ToString(),""));
listBoxFeeds.Items.Clear();
for (int i = 0; i < theFeeds.getFeedList().Count; i++)
{
feed afeed=(feed)theFeeds.getFeedList()[i];
listBoxFeeds.Items.Add(afeed);
}
}
}
else if (e.ClickedItem == this.deleteToolStripMenuItem)
{
// delete it, after a warning
DialogResult result;
result = MessageBox.Show(this,
"Vil du virkelig fjerne denne kilden ?",
"Fjern kilde",
MessageBoxButtons.YesNo);
if (result == DialogResult.Yes)
{
theFeeds.getFeedList().Remove(theFeed);
listBoxFeeds.Items.Clear();
for (int i = 0; i < theFeeds.getFeedList().Count; i++)
listBoxFeeds.Items.Add(theFeeds.getFeedList()[i]);
listBoxItems.Items.Clear();
}
}
else if (e.ClickedItem == this.updateToolStripMenuItem)
{
// update the feed theFeed
theFeed.xmldoc = null;
FillUpItemlist(theFeed);
}
}
// add a feed
private void buttonNew_MouseClick(object sender, MouseEventArgs e)
{
//Introduce a new feed
FeedForm ff = new FeedForm("<title>", "<uri>");
ff.ShowDialog(this);
if (ff.DialogResult == DialogResult.OK)
{
theFeeds.getFeedList().Add(
new feed(ff.title, ff.link.ToString(), ""));
listBoxFeeds.Items.Clear();
for (int i = 0; i < theFeeds.getFeedList().Count; i++)
{
feed afeed = (feed)theFeeds.getFeedList()[i];
listBoxFeeds.Items.Add(afeed);
}
}
}
// update all feeds
private void buttonUpdate_MouseClick(object sender, MouseEventArgs e)
{
if (theFeeds.getFeedList().Count > 0)
{
for (int i = 0; i < theFeeds.getFeedList().Count; i++)
{
feed afeed = (feed)theFeeds.getFeedList()[i];
afeed.xmldoc=null;
}
// select and show first
listBoxFeeds.SelectedIndex=0;
FillUpItemlist((feed)listBoxFeeds.SelectedItem);
}
}
// see you later...
private void buttonExit_MouseClick(object sender, MouseEventArgs e)
{
this.Close();
this.Dispose();
}
}
}
Som du ser dersom du kjører programmet så er det en rekke ting som kan forbedres. Dersom programmet skulle utvikles i retning av et produkt så måtte vi i hvert fall vurdere å:
- forbedre sikkerheten
- bruke threads for oppdatering i bakgrunnen
- forbedre brukergrensesnittet funksjonelt
- gjennomføre en kraftig estetisk "makeover"
- trekke ut mer informasjon fra RSS-filene for å få fram bedre beskrivelse av kildene.
- la programmet ha hukommelse slik at det i tillegg til å huske de kildene vi abonnerer på, også husker et antall tidligere (permanent) items fra disse kildene.





