Click here to Skip to main content
15,896,915 members
Articles / Web Development / HTML

Keyword Matching RSS Reader Control

Rate me:
Please Sign up or sign in to vote.
3.38/5 (5 votes)
18 Apr 2008CPOL2 min read 60.4K   177   18  
Display RSS results that contain specific keywords.
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Xml;
using System.Text;


/// <summary>
/// RSS Reader Control
/// 
/// litCopy literal control will display control messages, ie: No RSS feed defined
/// 
/// Following properties are customizable:
///     - SourceRss (RSS URL) - can be comma-delimited when using titleKeyword matching
///     - TitleKeywords - match these in titles
///     - TitleLength - number of characters to display in the title before truncating at the last word, and adding '...'
///     - ShowTitles
///     - ShowDescriptions
///     - ShowLinks
///     - Width
///     - Height
///     - RowsToDisplay
///     - LinkTarget
///     - UseTitleBullets
///     
/// ie. in our class where the control has been imported, use:
///     RssReader1.Width = xxx; 
///     RssReader1.Height = xxx;
/// </summary>
public partial class Controls_RssReader : System.Web.UI.UserControl
{

    ArrayList arrSourceRss;
    ArrayList arrTitleKeywords;

    private string _linkTarget;
    /// <summary>
    /// Default is _blank {_blank, _self, _parent, _top}
    /// </summary>
    public string LinkTarget
    {
        get { return _linkTarget; }
        set { _linkTarget = value; }
    }

    private bool _useTitleBullets;
    /// <summary>
    /// Prefix each title with bullets
    /// </summary>
    public bool UseTitleBullets
    {
        get { return _useTitleBullets; }
        set { _useTitleBullets = value; }
    }

    private string _RenderType;
    /// <summary>
    /// {Text, DataGrid} Render the RSS feed as Text or DataGrid
    /// </summary>
    public string RenderType
    {
        get { return _RenderType; }
        set { _RenderType = value.ToLower(); }
    }

    private string _rowDivider;
    /// <summary>
    /// Row divider, ie. '<hr />'
    /// </summary>
    public string RowDivider
    {
        get { return _rowDivider; }
        set { _rowDivider = value; }
    }

    private bool _showLinks;
    /// <summary>
    /// Show links for each RSS item
    /// </summary>
    public bool ShowLinks
    {
        get { return _showLinks; }
        set { _showLinks = value; }
    }


    private bool _showDescriptions;

    /// <summary>
    /// Show descriptions for each RSS Item
    /// </summary>
    public bool ShowDescriptions
    {
        get { return _showDescriptions; }
        set { _showDescriptions = value; }
    }

    private bool _showTitles;

    /// <summary>
    /// Show titles for each RSS Item
    /// </summary>
    public bool ShowTitles
    {
        get { return _showTitles; }
        set { _showTitles = value; }
    }

    private string _sourceRss;

    /// <summary>
    /// Specify the source for the RSS Feed.  Comma-delimited for multiple feeds, when titles require specific keywords
    /// </summary>
    public string SourceRss
    {
        get { return _sourceRss; }
        set { _sourceRss = value; }
    }

    private string _titleKeywords;

    public string TitleKeywords
    {
        get { return _titleKeywords; }
        set { _titleKeywords = value; }
    }

    private int _width;

    /// <summary>
    /// Width of the feed
    /// </summary>
    public int Width
    {
        get { return _width; }
        set { _width = value; }
    }

    private int _rowsToDisplay;
    /// <summary>
    /// Number of rows from the feed to display
    /// </summary>
    public int RowsToDisplay
    {
        get { return _rowsToDisplay; }
        set { _rowsToDisplay = value; }
    }

    private int _titleLength;
    /// <summary>
    /// Number of characters to display before showing "..."
    /// </summary>
    public int TitleLength
    {
        get { return _titleLength; }
        set { _titleLength = value; }
    }


