⬆️ ⬇️

Himself RSS reader

One day, in the middle of the 5th year, the classmate asked me to help her with her labs

C #, as she only studied it. Having learned the task - “write an RSS reader” - and evaluate

situation - the end of the semester - I decided to help her, because I needed the RSS reader myself.





A bit of theory





RSS is a web content transfer format. The name of the technology is the acronym "Really Simple

Syndication ", that is," a really simple transfer of information. "

RSS is an XML dialect. All RSS files must comply with the XML1.0 specification published on the WWW Consortium (W3C) website .

At the top level, an RSS document is an < rss > element with a required attribute.

version indicating the version

RSS (by the way, I made my application based on RSS 2.0). Child element < rss >

- one < channel > element that includes channel information (metadata)

and its contents.

An example RSS 2.0 file looks like this:

<? xml version = "1.0" ? >

< rss version = "2.0" >



< channel >



< title > Liftoff News </ title >



< link > liftoff.msfc.nasa.gov </ link >



< description > Liftoff to Space Exploration. </ description >



')

< item >



< title > Star City </ title >



< link > liftoff.msfc.nasa.gov/news/2003/news-starcity.asp </ link >



< description >

How do Americans get ready to work

International Space Station? They take a crash course in culture, language

and the protocol at Russia's Star City.

</ description >



< pubDate > Tue, 03 Jun 2003 09:39:21 GMT </ pubDate >



</ item >





< item >



< title > Space Exploration </ title >



< link > liftoff.msfc.nasa.gov </ link >



< description >

Sky watchers in Europe, Asia, and parts of Alaska and Canada

on Saturday, May 31st.

</ description >



< pubDate > Fri, 30 May 2003 11:06:42 GMT </ pubDate >



</ item >



</ channel >

</ rss >







Pretty simple file. What does he give us? First, the channel (Channel,

he's Feed) and various information about it - the title, the link to the official website,

channel description, etc.). Secondly, the list of articles / news / records (item) call

as you wish, as well as the properties of these records: title, link, description, date of publication.

In fact, the properties of both the channel and the recording can be much more. All of them

given in the rss 2.0 specification. Her translation, made by Alexey Beshenov , can be found here . The latest specification is available

find here .

To work with the information provided by rss, we need 3 classes: a class for

channel storage, let's call it RssFeed ;

class for storing a list of entries - RssItems ; storage class

Records - RssItem .



Form creation



Open Microsoft Visual Studio 2005 (<span

lang = “en”> Linux guides open MonoDevelop) and create a new application. Call it

Rssreader The interface is simple:



The first and main control that needs to be placed on the form is TableLayoutPanel ,

stretched to full shape (Dock = Fill). This is a very convenient control, it represents

is a table in which every cell you can place an interface element

(an element can occupy several columns and / or rows of a table at the same time). Dimensions

columns can be fixed or specified as a percentage of the size of the table.

This is very useful when resizing a table.

I think the purpose of the remaining elements is clear: TextBox - entering the channel address; Button - button to update the feed; in listview

- displays a list of entries; in WebBrowser - the content is displayed

records

Now we will begin development of the reader. We will start it from the bottom, namely from the class <span

lang = "en-us"> RssItem , then create a class <span

lang = "en-us"> RssItems ,

last to be written

Rssfeed



RssItem



This class provides us with record information. According to the specification of rss 2.0

"All < item > elements are optional, but at least

< title > or < description > must exist. ”

Add a new class to the project, call it RssItem . As a result, we obtain the following:

using

System;

using System.Collections.Generic;

using System.Text;



namespace RssReader



{

class RssItem

{

}

}


Our class will store minimal information about the record: title (title), link

(link to the full text) and description (a brief overview of the message). Add to

Class 3 public fields to store this information:
class RssItem

{

public String title; // record header

public

String link; // link to

full text

public String description; // record description

}




Now add a constructor that will fill in these properties. At the entrance to the designer

must be transferred to a specific entry from rss. Since rss is just a dialect

