ASP 101 - Active Server Pages 101 - Web01
The Place ASP Developers Go!



Windows Technology Windows Technology
15 Seconds
4GuysFromRolla.com
ASP 101
ASP Wire
VB Forums
VB Wire
WinDrivers.com
internet.commerce internet.commerce
Partners & Affiliates
ASP 101 is an
internet.com site
ASP 101 is an internet.com site
IT
Developer
Internet News
Small Business
Personal Technology

Search internet.com
Advertise
Corporate Info
Newsletters
Tech Jobs
E-mail Offers

ASP 101 News Flash ASP 101 News Flash



 Top ASP 101 Stories Top ASP 101 Stories
An Overview of ASP.NET
Connections, Commands, And Procedures
What is ASP?

QUICK TIP:
Use AdExecuteNoRecords
Show All Tips >>
ASP 101 RSS Feed ASP 101 Updates


An ASP.NET RSS Feed Reader

by John Peterson

Introduction

A few months ago, I published an article (A MegaTokyo RSS Feed Reader) that showed how you could use classic ASP and Microsoft's XML parser to convert an RSS feed into HTML for display on a web page. While the code in that article worked fine, there were two main complaints that I seemed to keep hearing from readers:

  1. It was written in classic ASP and not ASP.NET.
  2. The format of the resulting HTML was a pain to change because I had hard-coded it into the script.

This time around I set out to address both of those issues.

If you're not familiar with RSS, you might find XML Files's RSS section helpful.

An ASP.NET RSS Feed Reader

If I was going to go through the trouble of doing this in ASP.NET, I was going to do it right and, while it is possible, I didn't want to call the COM objects that we used the first time around. This is .NET after all so naturally I wanted to use the .NET Framework's XmlDocument object. Aside from using the .NET object, this part of the script is basically the same. We create an XML object and load an XML file into it either from the remote server or from the file system.

Now to the formatting. Since I was basically starting from scratch anyway, I once again figured that I should take the time and do it right. So instead of all the string parsing and editing I did via VBScript the first time around, this time I set out to create an XSL stylesheet to handle the conversion from the RSS feed's XML format to the desired HTML format. The bad news is that my XSL skills are very weak and, while I knew how to use a stylesheet, actually writing one took me a lot longer than it should have. The good news is that after several tries I finally did get a couple different ones hammered out so you can see how easy it is to change the format of the resulting HTML. All you do is load a different stylesheet... it really couldn't be any simpler.

The last issue that I feel I should mention is that this time around I didn't have to write any caching code. I simply set the page to output cache and presto... instant caching... isn't ASP.NET great!

Why MegaTokyo?

Aside from the fact that they keep changing their format (I miss the thumbnails) and they keep forgetting to update their feed... why not? It's something I read and I want to know when it get's updated. Enough said. For those who haven't yet been there and have no idea what I'm talking about, you might want to visit MegaTokyo.

Despite the fact that I'm using MegaTokyo's feed, there's nothing in the code that should stop you from using it with most any RSS feed. You'll probably need to tweak the XSL files to get your feed to look how you want, but aside from that the script should work with most RSS feeds right "out of the box".

The Code

megatokyo_rss.aspx
<%@ Page Language="VB" Debug="False" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>
<%@ Import Namespace="System.Xml.Xsl" %>
<%@ OutputCache Duration="3600" VaryByParam="none" %>
<script language="VB" runat=server>
  Sub Page_Load(sender As Object, e As EventArgs)
    ' Using a live RSS feed... could also use a cached XML file.
    Dim strXmlSrc  As String = "http://www.megatokyo.com/rss/megatokyo.xml"
    'Dim strXmlSrc As String = Server.MapPath("megatokyo.xml")
    ' Path to our XSL file.  Changing the XSL file changes the
    ' look of the HTML output.  Try toggling the commenting on the
    ' following two lines to give it a try.
    Dim strXslFile As String = Server.MapPath("megatokyo.xsl")
    'Dim strXslFile As String = Server.MapPath("megatokyo2.xsl")
    ' Load our XML file into the XmlDocument object.
    Dim myXmlDoc As XmlDocument = New XmlDocument()
    myXmlDoc.Load(strXmlSrc)
    ' Load our XSL file into the XslTransform object.
    Dim myXslDoc As XslTransform = New XslTransform()
    myXslDoc.Load(strXslFile)
    ' Create a StringBuilder and then point a StringWriter at it.
    ' We'll use this to hold the HTML output by the Transform method.
    Dim myStringBuilder As StringBuilder = New StringBuilder()
    Dim myStringWriter  As StringWriter  = New StringWriter(myStringBuilder)
    ' Call the Transform method of the XslTransform object passing it
    ' our input via the XmlDocument and getting output via the StringWriter.
    myXslDoc.Transform(myXmlDoc, Nothing, myStringWriter)
    ' Since I've got the page set to cache, I tag on a little
    ' footer indicating when the page was actually built.
    myStringBuilder.Append(vbCrLf & "<p><em>Cached at: " _
        & Now() & "</em></p>" & vbCrLf)
    ' Take our resulting HTML and display it via an ASP.NET
    ' literal control.
    litMegaTokyoRssHtml.Text = myStringBuilder.ToString
  End Sub
