Web Dev Bros

hot talk about web development

« »

ASP (VBScript) RSS reader/writer class

July 1, 2007, 9:51 pm by Michal

Once i was looking for a nice RSS class/component for ASP which allows me to read all kind of feed formats programmatically. In addition to the correct parsing it should also be able to create own feeds for publishing purposes. Unfortunately I could not find any component which fits those requirements in ASP and therefore written my own.
Due to the different versions of RSS (0.91, 0.92, 1.0, 2.0, etc.) and formats like ATOM it was not really easy to parse them all within one component. I needed to find the least common denominator which consists of the basic elements like feed title, feed description, feed published date, the feeds language and it published items. The items on the other hand must hold at least title, description, category, author, link and published date. This metadata is available but its occurrence is a bit different in e.g. ATOM and RSS. The component I have written consists of two VBScript classes (RSS and RSSItem) which supports the following features (download and documentation is at the bottom):

Before I keep going with the examples of how to use the class(es) here is a link to a demo I have quickly created on my ASP server. Play around and check if your feeds are being correctly recognized by the component.

RSS reader DEMO

Could the component parse your feed? If not please let me know so I can improve it. However, lets check how we use this tool. The following example creates an instance of the RSS class, requests the feed and loads all its information into the class' properties. The title of the feed is written to the response:

PLAIN TEXT ASP:
  1. <!--#include file="RSS.asp"-->
  2. set r = new RSS
  3. r.url = "http://syndication.thedailywtf.com/TheDailyWtf"
  4. r.load()
  5. if r.failed then
  6.    response.write("Could not load the feed.")
  7. else
  8.    response.write(r.title)
  9. end if

Interesting thing here is the failed property. Whenever a feed is requested it is necessary to check the failed property if the request has failed or not. If it failed it means that the feed could not be recognized as a valid (supported) feed, the server is not responding, the url does not exist, or the XML could not be parsed (and therefore is invalid). As we are requesting data from a kind of "untrusted" source it is a nice feature to display our user that the feed is currently not available. If the load was a success all properties are populated with the feeds data. Iterating through the items of the previous example looks the following:

PLAIN TEXT ASP:
  1. for each item in r.items.items
  2.    response.write(item.title)
  3.    response.write(month(item.publishedDate))
  4. next

Those lines iterate through the items (items is a dictionary which holds objects of type RSSItem). Nice feature here is that the date has already been converted into a VBScript date type and can be used within all date functions. In this example the month of the date is written out.
With this concept it is easily possible to request feeds and process them programmatically. E.g. storing them into the database, etc.

Using the cache

PLAIN TEXT ASP:
  1. <!--#include file="RSS.asp"-->
  2. <!--#include file="Cache.asp"-->
  3. set r = new RSS
  4. r.url = "http://www.webdevbros.net/feed/"
  5. r.setCache "h", 1
  6. r.load()
  7. if r.failed then
  8.    response.write("Could not load the feed.")
  9. else
  10.    response.write(r.description)
  11. end if

Caching can be turned on with the "setCache" method which requires the type of interval and the interval value (in the example 1 hour). This feed is stored now within the cache (see Caching class for ASP) on the server for 1 hour before it is requested again. All users share the same cache which means that only the first user will recognize the request and the others will already get it from the cache. The RSS class supports caching but it requires the Cache class for this feature. Just download it and include it like in the example.

Using XSLT for the feed

PLAIN TEXT ASP:
  1. <!--#include file="RSS.asp"-->
  2. set r = new RSS
  3. r.url = "http://www.webdevbros.net/feed/"
  4. r.draw("stylesheet.xsl")
  5. if r.failed then response.write("Could not load the feed.")

If you have your own XSL file for your feeds you can apply it with the draw() method. It grabs the feed, applies the given stylesheet and prints out the result to the response. As you can see there is again this check for the failed property. That is necessary because the same errors as with the load() method could happen. Additionally the transformations could have failed. It is also possible to use caching here, just as described before.