XML, then we pass the < item > branch to the constructor as input. Yes. Next, the constructor

loops through each tag inside the received record and, meeting

the desired tag, write information from it to the appropriate class property. Implemented

it may be like this:

///



/// Constructor to fill the record



///

/// <param

name = "ItemTag"> xml tag for reading

public

RssItem ( XmlNode ItemTag)



{



//

view all post tags



foreach ( XmlNode xmlTag in

ItemTag.ChildNodes)



{



// check the tag name if

corresponds to one of the specified,



// then in

the corresponding property of the object is written the contents of the tag



switch (xmlTag.Name)



{

case "title" :



{



this .Title = xmlTag.InnerText;



break ;

}

case

"Description" :



{

this .Description = xmlTag.InnerText;



break ;



}



case

"Link" :



{



this .Link

= xmlTag.InnerText;



break ;



}



}



}



}


Oh by the way since we work with <font color = "# 2B91AF"

face = "Courier New" size = "2"> XmlNode, you need to enable

corresponding assembly in <font color = "# 0000ff" face = "Courier New"

size = "2"> using section:

using

System.Xml;



Rssitems



This class we have is a list of all feed entries. We will implement it

through generics, namely my favorite generic class

List

And I like this generic because it provides very convenient methods of working with

arrays of data.

Add a new class to the project and name it RssItems . We get the following:

using

System;

using System.Collections.Generic;



using System.Text;

namespace

RssReader



{



class rssItems



{



}



}


Next we inherit RssItems from

List , instead of T specifying

the type whose objects will be stored in the list. At the same time override the method Contains,

to determine the existence of an entry in the list by its title.

///



/// Check for the existence of the specified

item in list

///



/// object to compare



/// true if there is an object in the list, otherwise

false



new

public

bool Contains ( RssItem Item)



{



foreach ( RssItem itemForCheck in this )



{



//

Compare record headers



if

(Item.Title == itemForCheck.Title)



{



// found

coincidence. return the truth



return

true ;



}



}



//

no matches found. we return the box



return

false ;



}


It would also be not bad to be able to catch the record of interest from the list.

using her title. To do this, we write another method similar to the Contains method:

///



/// Get an entry from the list by its

header

///



/// record title



/// If the record exists, it is returned

otherwise, it returns null

public RssItem GetItem ( String Title)



{ foreach ( RssItem itemForCheck in this )



{



//

Compare the record header with the query.



if

(Item.Title == Title)



{



// found a match.

return the found record



return

itemForCheck;



}



}



// no matches found.



return null ;



}


Rssfeed



So we got to the main class of our reader.

This class will store channel information. According to the specification of rss 2.0 to mandatory

Channel elements include: < title > - title

channel through which people will refer to the service; < link > is the URL of the website associated with the channel; < description > is a phrase or sentence to describe the channel.

Add a new class to the project again and call it RssFeed .

using

System;

using System.Collections.Generic;



using System.Text;





namespace RssReader



{

class RssFeed



{



}

}


Since all of the above channel properties are required, we need to add

them and in our class. We also add a property of type RssItems to store the list of channel entries:

class RssFeed



{

public String Title;

// channel header



public

String Description; //

description of the canal



public

String link; // link to

channel related website



public

RssItems Items; // list of channel entries



}


All that remains to be done now is to write a class constructor, which will be

receive, as a parameter, a link to the rss channel, and if the rss is really there

There is, fill the properties of the created object with data from rss (I hope the code

no questions arise, I tried to comment on it in detail):

///



/// Constructor for filling data

channel

///

/// Channel Address

public

RssFeed ( String Url)