</script>
<html>
<head>
  <title>ASP 101's ASP.NET MegaTokyo RSS Feed Reader</title>
</head>
<body>
<asp:Literal id="litMegaTokyoRssHtml" runat="server" />
</body>
</html>

Here are the listings for the two included XSL files as well:

megatokyo.xsl
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" /> 
  <xsl:template match="/">
    <xsl:for-each select="rss/channel/item">
      <p>
      <a href="{link}"><strong><xsl:value-of select="title" /></strong></a>
      <xsl:value-of disable-output-escaping="yes" select="description" />
      </p>
      <hr />
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

 

megatokyo2.xsl
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" /> 
  <xsl:template match="/">
    <xsl:for-each select="rss/channel">
      <h2><a href="{link}"><xsl:value-of select="title" /></a></h2>
    </xsl:for-each>
    <ul>
      <xsl:for-each select="rss/channel/item">
        <li><a href="{link}"><strong><xsl:value-of select="title" /></strong></a></li>
      </xsl:for-each>
    </ul>
  </xsl:template>
</xsl:stylesheet>

The Output

Just so you can see what you'll be getting, here are examples of what the output from each stylesheet looks like:

Sample megatokyo.xsl Output

Comic [614] - "I wish i could start over"

chapter 5, episode 80
[click to read]

[piro]
posted: 09.27.2004 [3:00 Pm EST]


Comic [613] - "but some girls like pathetic dorks"

chapter 5, episode 79
[click to read]

[piro]
posted: 09.24.2004 [11:00 am EST]


Comic [612] - "playing poorly"

chapter 5, episode 78
[click to read]

[piro]
posted: 09.22.2004 [12:34 am EST]


Cached at: 9/28/2004 1:01:00 PM

 

Sample megatokyo2.xsl Output

Megatokyo News

Cached at: 9/28/2004 1:01:00 PM

Download

For those who don't like cutting and pasting, you can download a zip file containing the ASP.NET code and the two XSL files from here: megatokyo_rss_aspx.zip (3.8 KB).

Related Information




Update: How to Show a Limited Number of Items from an RSS Feed

One of the most common questions I receive about the code on this page is how to limit the number of items displayed. For example, let's assume the RSS feed you are pulling in lists the last 20 items published, but you only want to display the 5 most recent items. Luckily, it's relatively easy to do. What's even better is that you can easily do it by creating a modified .XSL file. This means that you can easily display the abbreviated list in one place and the full list in another using the same script just by specifying a different style sheet file.

The change to the XSL files is quite simple. Here are the same two files presented above with the new restriction that limits the number of items displayed to the first 5 highlighted in red.

megatokyo_top5.xsl
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" /> 
  <xsl:template match="/">
    <xsl:for-each select="rss/channel/item[position()<=5]">
      <p>
      <a href="{link}"><strong><xsl:value-of select="title" /></strong></a>
      <xsl:value-of disable-output-escaping="yes" select="description" />
      </p>
      <hr />
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

 

megatokyo2_top5.xsl
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" /> 
  <xsl:template match="/">
    <xsl:for-each select="rss/channel">
      <h2><a href="{link}"><xsl:value-of select="title" /></a></h2>
    </xsl:for-each>
    <ul>
      <xsl:for-each select="rss/channel/item[position()<=5]">
        <li><a href="{link}"><strong><xsl:value-of select="title" /></strong></a></li>
      </xsl:for-each>
    </ul>
  </xsl:template>
</xsl:stylesheet>

The limiting command just says that the position of the element needs to be less then or equal to 5: [position()<=5]. The problem is that since this command is inside an XML-formatted file, we need to encode the < character as < to prevent it from causing problems.

That's all there is to it. I chose to display the first five items since I figured that would probably be similar to what most people are trying to do, but you can obviously change the criteria to whatever happens to fit your situation.




Update: How to Show Multiple RSS Feeds on One Page

