After a long search on internet, I finally thought I have to write this RSS Aggregator Web Part that works for both Atom and RSS Formats.
First, I would like to give credit to this post by Sahil Malik which gave me the kick start.
Next, read my previous blog to understand the differences between RSS and Atom XML structure as I will be using the base of them to retrieve both blogger posts.
Now that we have our basic understanding lets jump in to the code. I am using the same css class names here since I wanted to mimic the same way as the outbox RSS Webpart. You can have your own incase you need.
We will be using 3 classes here; 1. Webpart Class, 2. Class for RSSFeed 3. Class for RSSItem and 1 JS file. Ofcourse, this code is in working condition, however its not clean. You might want to look at the redundant variable declarations.
JS: _____________________________________________________________
Variable Declarations: _______________________________________________
WebPart: ________________________________________________________
RSSFeed Class: ___________________________________________________________
RSS Item Class: ____________________________________________________________
First, I would like to give credit to this post by Sahil Malik which gave me the kick start.
Next, read my previous blog to understand the differences between RSS and Atom XML structure as I will be using the base of them to retrieve both blogger posts.
Now that we have our basic understanding lets jump in to the code. I am using the same css class names here since I wanted to mimic the same way as the outbox RSS Webpart. You can have your own incase you need.
We will be using 3 classes here; 1. Webpart Class, 2. Class for RSSFeed 3. Class for RSSItem and 1 JS file. Ofcourse, this code is in working condition, however its not clean. You might want to look at the redundant variable declarations.
JS: _____________________________________________________________
<script type="text/javascript">
function switchMenu(obj) {
var el = document.getElementById(obj);
if (el.style.display != 'none') {
el.style.display = 'none';
}
else {
el.style.display = '';
}
CollapseAllDivs(el);
}
function CollapseAllDivs(sDiv) {
var rollUpContainer = document.getElementById('rollUpContainer');
var div = rollUpContainer.getElementsByTagName('div');
for(i = 0; i < div.length; i++) {
if (div[i].id.match("rssAgg") != null) {
var getDiv = document.getElementById(div[i].id);
if (sDiv.id != getDiv.id) {
getDiv.style.display = 'none';
}
}
}
}
</script>
Variable Declarations: _______________________________________________
private string rssUrl;
private string feedName;
private const string constDefFeedLimitValue = "5";
private string feedLimit = constDefFeedLimitValue;
private int feedLmt;
WebPart: ________________________________________________________
public class RssFeedAggregator : System.Web.UI.WebControls.WebParts.WebPart
{
private string rssUrl;
private string feedName;
private const string constDefFeedLimitValue = "5";
private string feedLimit = constDefFeedLimitValue;
private int feedLmt;
public RssFeedAggregator()
{
this.ExportMode = WebPartExportMode.All;
}
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;
string parameterToken;
writer.Write("<div id=\"rollUpContainer\">");
foreach (RssItem singleRssItem in feed)
{
if (i < feedLmt)
{
parameterToken = "rssAgg" + i;
writer.Write("<div id=\"rollUp\" class=\"slm-layout-main\">");
writer.Write("<table width=\"100%\">");
writer.Write("<tr>");
writer.Write("<td width=\"100%\" align=\"left\">");
writer.Write("<table width=\"100%\">");
writer.Write("<tr><td width='100%' class=\"groupheader item medium\">");
writer.Write("<a href='" + singleRssItem.BlogLink.ToString() + "' target='_blank'>" + singleRssItem.BlogTitle + "</a>");
writer.Write("</td>");
writer.Write("</tr>");
writer.Write("<tr><td width='100%' class=\"item link-item\">");
writer.Write("<a href=\"javascript:switchMenu('" + parameterToken + "');\">" + singleRssItem.Title + "</a>");
writer.Write("</td>");
writer.Write("</tr>");
writer.Write("</table>");
writer.Write("</td>");
writer.Write("</tr>");
writer.Write("</table>");
writer.Write("</div>");
if(i > 0)
writer.Write(string.Format(@"<div id='{0}' style='display:none'>", parameterToken));
else
writer.Write(string.Format(@"<div id='{0}'>", parameterToken));
writer.Write("<table><tr><td><div class=\"description\">");
writer.Write(singleRssItem.Body);
writer.Write("</div></td></tr>");
writer.Write("</table>");
writer.Write("</div>");
i++;
}
}
writer.Write("</div>");
}
public string FeedName
{
get
{
return feedName;
}
set
{
feedName = value;
}
}
[WebBrowsable(true),
Personalizable(true),
Category("RSS Properties"),
DisplayName("RSS Feed Url(s)"),
WebDisplayName("RSS Feed Url(s)"),
Description("Use ';' Character For Multiple Feed(s)")]
public string FeedURL
{
get
{
return rssUrl;
}
set
{
rssUrl = value;
}
}
[WebBrowsable(true)]
[Personalizable(true),
Category("RSS Properties"),
DisplayName("Feed Limit"),
WebDisplayName("Feed Limit"),
Description("Feed Limit"),
DefaultValue(constDefFeedLimitValue)]
public string FeedLimit
{
get
{
return feedLimit;
}
set
{
feedLimit = value;
}
}
}
RSSFeed Class: ___________________________________________________________
internal class RssFeed : List<RssItem>
{
private XmlDocument xDoc;
internal RssFeed(string RssURL)
{
if (RssURL == null)
{
this.Add(new RssItem());
}
else
{
string[] rssUrlsArray = RssURL.Split(new char[] { ';' });
foreach (string url in rssUrlsArray)
{
try
{
xDoc = new XmlDocument();
XmlTextReader xRead = new XmlTextReader(url);
xDoc.Load(xRead);
if (IsRss(xDoc))
ReadRssFeed(xDoc);
else
AtomFeed(xDoc);
}
catch (Exception)
{
this.Add(new RssItem());
}
}
}
}
internal bool IsRss(XmlDocument xDoc)
{
XmlNodeList xNodes = xDoc.GetElementsByTagName("rss");
if (xNodes.Count > 0)
return true;
else
return false;
}
internal void ReadRssFeed(XmlDocument rssDoc)
{
string blogTitle = string.Empty;
string blogLink = string.Empty;
XmlNodeList xNodesHeader = rssDoc.SelectNodes("./rss/channel");
foreach (XmlNode xNode in xNodesHeader)
{
blogTitle = HttpUtility.HtmlEncode(xNode.SelectSingleNode("./title").InnerText);
blogLink = xNode.SelectSingleNode("./link").InnerText;
}
XmlNodeList xNodes = rssDoc.SelectNodes("./rss/channel/item");
foreach (XmlNode xNode in xNodes)
{
this.Add(new RssItem(xNode, blogTitle, blogLink));
}
}
internal void AtomFeed(XmlDocument atomDoc)
{
string blogTitle = string.Empty;
string blogLink = string.Empty;
XmlNodeList xNodesHeader = atomDoc.GetElementsByTagName("feed");
foreach (XmlNode xNode in xNodesHeader)
{
if (xNode["title"] != null)
blogTitle = HttpUtility.HtmlEncode(xNode["title"].InnerText);
if (xNode["link"] != null)
blogLink = xNode["link"].InnerText;
}
XmlNodeList xNodes = atomDoc.GetElementsByTagName("entry");
foreach (XmlNode xNode in xNodes)
{
this.Add(new RssItem(xNode, true, GetHrefLink(xNode), blogTitle, blogLink));
}
}
internal string GetHrefLink(XmlNode xNode)
{
string ret = string.Empty;
for (int iCount = 0; iCount < xNode.ChildNodes.Count; iCount++)
{
if (xNode.ChildNodes[iCount].Name.ToLower() == "link")
{
if (xNode.ChildNodes[iCount].Attributes["rel"].Value.ToLower() == "alternate")
{
ret = xNode.ChildNodes[iCount].Attributes["href"].Value.ToString();
}
}
}
return ret;
}
}
RSS Item Class: ____________________________________________________________
internal class RssItem
{
private string title;
private string href;
private string body;
private string tags;
private DateTime pubDate;
private string blogTitle;
private string blogLink;
public string Href
{
get { return href; }
}
public string Title
{
get { return title; }
}
internal RssItem()
{
title = "No Data 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; }
}
public string BlogTitle
{
get { return blogTitle; }
set { blogTitle = value; }
}
public string BlogLink
{
get { return blogLink; }
set { blogLink = value; }
}
internal RssItem(XmlNode xNode, string sBlogTitle, string sBlogLink)
{
title = xNode.SelectSingleNode("./title").InnerText;
href = xNode.SelectSingleNode("./link").InnerText;
body = FixDesc(xNode.SelectSingleNode("./description").InnerText, href);
pubDate = Convert.ToDateTime(xNode.SelectSingleNode("./pubDate").InnerText);
XmlNodeList nodeList = xNode.SelectNodes("./category");
foreach (XmlNode node in nodeList)
{
tags = tags + " " + node.InnerText;
}
BlogTitle = sBlogTitle;
blogLink = sBlogLink;
}
internal RssItem(XmlNode xNode, bool isAtom, string hrefUrl, string sBlogTitle, string sBlogLink)
{
if (xNode["title"] != null)
title = xNode["title"].InnerText;
if(!string.IsNullOrEmpty(hrefUrl))
href = hrefUrl;
else
{
if (xNode["link"] != null)
{
href = xNode["link"].Attributes["href"].Value.ToString();
}
}
if (xNode["content"] != null)
body = FixDesc(xNode["content"].InnerText, href);
if (xNode["published"] != null)
pubDate = Convert.ToDateTime(xNode["published"].InnerText);
if (xNode["category"] != null)
{
tags = xNode["category"].Attributes["term"].Value.ToString();
}
BlogTitle = sBlogTitle;
BlogLink = sBlogLink;
}
public string FixDesc(object desc, object link)
{
if (link == null desc == null) return String.Empty;
string description = desc.ToString();
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) + "<br><a href=" + link.ToString() + " target='_blank'>More...</a>";
}
return stripDesc;
}
}
Comments
Anna
http://codename-srini.blogspot.com/2010/07/rss-aggregator-web-part-for-sharepoint.html