Generating an own feed (RSS 2.0)

PLAIN TEXT ASP:
  1. <!--#include file="RSS.asp"-->
  2. set r = new RSS
  3. r.title = "Freaky funky feed (FFF)"
  4. r.description = "another source for nonsense :)"
  5. r.publishedDate = now()
  6. r.language = "en"
  7. set it = new RSSItem
  8. it.title = "My first blog entry"
  9. it.description = "i am so freaky and can do <strong>html</strong>"
  10. it.publishedDate = dateAdd("d", -2, now())
  11. it.author = "f. freak"
  12. r.addItem(it)
  13. r.generate "RSS2.0", "/rss.xml"

This example generate a simple feed with one item. As you can see its necessary to use the RSSItem class. The generate() method generates a feed into a file called rss.xml. The method also returns the generated xmldom if you prefer to store the feed in a different way. E.g. you could output directly to the response with:

PLAIN TEXT ASP:
  1. r.generate("RSS2.0", empty).save(response)

Another example for the generation grabs an existing feed (in this case ATOM) and generates an RSS 2.0 version. Its somehow a tranformation which is therefore possible .. a nice side effect.

PLAIN TEXT ASP:
  1. <!--#include file="RSS.asp"-->
  2. set r = new RSS
  3. r.url = "http://www.webdevbros.net/feed/atom/"
  4. r.load()
  5. if not r.failed then r.generate "RSS2.0", "/rss.xml"

There is nothing to say more now :) Have fun with this component and feel free to use it. Just keep my credits ... I am looking forward to any enhancements from you guys and to the feedback. I am not an expert on feeds and therefore you might have some suggestions, improvements, etc.

Greetings from vienna.

Download RSS 1.0
RSS 1.0 Documentation
DEMO

NOTE: RSS class is part of the ajaxed library now!
check ajaxed library for a newer version...


1 Star2 Stars3 Stars4 Stars5 Stars (11 votes, average: 4.27 out of 5)
Loading ... Loading ... Category: classic ASP (VBScript)  |  Comment (RSS)  |  Trackback