    private void Page_Init(object sender, System.EventArgs e)
    {
        this.EnableViewState = false;
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {

        }

        if (RenderType == String.Empty | RenderType == null)
        {
            RenderType = "Text";
        }

        if (ShowDescriptions)
            _showDescriptions = true;
        if (ShowLinks)
            _showLinks = true;
        if (ShowTitles)
            _showTitles = true;

        if (_width == 0)
        {
            _width = 600;
        }
        dgFeed.Width = _width;          // for datagrid
        PnlTextFeed.Width = _width;     // for text render

        dgFeed.Visible = true;
        //litCopy.Visible = false;
        LoadData();

    }

    protected void LoadData()
    {
        bool addRow = false;
        int rowCount = 0;

        DataTable dtFeed;
        int dtFeedRowCount = 0;
        StringBuilder sb = new StringBuilder();

        string rowTitle = "";

        if (_rowsToDisplay == 0)
        {
            _rowsToDisplay = 5;
        }

        if (!HasValue(_sourceRss))
        {
            sb.Append("<font color=red><b>No RSS source has been specified in your file's code-behind.</b><br>For example:");
            sb.Append("<pre>RssReader1.SourceRss = \"RssReader1.SourceRss = \"http://news.google.com/news?hl=en&ned=us&q=carbon+offset&ie=UTF-8&output=rss,http://news.google.com/news?hl=en&ned=us&q=bio+fuel&ie=UTF-8&output=rss,http://news.google.com/news?hl=en&ned=us&q=eliminate+poverty&ie=UTF-8&output=rss,http://news.google.com/news?hl=en&ned=us&q=Jatropha+trees&ie=UTF-8&output=rss,http://news.google.com/news?hl=en&ned=us&q=reduce+global+warming&ie=UTF-8&output=rss,http://news.google.com/news?hl=en&ned=us&q=tree+planting&ie=UTF-8&output=rss,http://news.google.com/news?hl=en&ned=us&q=carbon+neutral&ie=UTF-8&output=rss,http://news.google.com/news?hl=en&ned=us&q=green+business&ie=UTF-8&output=rss,http://news.google.com/news?hl=en&ned=us&q=Jatropha+plantations&ie=UTF-8&output=rss,http://news.google.com/news?hl=en&ned=us&q=carbon+footprint&ie=UTF-8&output=rss\";<br />");
            sb.Append("RssReader1.TitleKeywords = \"global warming,carbon footprint,global warming solutions,prevent global warming,offset carbon footprint\"");
            sb.Append("RssReader1.RowsToDisplay = 5;<br />");
            sb.Append("RssReader1.Width = 400;<br />");
            sb.Append("RssReader1.ShowLinks = false;<br />");
            sb.Append("RssReader1.ShowTitles = true;<br />");
            sb.Append("RssReader1.ShowDescriptions = false;<br />");
            sb.Append("RssReader1.RowDivider = \"&lt;hr&gt;\";</pre></font>");

            litCopy.Text = sb.ToString();
        }
        if (HasValue(_sourceRss))
        {
            // if TitleKeywords contains values, cycle through the list of RSS feeds to get 
            // titles with those keywords.

            if (HasValue(_titleKeywords))
            {
                arrTitleKeywords = new ArrayList(_titleKeywords.ToLower().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries));
            }
            else
            {
                arrTitleKeywords = new ArrayList();
            }

            arrSourceRss = new ArrayList(_sourceRss.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries));

            if (RenderType == "text" && _useTitleBullets)
            {
                sb.Append("<ul>");
            }            

