ASP (VBScript) RSS reader/writer class

By | July 1, 2007

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):

  • Reading all kind of RSS formats (RSS 0.91, 0.92, 0.94, 1.0, 2.0 and ATOM)
  • Generating own feeds as RSS 2.0 (with UTF8)
  • Generation can be done directly into a file
  • XSLT can be applied to the feed
  • Feeds can be cached for a given amount of time (all visitors share the same cache).
  • Timeout for the request can be configured. (if server not responding, etc.)
  • Supports the simple Dublin Core elements (http://www.dublincore.org/)
  • easy to use programmers interface

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:

  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:

  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

  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

  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)

  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:

  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.

  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…

27 comments on “ASP (VBScript) RSS reader/writer class

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

    Microsoft VBScript runtime error ’800a01a8′

    Object required: ‘lib’

    /RSS.asp, line 163

    Any ideas?!
    Sam

  2. 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.

  3. John Altland on said:

    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

  4. @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…

  5. Glitch64 on said:

    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!

  6. Glitch64 on said:

    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.

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

    dany bay

  8. 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…

  9. Pingback: Web Dev Bros » Blog Archive » ajaxed 1.0 released

  10. 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

  11. 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.

  12. 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

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

  14. Is this open source? In the code it says “see license.txt in the root” but there’s no such file in the .zip

  15. 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/

  16. 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 … ?

  17. 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

    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….

  18. Danny on said:

    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?

    • @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

  19. 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

  20. 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

  21. 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.

  22. Lee Allan on said:

    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?

  23. 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.

  24. John Rangel on said:

    Hi Michal,

    Great work on the RSS Feed! I am working with it and I had a quick question. How does one format the date attribute in the RSS feed? when I try to format it with a formatdatetime function it spits out an error.

Leave a Reply

*

* Copy This Password *

* Type Or Paste Password Here *

33,886 Spam Comments Blocked so far by Spam Free Wordpress