RSS-читалка на C# своими руками
Сегодня интернет представляет собой огромное скопление информации, но, чего греха таить, полезная инфа захламлена блогерами-графоманами, религиозными войнами и сомнительными сайтами, но выход есть: пробраться через хлам к свеженьким новостям поможет RSS – эта технология позволяет подписаться на новости интересных сайтов и получать самые свежие их экземпляры . К тому же RSS может существенно помочь в экономии трафика, что всё ещё актуально. Сегодня я покажу как самостоятельно, бысто и легко написать RSS-аггрегатор, т.е. прогу, которая будет скачивать последние новости и выводить их в удобоваримом формате, а заодно посмотрим насколько просто в C# работать с XML, файлами и регулярными выражениями.
Предполагается, что у читателя есть хотя бы базовые знания C#. Итак, приступим. Для начала сформулируем требования к нашей программе. Нам надо, чтобы она:
1. могла подписываться на RSS-ленты и отписываться от них. 2. загружала по мере необходимости свежие новости. 3. отображала новости в удобном и легко настраиваемом формате. 4. могла сохранять по желанию пользователя отдельные RSS-ленты. 5. что-то ещё по вкусу, сам допишешь
Создадим WindowsForm Application. Сразу скажу, что я пользовался для написания этой программы средой разработки SharpDevelop 2.1, но ты можешь использовать и Visual Studio, если конечно она у тебя лицензионная или Express. Кидай на форму ListBox – lbFeeds, WebBrowser – wbIE, TextBox – tbFeedURL, и три кнопки bNew, bEdit и bDelete. То, что получилось у меня, можешь наблюдать на скриншоте:
Также для сохранения выбранной ленты нам потребуется контекстное меня cmsIE с единственным пунктом – Сохранить и SaveFileDialog – sfd1. Теперь когда с GUI покончено, можно, наконец, приступать к самому интересному – кодингу. Подключи пространства имен, которые нам пригодятся в дальнейшем:
[code=c#] using System.Text.RegularExpressions; using System.Xml; using System.Xml.Xsl; using System.Text; using System.IO; [/code=c#]
Следуя идеям ООП, давай напишем класс для работы c RSS. Для начала, он будет загружать указанную RSS-ленту. И поскольку мы договорились о гибком управлении форматированием вывода, то он будет применять к ленте XSL-трансформацию. Что в синтаксисе C# выглядит .
[code=c#] public class RSS < private string _URL; private string XML_FileName; private string HTML_FileName; private string XSL_FileName; public RSS(string URL): this(URL, "feed.xsl") public RSS(string URL, string XSLT_File) < if (! Directory.Exists("files")) Directory.CreateDirectory("files"); XML_FileName = @"files\"+EscapeUrl(URL)+".xml"; HTML_FileName = @"files\"+EscapeUrl(URL)+".htm"; long dt=0; if (File.Exists(XML_FileName)) dt = DateTime.Now.Ticks-File.GetCreationTime(XML_FileName).Ticks; XSL_FileName=XSLT_File; _URL = URL; if (!(File.Exists(XML_FileName) && dt<3600e8)) /* если лента уже была обновлена в течении предыдущего часа * то загрузим её из локального файла */ try < System.Net.WebClient client = new System.Net.WebClient(); client.DownloadFile(_URL, XML_FileName); string sXML = File.ReadAllText(XML_FileName, Encoding.GetEncoding(1251)); sXML = Regex.Replace(sXML, @"<\?xml-stylesheet.*\?>", ""); sXML = Regex.Replace(sXML, @"<\w+\sxmlns:xsi.*\.xsd.?\s*>", ""); sXML = Regex.Replace(sXML, @"", ""); File.WriteAllText(XML_FileName, sXML, Encoding.GetEncoding(1251)); > catch (XmlException e) < MessageBox.Show(e.Message," Ошибка загрузки или обработки XML"); > >
private string EscapeUrl(string s) < return s.Replace('/','_').Replace(".xml","").Replace("http:__","").Replace("www.",""); > public string TransformToHTML() < XslCompiledTransform xslt = new XslCompiledTransform(); xslt.Load(XSL_FileName); xslt.Transform(XML_FileName, HTML_FileName); return HTML_FileName; > > [/code=c#]
Итак, конструктору передаётся два параметра: адрес ленты и имя файла с XSL-трансформацией, причём если второй параметр не задан, то используется трансформация по умолчанию - feed.xsl. Далее, если необходимо, создаем директорию, в которую будем записывать скачанные ленты и их отформатированное представление. Если запрашиваемая лента уже была скачана, то проверяем когда это было. Для простоты будем считать, что за час лента не обновляется, т.е. будем скачивать одну и ту же ленту не более одного раза за час.
Метод EscapeUrl служит для преобразования адреса ленты в уникальное имя файла без учёта расширения, в который она будет сохраняться, например ]]> http://www.realcoding.net/0/_upload/news.xml ]]> –> realcoding.net_0__upload_news. Обрати внимание, как производятся операции над строками, поскольку в .NET строка-это объект, то любой метод обработки строки создаёт новый объект, в который записывает результат. И, чтобы не хранить эти временные объекты в локальных переменных, можно записывать все методы обработки строки в одну строку.
Затем скачиваем RSS-файл из сети при помощи замечательного класса System.Net.WebClient, и не надо возмущаться в стиле: «Зачем он так извращается, ведь метод XmlDocument.Load и сам может прекрасно скачать файл?». Да, может, но дело тут вот в чём: метод Load не сможет обработать XML- документы со стилями(XSL), определениями(DTD) и схемами(XSD), а rss-ленты очень часто сопровождаются ими, но для просмотра они нам нафиг не нужны, поэтому вырезаем всё это добро при помощи специально обученных регулярных выражений. Затем записываем очищенный xml обратно в файл.
Функция TransformToHTML применяет к сохраненному XML-файлу XSL-трансформацию и возвращает имя htm-файла, в который она записала результат. По умолчанию применяется вот такая трансформация