Свой RssReader на C# (Csharp). Работа с RSS (XML)
Уже несколько лет очень популярной технологией является RSS. Почти на каждом сайте мы можем встретить RSS-ленты в которых содержатся новости сайта, статьи, последние топики форумов, и т.д. Для того чтобы написать свою программу чтения RSS сначала нужно прочитать спецификацию RSS. Краткие сведения о RSS можно почитать в моей статье "Создание собственной RSS-ленты".Если говорить в общих чертах, то RSS представляет собой диалект XML. Обязательными элементами которого являются channel, item, title, description, link, pubDate.
Наша программа будет запрашивать RSS-ленту сайта devoid.com.ua, которая находится здесь и содержит 10 новых статей портала.
Приступим к программированию. Запускаем Visual Studio 2005 и создаем новый проект под названием, скажем RssReader. На форме кнопка (Button) и Веб-браузер (WebBrowser). Форма выглядит примерно так:

Как видно из дизайнера формы, загружать наш RSS-поток мы будем по нажатию кнопки "Загрузить". Все возможные элементы RSS-ленты мы парсить не будем, ограничимся лишь channel, item и img.
Следующим шагом и будет написание классов, которые будут отвечать за отпарсенную информацию из RSS-потока.
Класс, который отвечает за настройки канала (channel) будет выглядеть так:
// Класс который отвечает за настройки канала
public class ChannelClass
{
public string title;
public string description;
public string link;
public string copyright;
public ChannelClass()
{
title = "";
description = "";
link = "";
copyright = "";
}
}
Как видно класс Канала содержит в себе четыре поля, которые говорят сами за себя. Название канала, Описание канала, ссылка, и копирайт (является необязательным).Следующим классом который мы создадим будет класс, который будет отвечать за рисунок канала (рисунок является необязательным элементом канала, но в целях получения опыта научимся работать и с ним):
// Класс рисунка канала
public class ImageOfChanel
{
public string imgTitle;
public string imgLink;
public string imgURL;
public ImageOfChanel()
{
imgTitle = "";
imgLink = "";
imgURL = "";
}
}
Класс довольно простой, и содержит в себе 3 обязательных элемента: Название канала, URL-рисунка, и URL-сайта.Далее пишем класс, который отвечает за элементы <item> канала:
// Класс статей
public class Items
{
public string title;
public string link;
public string description;
public string pubDate;
public Items()
{
title = "";
link = "";
description = "";
pubDate = "";
}
}
Здесь тоже ничего нового мы не увидели, названия говорят всё за себя.Отметим что основным методом нашего RssReadera будет метод считывания данных из RSS-ленты и заполнение данными соответствующих обьектов классов, которые нужно обьявить перед телом метода:
ImageOfChanel imageChanel = new ImageOfChanel(); // обьект класса рисунка
Items[] articles; // создаем массив элементов item канала
ChannelClass channel = new ChannelClass(); // создаем обьект класса ChannelClass
Для ясности я сначала приведу код метода получения данных, а далее подробно распишу:
bool getNewArticles(string fileSource)
{
try
{
XmlDocument doc = new XmlDocument();
doc.Load(fileSource);
XmlNodeList nodeList;
XmlNode root = doc.DocumentElement;
articles = new Items[root.SelectNodes("channel/item").Count];
nodeList = root.ChildNodes;
int count = 0;
foreach (XmlNode chanel in nodeList)
{
foreach (XmlNode chanel_item in chanel)
{
if (chanel_item.Name == "title")
{
channel.title = chanel_item.InnerText;
}
if (chanel_item.Name == "description")
{
channel.description = chanel_item.InnerText;
}
if (chanel_item.Name == "copyright")
{
channel.copyright = chanel_item.InnerText;
}
if (chanel_item.Name == "link")
{
channel.link = chanel_item.InnerText;
}
if (chanel_item.Name == "img")
{
XmlNodeList imgList = chanel_item.ChildNodes;
foreach (XmlNode img_item in imgList)
{
if (img_item.Name == "url")
{
imageChanel.imgURL = img_item.InnerText;
}
if (img_item.Name == "link")
{
imageChanel.imgLink = img_item.InnerText;
}
if (img_item.Name == "title")
{
imageChanel.imgTitle = img_item.InnerText;
}
}
}
if (chanel_item.Name == "item")
{
XmlNodeList itemsList = chanel_item.ChildNodes;
articles[count] = new Items();
foreach (XmlNode item in itemsList)
{
if (item.Name == "title")
{
articles[count].title = item.InnerText;
}
if (item.Name == "link")
{
articles[count].link = item.InnerText;
}
if (item.Name == "description")
{
articles[count].description = item.InnerText;
}
if (item.Name == "pubDate")
{
articles[count].pubDate = item.InnerText;
}
}
count += 1;
}
}
}
return true;
}
catch (Exception ex)
{
return false;
}
}
Не стоит пугаться столь большого обьема кода, на самом деле он довольно прост. Следует отметить также, что так как RSS является диалектом
XML, то и работать мы будем с ним как с XML-документом. Для этого нужно в uses добавить XML:
using System.Xml; using System.IO;using System.IO; - тоже добавьте, это нам понадобится позже.
Итак, функция getNewArticles(string fileSource) принимает в качестве параметра ссылку на RSS-поток, и возвращает либо true при успешной работе, либо false при неудачной попытке. Весь код помещен в try...catch для отслеживания исключительных ситуаций.
Далее идем по коду:
XmlDocument doc = new XmlDocument(); doc.Load(fileSource);Создаем обьект класса doc и загружаем в него наш RSS-поток методом Load(fileSource).
XmlNodeList nodeList;
XmlNode root = doc.DocumentElement;
articles = new Items[root.SelectNodes("channel/item").Count];
nodeList = root.ChildNodes;
int count = 0;
Создаем XmlNode root - который будет содержать корневой элемент XML.Далее получаем количество элементов item в нашем RSS-потоке, используя SelectNodes() и выражение XPath, которое позволяет это сделать.
nodeList получает все элементы channel.
count - используется как индексатор массива articles[].
foreach (XmlNode chanel in nodeList)
{
...
}
Этим циклом мы проходим по всем элементам cnannel. Обрабатывая название канала, описание, ссылку - этими строками:
foreach (XmlNode chanel_item in chanel)
{
if (chanel_item.Name == "title")
{
channel.title = chanel_item.InnerText;
}
if (chanel_item.Name == "description")
{
channel.description = chanel_item.InnerText;
}
if (chanel_item.Name == "copyright")
{
channel.copyright = chanel_item.InnerText;
}
if (chanel_item.Name == "link")
{
channel.link = chanel_item.InnerText;
}
...
Когда мы находим элемент <img> или <item>, который содержит тоже элементы, мы просто запускаем еще один цикл, который обрабатывает их:
if (chanel_item.Name == "img")
{
XmlNodeList imgList = chanel_item.ChildNodes;
foreach (XmlNode img_item in imgList)
{
if (img_item.Name == "url")
{
imageChanel.imgURL = img_item.InnerText;
}
if (img_item.Name == "link")
{
imageChanel.imgLink = img_item.InnerText;
}
if (img_item.Name == "title")
{
imageChanel.imgTitle = img_item.InnerText;
}
}
}
if (chanel_item.Name == "item")
{
XmlNodeList itemsList = chanel_item.ChildNodes;
articles[count] = new Items();
foreach (XmlNode item in itemsList)
{
if (item.Name == "title")
{
articles[count].title = item.InnerText;
}
if (item.Name == "link")
{
articles[count].link = item.InnerText;
}
if (item.Name == "description")
{
articles[count].description = item.InnerText;
}
if (item.Name == "pubDate")
{
articles[count].pubDate = item.InnerText;
}
}
count += 1;
}
После выполнения этой функции, мы имеем обьекты классов, заполненные данными.
в imageChanel содержатся все данные о рисунке (если он есть), в channel - все параметры канала, а массив articles - содержит все статьи портала devoid.com.ua
(или элементы item в случае парсинга другой RSS-ленты).
Для отображения отпарсенных данных нам и пригодится WebBrowser. Все данные из RSS-потока мы сохраним в виде *.html
файла, и потом отобразим его. Для этого напишем простую функцию:
bool generateHtml()
{
try
{
using (StreamWriter writer = new StreamWriter("last_articles.html"))
{
writer.WriteLine("<html>");
writer.WriteLine("<head>");
writer.WriteLine("<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">");
writer.WriteLine("<title>");
writer.WriteLine(channel.title);
writer.WriteLine("</title>");
writer.WriteLine("<style type='text/css'>");
writer.WriteLine("A{color:#483D8B; text-decoration:none; font:Verdana;}");
writer.WriteLine("pre{font-family:courier;color:#000000;");
writer.WriteLine("background-color:#dfe2e5;padding-top:5pt;padding-left:5pt;");
writer.WriteLine("padding-bottom:5pt;border-top:1pt solid #87A5C3;");
writer.WriteLine("border-bottom:1pt solid #87A5C3;border-left:1pt solid #87A5C3;");
writer.WriteLine("border-right : 1pt solid #87A5C3; text-align : left;}");
writer.WriteLine("</style>");
writer.WriteLine("</head>");
writer.WriteLine("<body>");
writer.WriteLine("<font size=\"2\" face=\"Verdana\">");
writer.WriteLine("<a href=\"" + imageChanel.imgLink + "\">");
writer.WriteLine("<img src=\"" + imageChanel.imgURL + "\" border=0></a> ");
writer.WriteLine("<h3>" + channel.title + "</h3></a>");
writer.WriteLine("<table width=\"80%\" align=\"center\" border=1>");
foreach (Items article in articles)
{
writer.WriteLine("<tr>");
writer.WriteLine("<td>");
writer.WriteLine("<br>  <a href=\"" + article.link + "\"><b>" + article.title + "</b></a>");
writer.WriteLine("& (" + article.pubDate + ")<br><br>");
writer.WriteLine("<table width=\"95%\" align=\"center\" border=0>");
writer.WriteLine("<tr><td>");
writer.WriteLine(article.description);
writer.WriteLine("</td></tr></table>");
writer.WriteLine("<br>  <a href=\"" + article.link + "\">");
writer.WriteLine("<font size=\"1\">читать дальше</font></a><br><br>");
writer.WriteLine("</td>");
writer.WriteLine("</tr>");
}
writer.WriteLine("</table><br>");
writer.WriteLine("<p align=\"center\">");
writer.WriteLine("<a href=\"" + channel.link + "\">" + channel.copyright + "</a></p>");
writer.WriteLine("</font>");
writer.WriteLine("</body>");
writer.WriteLine("</html>");
return true;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return false;
}
}
Функция не сложная и не требует глубоких пояснений, стоит только отметить что мы создаем StreamWriter, который записывает все данные в файл last_articles.html
Теперь осталось лишь добавить обработчик нажатия кнопки, который выглядит вот так:
if (getNewArticles("http://devoid.com.ua/rss.php") == true && generateHtml() == true)
{
Browser.Navigate(Environment.CurrentDirectory + "\\last_articles.html");
}
После всего вышесказанного, осталось только нажать F5 и получить новые статьи сайта www.devoid.com.ua.Стоит заметить также что наш парсер является уникальным, и сможет работать со всеми RSS-лентами стандарта 2.0.
Исходники этого RSS-ридера можно скачать отсюда.
Спасибо за внимание, успехов!
Информация о статье "Свой RssReader на C# (Csharp). Работа с RSS (XML)"
DeVoid |
http://devoid.com.ua/ |
30 Сентября 2007 |
Просмотрели 4411 раз
КОММЕНТАРИИ (3)
16 Июля 2009 00:26:23 |
#
К сожалению, при переезде на новый движок, все исходники к этой статье потерялись, но по материалу, который изложен в этой статье вполне можно написать свой :)
24 Апреля 2010 17:16:08 |
#
Отличная статья.
Вы были правы, без исходников тоже можно обойтись. Я сам разобрался, и всё получилось. Еще раз - спасибо.
Зарегистрируйтесь или выполните Вход для того чтобы оставлять комментарии


Не менее интересно
Можете выложить исходники RSS-ридера а то по вашей ссылки не качается.