            for (int x = 0; x < arrSourceRss.Count; x++)
            {
                if (rowCount >= _rowsToDisplay)
                {
                    break;
                }

                dtFeed = GetRSSFeed(arrSourceRss[x].ToString()).Copy();
                //Response.Write("hasdata: " + dtFeed.Rows.Count);
                dtFeedRowCount = dtFeed.Rows.Count;
                if (dtFeedRowCount > 0)
                {
                    if (RenderType == "text")
                    {
                        // use bullets - create the unordered list

                        // rows
                        foreach (DataRow row in dtFeed.Rows)
                        {
                            // columns in rows: title, link, item_Id, pubDate, description, channel_Id
                            foreach (DataColumn col in dtFeed.Columns)
                            {
                                //Response.Write("<b>COL: </b>: " + row[col] + ": " + col + "<br>");

                                //
                                // If TitleKeywords has values - optimizing title text 
                                //
                                addRow = false;

                                // check the rows to display
                                if (rowCount <= _rowsToDisplay)
                                {
                                    addRow = true;
                                }
                                else
                                {
                                    break;
                                }

                                rowTitle = row["title"].ToString();


                                if (_titleLength != 0)
                                {
                                    // limit the title to the number of characters - to the last word
                                    // get subset, then find last space, and truncate
                                    try
                                    {
                                        rowTitle = rowTitle.Substring(0, _titleLength);
                                        rowTitle = rowTitle.Substring(0, rowTitle.LastIndexOf(' ')) + " ...";
                                    }
                                    catch (Exception)
                                    {
                                        // do nothing
                                    }
                                }

                                if (arrTitleKeywords.Count > 0)
                                {
                                    foreach (string keywords in arrTitleKeywords)
                                    {
                                        if (rowTitle.ToLower().Contains(keywords.ToLower().Trim()))
                                        {
                                            addRow = true;
                                            break;
                                        }
                                        else
                                        {
                                            addRow = false;
                                        }
                                    }
                                }
                                else
                                {
                                    // since we're not filtering the rows based on keywords, always add them
                                    addRow = true;
                                }

                                if (addRow)
                                {
                                    rowCount ++;
                                    // Bullets
                                    if (_useTitleBullets)
                                    {
                                        sb.Append("<li>");
                                    }

                                    //
                                    // Titles - with/without links
                                    //
                                    if (_showTitles & _showLinks)
                                    {
                                        // link target
                                        if (HasValue(_linkTarget))
                                        {
                                            sb.Append("<a href='" + row["link"] + "' target='" + _linkTarget + "'>");
                                        }
                                        else
                                        {
                                            sb.Append("<a href='" + row["link"] + "' target='_blank'>");
                                        }

                                        sb.Append(rowTitle);
                                        sb.Append("</a>");
                                    }
                                    else if (_showTitles & !_showLinks)
                                    {
                                        sb.Append(rowTitle);
                                    }

                                    // Description
                                    if (_showDescriptions)
                                    {
                                        sb.Append(row["description"]);
                                    }

                                    // Bullets
                                    if (_useTitleBullets)
                                    {
                                        sb.Append("</li>");
                                    }

                                    if (dtFeed.Rows.Count > 1)
                                    {
                                        sb.Append(_rowDivider);
                                    }

                                    break;
                                }   // addRow == true
                            }   // col
                            if (rowCount >= _rowsToDisplay)
                            {
                                break;
                            }
                        }   // row

                    }
                    else if (RenderType == "datagrid")
                    {
                        dgFeed.DataSource = dtFeed;
                        try
                        {
                            dgFeed.DataBind();

                        }
                        catch (HttpException)
                        {
                            // some feeds may not have the description field, if no information is available, only title
                            dgFeed.Visible = false;
                            litCopy.Text = "No recent information has been posted.";
                            litCopy.Visible = true;
                        }
                    }
                }
            }

            // use bullets - create the unordered list
            if (RenderType == "text" && _useTitleBullets)
            {
                sb.Append("</ul>");
            }

            if (RenderType == "text")
            {
                // add the content to the page
                litFeed.Text = sb.ToString();
            }