25 Comments

  1. Sam says: July 6, 2007 at 4:21 pm

    Hi Michal, thanks for this, im getting an error:

    Microsoft VBScript runtime error '800a01a8'

    Object required: 'lib'

    /RSS.asp, line 163

    Any ideas?!
    Sam

    Reply to this comment
  2. Michal says: July 7, 2007 at 9:29 pm

    hi sam, this class is extracted from my framework which also includes the possibility to throw custom errors. This error comes up because the class wants to call the throwError function which it cannot find. Just take a look into the line where the error is thrown to see the reason. In your case its "lib.throwError("Title, Link and description are required.")". This means that if you want to generate a feed it is necessary to set the properties title, link and description of the feed.

    Reply to this comment
  3. John Altland says: August 9, 2007 at 3:34 pm

    Hi Michal,

    I've tried making the url field into an array to make the tool aggregate rss feeds into one giant list. The issue I'm having is that the items collection seems to reset with each rss feed. Here are my modifications to the load function ... do you know what else I would need to change to have this functionality work? - Thanks for anything.

    if theCache is nothing then
    for each address in url
    loadXML(getXMLHTTPResponse(address))
    next
    else
    for each address in url
    if address "" then
    cacheID = address & "|LOAD"
    cachedItem = theCache.getItem(cacheID)
    if cachedItem "" then
    'the cache for this method stores the data as xml and needs to be parsed again
    loadXML(cachedItem)
    else
    'load and save to cache
    xmlResponse = getXMLHTTPResponse(address)
    loadXML(xmlResponse)
    theCache.store cacheID, xmlResponse
    end if
    end if

    if failed then exit sub

    select case getRSSType()
    case "RSS1.0"
    readRSS("1.0")
    case "RSS2.0"
    readRSS("2.0")
    case "ATOM"
    readATOM()
    end select
    next
    end if

    Reply to this comment
  4. Michal says: August 12, 2007 at 7:04 pm

    @john: why dont you just create an instance for each feed an merge the items together? for this you dont need to change any of the code...

    Reply to this comment
  5. Glitch64 says: September 20, 2007 at 12:04 am

    Excellent work Michal. Now I just have to decide if I want to load the rss data into a db table for further "searching/filtering" or just slap the data into an array and do an old fashioned "do loop" for searching/filtering.

    This is almost EXACTLY what I was looking for (I did NOT want to write it myself...gotta love GOOGLE, a lazy man's paradise!)

    Thanks again!

    Reply to this comment
  6. Glitch64 says: September 20, 2007 at 12:07 am

    John, to make a giant list I'll define an array and simply call a new rss for each source I want (looping thru each and loading in my array). From there I'll call the array for the actual data.

    Reply to this comment
  7. Dany says: March 14, 2008 at 12:53 pm

    as to set up to 5 number the items es. iMaxResults = 5 items

    dany bay

    Reply to this comment
  8. cavone.com says: March 31, 2008 at 3:40 pm

    Hy all,
    To fix "lib.throwError" problem just add the following code in rss.asp:

    public ErrMessage ''[string] Error Message

    private Sub libthrowError(str)
    ErrMessage = str
    Response.Write ErrMessage
    end sub

    and then find & replace lib.throwError with libthrowError in the file...

    Reply to this comment
  9. Web Dev Bros » Blog Archive » ajaxed 1.0 released says: April 15, 2008 at 8:55 am

    [...] ajaxed has the right component inside. There is a full detailed article about this component here. PLAIN TEXT [...]

    Reply to this comment
  10. Reine says: May 15, 2008 at 11:21 am

    Hello Michel,

    I'm using my own RSS class at the moment, but would like to have one that can handle more feed type, like your.
    But when I tested one of my important feed-links in your demo page it failed.
    I don't know German but it looks like it's having problems extracting the field.
    Can you please have a look at this and email me back?

    Here is the feed: http://rss.bowlingdigital.com/bowling/?q=node/feed

    BRG Reine

    Reply to this comment
  11. Reine says: May 15, 2008 at 11:22 am

    I noticed that my xml tag was stripped in the last post...

    I don't know German but it looks like it's having problems extracting the pubDate field.

    Reply to this comment
  12. Michal says: May 15, 2008 at 12:05 pm

    reine i have to take a closer look into it .. but as i have recognized also IE does not recognized this feed. google reader does :)
    i will look into it. thanks for your feedback

    Reply to this comment
  13. Reine says: May 26, 2008 at 8:45 am

    Michal, how is it going, have you found any solution to my problem?

    Reply to this comment
  14. Steve says: June 18, 2008 at 11:27 pm

    Is this open source? In the code it says "see license.txt in the root" but there's no such file in the .zip

    Reply to this comment
  15. Michal says: June 19, 2008 at 3:24 am

    yeah it totally is ... you cannot find the license.txt because i have extracted the component from the ajaxed library .. just a small mistake. you might want to check the ajaxed library http://www.webdevbros.net/ajaxed/

    Reply to this comment
  16. Urs says: November 17, 2008 at 4:55 pm

    Great work - but a small question back to the first comment:

    i hav2 "set RSSFeed1 = new RSS" and "Set RSSFeed2 = new RSS"

    any suggestion how i "merge" them into on and sort them by date?

    Only solution in my mind: put every child of the xml in one array/new xml / Database and then sort the full array. But this will take a lot of processing time ... ?

    Reply to this comment
  17. Michal says: November 18, 2008 at 4:00 am

    Urs i would suggest you make use of the sortedlist from .net inside ASP (check http://stackoverflow.com/questions/156436/sorting-a-collection-in-classic-asp for details( and sort the items by date .. then you create another RSS feed. should work fine. some pseudocode

    PLAIN TEXT ASP:
    1. 'reading feeds and adding them to the sorted list
    2. 'so they get sorted automatically
    3. set list = server.createObject("System.Collections.Sortedlist")
    4. set feed1 = new RSS
    5. feed1.url = "http://...."
    6. if not feed1.failed then
    7.   for each i in feed1.items.items
    8.     list.add i.publishedDate, i
    9.   next
    10. end if
    11. set feed2 = new RSS
    12. feed2.url = "http://...."
    13. if not feed2.failed then
    14.   for each i in feed2.items.items
    15.     list.add i.publishedDate, i
    16.   next
    17. end if
    18.  
    19. 'creating our final feed
    20. set feed = new RSS
    21. for i = 0 to list.count - 1
    22.   feed.addItem(list.getByIndex(i))
    23. next
    24. 'write the feed to the respone
    25. feed.generate("RSS2.0", empty).save(response)
    26. 'alternatively you can write the feed to a file
    27. 'feed.generate "RSS2.0", "/feed/feed.xml"

    I haven tried the code so i am not sure if it works :) It could be that the sorted list cannot store ASP "objects". in this case you would need to create a lookup dictionary....

    Reply to this comment
  18. Danny says: July 20, 2009 at 9:32 pm

    Michal,

    Great job on this work. Work smoothly on most RSS.
    However, I tested on one RSS at your demo page (http://www.grafix.at/webdevbros/RSS/), putting this:

    http://www.maximumpc.com/articles/all/feed

    The images aren't showing up.

    Do you think it will be easy to add base url in the next version of your RSS class?

    Reply to this comment
    • Michal says: July 21, 2009 at 5:04 am

      @Danny: adding the base url should be not that big deal. However, I am really busy for the next time ... If you have some time you could extend it and I would release it as a new version. how does that sound? greets

      Reply to this comment
  19. Brian T says: September 11, 2009 at 3:12 pm

    can you show the code for the demo using ajax and the rss reader? its hard to see what is passed back in the code with just the output :) many thanks - great code too

    Reply to this comment
  20. Mike Mathewson says: October 14, 2009 at 6:34 am

    Michael -

    I’m using your ASP RSS Reader and I’ve run into a little problem. When reading ATOM feeds there are multiple parameters for each item. I’m tring to get the link that is directed back to the item which has an attribute rel=’alternate’. Unfortunately the script pulls up the first LINK which is typically ‘rel=self’ which is a link back to the feed file. I’ve tried playing around with your script but can’t figure out a way to access this alternate link. Do you know if there is a way or do you have any other tools you can direct me to? Thank you very much for your help – Mike

    Reply to this comment
  21. Mike Mathewson says: October 16, 2009 at 4:16 am

    Figured it out, for those that are interested here's the solution:

    RSS.asp in the readATOM section

    replace this line:

    .link = getAttribute(n, "link", "href")

    with:

    .link = getAttribute(n, "link[@rel='alternate']", "href")

    Now when ATOM feeds are read, the returned link will be the link back to the URL of the item instead of the ATOM feed file.

    Reply to this comment
  22. Lee Allan says: October 20, 2009 at 10:37 pm

    Thank you for posting this. It has been very helpful.
    I am having trouble with a feed that has an array of category fields for each -item.
    I have tried adding an array definition to the dictionary, and that did not work. Also tried to enumerate the r.items an could not get that to work. I obviously don't know how to reference the child array of item->category. Do you have a suggestion?

    Reply to this comment
  23. Mike Mathewson says: October 21, 2009 at 6:02 am

    Lee -
    I don't do anything with the category field so I haven't worked on that problem. I was only able to figure out my last problem by scouring over code samples that I could dig up on the web. In my searching I don't recall seeing anything that wold help you - sorry.

    Reply to this comment

Leave a Reply

Click here to cancel reply.

Entries (RSS) and Comments (RSS). Valid XHTML and CSS.
Powered by WordPress and Fluid Blue theme.
Mobilize:
images: on /off
Save this page at PhoneFavs.

Original version.
Mobilized by PhoneFavs