{



//

We initialize the list of records



Items = new

RssItems ();



// Create a reader to read Rss from

specified address



XmlTextReader

xmlTextReader = New XmlTextReader (Url);



// create a new xml document to write to it

RSS feed



XmlDocument xmlDoc = New

XmlDocument ();



try



{



// load the RSS into the document using the reader



xmlDoc.Load (xmlTextReader);



// close reader for

uselessness



xmlTextReader.Close ();



//

since all the RSS feed information is written between the tags,

// ship we get this thread.



XmlNode channelXmlNode = xmlDoc.GetElementsByTagName ( "channel" ) [0];



// if a

the branch exists, we begin to flood the properties of the object

// data from a branch



if

(channelXmlNode! = null )



{



// iterate all descendants of the tag



foreach ( XmlNode

channelNode in channelXmlNode.ChildNodes)



{



// if the name of the descendant tag is of interest to us, then

write his data



// to a specific

object property



switch

(channelNode.Name)



{



case

"Title" :



{



Title =

channelNode.InnerText;



break ;



}



case "description" :



{



Description =

channelNode.InnerText;



break ;



}



case "link" :



{



Link = channelNode.InnerText;



break ;



}



case "item" : // if the name of the tag being checked is item, then



{



// create a new tag from this

write object



Rss <span

lang = "en-us"> Item channelItem = new

RssItem (channelNode);



// and add it to

list of channel entries



Items.Add (channelItem);



break ;



}



}



}



}



else

//

if no tag is found in the resulting file, then we throw an exception



{



throw New Exception ( "Error in XML. Channel description not found!" );



}



}



// If the channel url is not specified correctly, then throw it away.

source unreachable exception

catch

(System.Net.WebException ex)



{



if (ex.Status

== System.Net.WebExceptionStatus.NameResolutionFailure)



throw new Exception ( "Unable to connect to the specified source. \ r \ n" +

Url);



else throw

ex;



}



// if the RSS address was specified

local path that does not exist yet,



//

then throw the corresponding exception



catch

(System.IO.FileNotFoundException)



{



throw New

Exception ( "File" + Url + "

not found! ” );



}



// well and lastly, we catch everything

the remaining exceptions, and pass them on as is



catch (Exception ex)



{



throw

ex;



}



finally



{



//

close the reader



xmlTextReader.Close ();



}



}

Final stage



Now, all that's left to do is write the code for the click event handlers.

“update” buttons and selecting an item in ListView , as well as adding a global variable CurrentFeed, in which the loaded channel will be stored:



//

Global variable storing channel data



Rssfeed

CurrentFeed;





// processing of clicking on the "Update" button

private void btRefresh_Click ( object sender, EventArgs

e)



{



// Check if the address is set



if (! String .IsNullOrEmpty (tbUrl.Text))



{



// Clear the ListView before adding new data



lvNews.Clear ();



// Initialize the channel



CurrentFeed = new RssFeed (tbUrl.Text);



foreach ( Rss <span

lang = "en-us"> Item feedItem in

CurrentFeed.Items)



{



// create an item to display in the ListView



ListViewItem listViewItem = new ListViewItem (feedItem.Title);



// set his name



listViewItem.Name = feedItem.Title;



// put it in the listview



lvNews.Items.Add (listViewItem);



}



}



}



// Processing the change of item selection in the ListView

private void lvNews_SelectedIndexChanged ( object sender, EventArgs

e)



{



// get the news associated with the selected ListViewItem



if (lvNews.SelectedItems.Count> 0

&& // check that something is really selected



CurrentFeed! = Null

&& // check that the channel is initialized



CurrentFeed.Items.Count> 0

// check the existence of records in the channel



)



{



// display the full text of the selected entry



wbDescription.DocumentText =

CurrentFeed.Items.GetItem (lvNews.SelectedItems [0] .Text) .Description;

}

}


Conclusion



As a result, we got a simple RSS reader that can read standard 2.0 feeds.

In the next article I will try to tell you how to make our classes more

universal, as well as you can organize the storage of the history of visited

tapes.

Download the source of the written reader here .



PS: constructive criticism, as well as suggestions and suggestions are welcome.


Ramil Aliyakberov aka R @ Me0!



* All source codes were highlighted using Source Code Highlighter .

Source: https://habr.com/ru/post/27443/



All Articles