            // if after iterations, still no data, present default copy
            if (dtFeedRowCount == 0)
            {
                dgFeed.Visible = false;
                litCopy.Text = "No data found.";
                litCopy.Visible = true;
            }
        }
    }

    /// <summary>
    /// Gets the content of an RSS feed, and populates a DataTable 
    /// </summary>
    /// <param name="thisNetworkName"></param>
    /// <returns></returns>
    protected DataTable GetRSSFeed(string RSS_FEED)
    {
        DataSet ds = new DataSet();
        DataTable outputTable = new DataTable();
        DataView dv;

        // if that fails, then use the country name + mobile

        //http://www.flipdog.com/rss/belize/
        //http://www.topix.net/rss/world/canada
        //http://www.infoplease.com/ipa/A0004379.html - world stats
        // if the feed is not found with the entire name, retry with the first word, adding "mobile" to it

        try
        {
            XmlTextReader reader = new XmlTextReader(RSS_FEED);
            ds.ReadXml(reader);         // populate dataset
        }
        catch (Exception)
        {
            // do nothing;
            Response.Write("Data Unavailable");

        }


        if (ds.Tables.Count > 3)
        {
            // populate dv so we can filter out extra <item> rows
            dv = new DataView(ds.Tables[3]);
            //outputTable = dv.Table.Clone();
            outputTable = dv.Table.Copy();


            //try
            //{

            //    // iterate through the dv rows, copy them to the outputTable until max rows is reached
            //    for (int rowCount = 0; rowCount < ; rowCount++)
            //    {
            //        outputTable.ImportRow(dv.Table.Rows[rowCount]);
            //    }

            //    // some feeds may not have the 'description' field if the title indicates no data
            //    //if (!outputTable.Columns.Contains("description"))
            //    //{
            //    //    DataColumn dataColumn = new DataColumn();
            //    //    dataColumn.DataType = Type.GetType("System.String");
            //    //    dataColumn.ColumnName = "description";
            //    //    outputTable.Columns.Add(dataColumn);
            //    //}

            //    return outputTable;
            //}
            //catch (IndexOutOfRangeException orex)
            //{
            //    // do nothing - no more rows to read
            //}

            return outputTable;
        }


        return outputTable;


    }

    /// <summary>
    /// Checks if a QueryString or other object contains a value.
    /// </summary>
    /// <param name="o"></param>
    /// <returns></returns>
    public bool HasValue(object o)
    {
        if (o == null)
        {
            return false;
        }

        if (o == System.DBNull.Value)
        {
            return false;
        }

        if (o is String)
        {
            if (((String)o).Trim() == String.Empty)
            {
                return false;
            }
        }

        return true;
    }

    /// <summary>
    /// Removed unwanted fields from the RSS dg display
    /// Set by, ie. RssReader1.ShowTitles = true;
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void dgFeed_ItemCreated(object sender, DataGridItemEventArgs e)
    {
        try
        {
            if (HasValue(((DataRowView)e.Item.DataItem).Row["title"]))
            {
                if (!_showTitles)
                {
                    ((DataRowView)e.Item.DataItem).Row["title"] = String.Empty;
                }
                if (!_showLinks)
                {
                    ((DataRowView)e.Item.DataItem).Row["link"] = String.Empty;
                }
                if (!_showDescriptions)
                {
                    ((DataRowView)e.Item.DataItem).Row["description"] = String.Empty;
                }

            }
        }
        catch (Exception)
        {
            // do nothing
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Systems Engineer
United States United States
I am a technical architect/senior software engineer, technical trainer, entrepreneur.

I have worked in several sectors from healthcare, to entertainment and global intelligent traffic systems, using .Net, SQL, NoSQL and some of the latest technologies to deliver quality software systems for clients.

Past tech flavors include C#, WCF, SOA, MVC, MVVM, Silverlight, Assembler, Pascal, VB, Java/J2EE/EJB/JDBC, Perl, NLTK, TSQL, NoSQL, KendoUI, NodeJS, SignalR, Backbone JS, Angular JS, Latest .Net technologies, Amazon AWS...

Comments and Discussions