I recently received an email asking how to display multiple RSS feeds on the same page. Here's the message:

John-

I really enjoyed your article on the RSS Feed Reader and it is by far the easiest solution I have found so far for displaying a RSS on a web page. I do have one question. Is it possible to have this code display multiple different RSS Feeds on the same page? Any insight into how this would be done would be great!

[ name removed to protect the innocent ;) ]

I receive a lot of this type of email. The approach is pretty much the same whether you're trying to do the same thing multiple times or trying to get one script to do multiple things. Either way, all you have to do is break things down into their fundamental steps and tackle each one individually. Once you've got each step working as it should, simply do them one after another.

This is where Subs and Functions are really useful. As an example, I've reorganized the code above into a structure which is better suited to be executed multiple times on the same page. Check out the code listing below:

multi_rss.aspx

<%@ Page Language="VB" Debug="False" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>
<%@ Import Namespace="System.Xml.Xsl" %>
<%@ OutputCache Duration="3600" VaryByParam="none" %>
<script language="VB" runat="server">

  Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
    litMegaTokyoRssHtml1.Text = GetTransformedRssFeed("http://www.megatokyo.com/rss/megatokyo.xml", "megatokyo.xsl")
    litMegaTokyoRssHtml2.Text = GetTransformedRssFeed("http://www.megatokyo.com/rss/megatokyo.xml", "megatokyo2.xsl")

    litGeneratedAt.Text = Now()
  End Sub

  Function GetTransformedRssFeed(ByVal strRssFeedUrl As String, ByVal strRssFeedTransformFile As String) As String
    ' Load our XML file into the XmlDocument object.
    Dim myXmlDoc As XmlDocument = New XmlDocument()
    myXmlDoc.Load(strRssFeedUrl)

    ' Load our XSL file into the XslTransform object.
    Dim myXslDoc As XslCompiledTransform = New XslCompiledTransform()
    myXslDoc.Load(Server.MapPath(strRssFeedTransformFile))

    ' Create a StringBuilder and then point a StringWriter at it.
    ' We'll use this to hold the HTML output by the Transform method.
    Dim myStringBuilder As StringBuilder = New StringBuilder()
    Dim myStringWriter As StringWriter = New StringWriter(myStringBuilder)

    ' Call the Transform method of the XslTransform object passing it
    ' our input via the XmlDocument and getting output via the StringWriter.
    myXslDoc.Transform(myXmlDoc, Nothing, myStringWriter)

    ' Return the resulting HTML
    Return myStringBuilder.ToString
  End Function
</script>
<html>
<head>
<title>ASP 101's ASP.NET MegaTokyo RSS Multi Feed Reader</title>
</head>
<body>

<table border="1">
  <tr>
    <td valign="top"><asp:Literal id="litMegaTokyoRssHtml1" runat="server" /></td>
    <td valign="top"><asp:Literal id="litMegaTokyoRssHtml2" runat="server" /></td>
  </tr>
</table>

<p><em>Page Generated at: <asp:Literal id="litGeneratedAt" runat="server" /></em></p>

</body>
</html>

Notice how I've moved the code that retrieves the RSS feed and transforms the result into HTML into its own function. Then I can simply call the function multiple times from the Page_Load subroutine. Each time I call it, I pass it parameters which indicate the appropriate feed location and XSLT file to use. The function then does its job and returns the resulting HTML to the line that called it. All that's left to do is to assign the function's return value (containing the HTML) to the appropriate literal control's Text property just as we did in the original version.

If you're not used to writing code this way, it can take a little getting used to. Once you do, you'll most likely find it easier to tackle more complex problems. If you take the time to break your large problem down into its fundamental pieces you'll realize that each piece by itself is a pretty easy problem to solve. The more complex a script, the more pieces you'll have to tackle, but just take them one at a time and you'll be done before you know it.

Some of you probably noticed that I didn't really break this problem down as far as I could have. If we really wanted to break things down to their fundamental pieces, I could have created one function to retrieve the RSS feed and another to apply the XSLT transformation. This approach would work just as well, but the tradeoff would have been that it would have added an additional function to the script. Since the script never retrieves an RSS feed without applying a transformation and never applys a transformation without first retrieving a feed, I decided this approach would be simpler and more readable. But, as is always the case, how you design your code will depend on your individual situation and needs.


Home |  News |  Samples |  Articles |  Lessons |  Resources |  Forum |  Links |  Search |  Feedback

Internet.com
The Network for Technology Professionals

Search:

About Internet.com

Legal Notices, Licensing, Permissions, Privacy Policy.
Advertise | Newsletters | E-mail Offers