Updated SharePoint RSS Aggregator Web Part
I've decided to start using CodePlex so I uploaded SharePoint RSS Aggregator Web Part that I posted some months earlier (http://dotnet.org.za/zlatan/archive/2008/06/06/multiple-rss-aggregator-web-part-example.aspx).
I took this opportunity to update the web part as well (actually on request from some people that are using it), so I changed it to use LINQ for parsing the XML data.
I also fixed up a small issue with filtering tag/category terms.
Here's the link to the Codeplex project were you can download the wsp file and source code:
http://www.codeplex.com/RSSAggregator
Here's the code as well:
using System;
using System.Runtime.InteropServices;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Serialization;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;
using System.Collections.Generic;
using System.Xml;
using System.Text.RegularExpressions;
using System.ComponentModel;
using System.Xml.Linq;
using System.Net;
using System.Text;
namespace RSSAggregator
{
[Guid("561df9ae-1742-4d17-9a88-5548f05bff25")]
public class RSSAggregator : System.Web.UI.WebControls.WebParts.WebPart
{
private string rssUrl;
private string feedName;
private const string constDefFeedCriteriaValue = "SAArchitect";
private string filterCriteria = constDefFeedCriteriaValue;
private const string constDefFeedLimitValue = "5";
private string feedLimit = constDefFeedLimitValue;
private int feedLmt;
private string tagValue;
public RSSAggregator()
{
}
protected override void RenderContents(System.Web.UI.HtmlTextWriter writer)
{
try
{
feedLmt = Convert.ToInt32(feedLimit);
}
catch (Exception)
{
feedLmt = 0;
}
RssFeed feed = new RssFeed(rssUrl);
feed.Sort(delegate(RssItem r1, RssItem r2)
{
return r2.PubDate.CompareTo(r1.PubDate);
});
int i = 0;
foreach (RssItem singleRssItem in feed)
{
if (i < feedLmt)
{
if (singleRssItem.Tags != null)
{
if (filterCriteria != null)
tagValue = singleRssItem.Tags.ToLower();
if (tagValue.Contains(filterCriteria) == true || filterCriteria == null)
{
writer.Write("<div class=\"container\">");
writer.Write("<font size=\"4\" face=\"Verdana\"><b><a href =\"");
writer.Write(singleRssItem.Href);
writer.Write("\"><font size=\"2\" face=\"Verdana\">");
writer.Write(singleRssItem.Title);
writer.Write("</a></b></font>");
writer.Write("<div class=\"module-content\"><table width=\"100%\" border=\"0\"><tr><td><font size=\"2\" face=\"Verdana\">");
writer.Write(singleRssItem.Body);
writer.Write("</font></td></tr></table></div>");
writer.Write("</div>");
writer.Write("<div class=\"module-content\"><table width=\"100%\" border=\"0\"><tr><td><font size=\"2\" face=\"Verdana\">");
writer.Write(singleRssItem.Tags);
writer.Write("</font></td></tr></table></div>");
writer.Write("</div>");
writer.Write("<div class=\"module-content\"><table width=\"100%\" border=\"0\"><tr><td><font size=\"2\" face=\"Verdana\">");
writer.Write(singleRssItem.PubDate.ToString());
writer.Write("</font></td></tr></table></div>");
writer.Write("</div>");
i++;
}
}
}
}
}
public string FeedName
{
get
{
return feedName;
}
set
{
feedName = value;
}
}
[WebBrowsable(true),
Personalizable(true),
Category("RSS Aggregator Web Part"),
DisplayName("URLs of the Feed"),
WebDisplayName("URLs of the Feed"),
Description("Please enter the URLs of the feed separated by ';' character.")]
public string FeedURL
{
get
{
return rssUrl;
}
set
{
rssUrl = value;
}
}
[WebBrowsable(true),
Personalizable(true),
Category("RSS Aggregator Web Part"),
DisplayName("Filter Criteria"),
WebDisplayName("Filter Criteria"),
Description("Please enter the tag value you wish to filter on for desired RSS feeds."),
DefaultValue(constDefFeedCriteriaValue)]
public string FilterOn
{
get
{
return filterCriteria.ToLower();
}
set
{
filterCriteria = value.ToLower();
}
}
[WebBrowsable(true)]
[Personalizable(true),
Category("RSS Aggregator Web Part"),
DisplayName("Feed Limit"),
WebDisplayName("Feed Limit"),
Description("Defines the list the web part will read from."),
DefaultValue(constDefFeedLimitValue)]
public string FeedLimit
{
get
{
return feedLimit;
}
set
{
feedLimit = value;
}
}
}
internal class RssFeed : List<RssItem>
{
private XElement rssDoc;
internal RssFeed(string RssURL)
{
if (RssURL == null)
{
this.Add(new RssItem());
}
else
{
string[] rssUrlsArray = RssURL.Split(new char[] { ';' });
foreach (string url in rssUrlsArray)
{
try
{
WebClient client = new WebClient();
byte[] byteData = client.DownloadData(url);
string strData = Encoding.UTF8.GetString(byteData);
rssDoc = XElement.Parse(strData);
foreach (var elm in rssDoc.Descendants("item"))
{
this.Add(new RssItem(elm));
}
}
catch (Exception)
{
this.Add(new RssItem());
}
}
}
}
}
internal class RssItem
{
private string title;
private string href;
private string body;
private string tags;
private DateTime pubDate;
public string Href
{
get { return href; }
}
public string Title
{
get { return title; }
}
internal RssItem()
{
title = "Feed not available at this time";
href = "~";
}
public string Body
{
get { return body; }
set { body = value; }
}
public string Tags
{
get { return tags; }
set { tags = value; }
}
public DateTime PubDate
{
get { return pubDate; }
set { pubDate = value; }
}
internal RssItem(XElement xNode)
{
if (xNode.NodeType == XmlNodeType.CDATA)
{
XCData titleCData = xNode.FirstNode as XCData;
title = titleCData.Value;
}
else
title = (string)xNode.Element("title").Value;
if (xNode.NodeType == XmlNodeType.CDATA)
{
XCData linkCData = xNode.FirstNode as XCData;
href = linkCData.Value;
}
else
href = (string)xNode.Element("link").Value;
if (xNode.NodeType == XmlNodeType.CDATA)
{
XCData bodyCData = xNode.FirstNode as XCData;
body = FixDesc(bodyCData.Value, href);
}
else
body = FixDesc((string)xNode.Element("description").Value, href);
pubDate = Convert.ToDateTime((string)xNode.Element("pubDate").Value);
foreach (XElement node in xNode.Elements("category"))
{
if (node.NodeType == XmlNodeType.CDATA)
{
XCData categoryCData = node.FirstNode as XCData;
if (tags == null)
tags = (string)categoryCData.Value;
else
tags = tags + ", " + (string)categoryCData.Value;
}
else
{
if (tags == null)
tags = (string)node.Value;
else
tags = tags + ", " + (string)node.Value;
}
}
}
public string FixDesc(object desc, object link)
{
if (link == null || desc == null) return String.Empty;
string description = desc.ToString();
//Replace all HTML tags so none get cut-off and screw up the page
Regex reg = new Regex("<.*?>", RegexOptions.Compiled);
string stripDesc = reg.Replace(description, String.Empty);
if (stripDesc.Length > 250)
{
int startPos = 250;
char[] chars = stripDesc.ToCharArray();
char c = chars[startPos];
while (!Char.IsWhiteSpace(c) && startPos < chars.Length)
{
startPos++;
c = chars[startPos];
}
stripDesc = new String(chars, 0, startPos) + " ... <a href='" + link.ToString() + "'> More</a>";
}
return stripDesc;
}
}
}