Hello all, I'm attaching a 'beta' RSS parsing search which will currently parse valid RSS .9, .91, .92, 1.0, 2.0 and many other RDF feeds. If anyone can provide me with links to other RSS version feeds, I'll be happy to TRY to make it capable of working with all of them. :)
[Usage]: rssx url-of-rss-feed [Variables]: //the number of milliseconds between 'popping' the next //rss feed result in the popup box. This will set the //popup timeout to 5 seconds: rssxTimeOutAfter = 5000; [Examples]: rssx http://ReliableAnswers.com/rss.asp rssx http://ReliableAnswers.com/jobs/news-rss.asp rssx http://slashdot.org/slashdot.rdf rssx http://royo.is-a-geek.com/SiteFeeder/GetFeed.aspx?FeedId=30 rssx http://regexlib.com/Rss.aspx rssx http://royo.is-a-geek.com/SiteFeeder/GetFeed.aspx?FeedId=42 rssx http://www.lockergnome.com/lockergnome.xml rssx http://royo.is-a-geek.com/SiteFeeder/GetFeed.aspx?FeedId=27 rssx http://news.netcraft.com/index.rdf rssx http://www.benmeadowcroft.com/rss/weblog.rdf rssx http://www.eff.org/rss/press.xml rssx http://www.vbaccelerator.com/home/The_Site/Indexes/RSS_Feeds/WhatsNew/ rss.xml rssx http://www.mvps.org/emorcillo/news.xml [Advanced]: One of the nifty things about this search is that you can 'daisy-chain' this search one after another in the box or in code and it'll append the popups to the end of the queue. If you want to have it display a dozen RSS feeds from different sources every hour you can put this code in your localprefs (untested, but it stands to logic): function myfeeds(){ rssx http://ReliableAnswers.com/rss.asp rssx http://ReliableAnswers.com/jobs/news-rss.asp rssx http://slashdot.org/slashdot.rdf rssx http://royo.is-a-geek.com/SiteFeeder/GetFeed.aspx?FeedId=30 rssx http://regexlib.com/Rss.aspx rssx http://royo.is-a-geek.com/SiteFeeder/GetFeed.aspx?FeedId=42 rssx http://www.lockergnome.com/lockergnome.xml rssx http://royo.is-a-geek.com/SiteFeeder/GetFeed.aspx?FeedId=27 rssx http://news.netcraft.com/index.rdf rssx http://www.benmeadowcroft.com/rss/weblog.rdf rssx http://www.eff.org/rss/press.xml rssx http://www.vbaccelerator.com/home/The_Site/Indexes/RSS_Feeds/WhatsNew/ rss.xml rssx http://www.mvps.org/emorcillo/news.xml setTimeout("myfeeds()",3600000); } myfeeds(); [Problem / Why it's Beta]: Here's the crux. I've got it working for all but one of the RSS feeds I had in my RSS collection (which is dozens of feeds from various sources). BEWARE attempting to test it using this feed, since it WILL crash DQSD, and probably Windows while it's at it. The crash occurs immediately upon calling send() from the xmlhttp object. I don't know why. In fact, I have ABSOLUTELY NO idea (which is strange for me). It just stalls, freezing up everything. I'm using asynchronous calls and spiffy function loading, array chaining, every optimization I can think of to make this code sweet, portable, dynamic and effective, while using the smallest footprint (and yes, 11 kb of code WAS really necessary to make this thing parse that wide a variety of RSS feeds). Are you ready for a laugh? The only feed that it COULD NOT parse is the syndication feed FROM THE W3C: rssx http://www.w3.org/2000/08/w3c-synd/home.rss For some reason their server doesn't respond to the xmlhttp object, but it will to PERL GET, IE, Mozilla, Netscape and other shtuff. I've played with the headers but just can't get it to work. :( Oh, and I do not *think* it is the stylesheet that they've embedded, since it should *still* return something to the client (and make it as far as the 'finished loading' onreadystatechange=4), but it doesn't. It just freezes immediately upon send(). The Ben Meadowcroft site ( http://www.benmeadowcroft.com/rss/weblog.rdf ), for example, uses a stylesheet as well, but my code processes and returns correctly. Any advice/thoughts are very much appreciated! Regards, Shawn K. Hall http://ReliableAnswers.com/ '// ======================================================== "I have discovered that all human evil comes from this, man's being unable to sit still in a room." -- Blaise Pascal (1623 - 1662)
<search function="rssx"> <name>RSS Feed Parser</name> <description>Parses an RSS feed and pops the results every 8 seconds (configurable). <div class="helpboxDescLabels">Switches:</div> <table class="helpboxDescTable"> <tr><td>url</td><td> - </td><td> URL of RSS Feed to process. </td></tr> </table> <div class="helpboxDescLabels">Examples:</div> <table class="helpboxDescTable"> <tr><td>rssx http://ReliableAnswers.com/rss.asp</td></tr> </table> </description> <category>Functions</category> <link>http://ReliableAnswers.com/x/dqsd/</link> <contributor>Shawn K. Hall</contributor> <script><![CDATA[ function rssx(q){ if( q == "?" ){ qsfind("rssx /function"); return false; } var sUrl = ((isURL(q)) ? q : "http://reliableanswers.com/rss.asp"); try{ //attempt to obtain the remote RSS feed var xmlHttp = new ActiveXObject("Microsoft.XmlHttp"); xmlHttp.onreadystatechange = function() { if (xmlHttp.readyState==4) { rssxXmlParser( xmlHttp, sUrl ); } }; xmlHttp.open("GET", sUrl, true); xmlHttp.setRequestHeader ( "Accept", "application/xml, text/xml, text/rss, application/xml+rdf, */*" ); xmlHttp.setRequestHeader ( "User-Agent", "Mozilla/4.0 (compatible; DQSD ( http://www.dqsd.net/ ); rssx Search ( http://ReliableAnswers.com/x/dqsd/ ))" ); xmlHttp.send(null); }catch(e){ alert("RSSX: Failure!\n" + e.number + "::" + e.description); } } function rssxXmlParser( xmlHttp, sUrl ){ var sBuild = ""; try{ //get the response content from the remote site var sBody = xmlHttp.responseText; sBody = sBody.replace(/(\<\?xml-stylesheet[^>]*>)/gim,"<!-- $1 -->"); var xBody = new ActiveXObject("MSXML2.DOMDocument"); xBody.loadXML( sBody ); if(xBody.parseError.errorCode != 0) throw new Error(0, "RSS is not well-formed.\nParse error: " + xBody.parseError.reason + " line: " + xBody.parseError.line.toString() + ", col: " + xBody.parseError.linepos.toString() + "\n" + xBody.parseError.srcText); //parse it var xElement = xBody.documentElement; //rss version, capabilities and format //default paths and properties var rDate = "pubdate"; var rLanguage= ""; var rItems = "item"; var rImage = "image"; var rInput = "textinput"; var rVersion = ""; var rSyPeriod= ""; var rSyFreq = ""; var rContent = ""; var rsTitle = ""; var rsImage = ""; var rsLink = ""; //document element name var rDocElem = xElement.nodeName; //version="1.0" xNode = xElement.attributes.getNamedItem("version"); if (xNode != null) rVersion = xNode.nodeTypedValue; switch (rVersion){ case "": rItems = "item"; rImage = "image"; rInput = "textinput"; break; case "0.9": case "0.91": case "0.92": case "1.0": case "2.0": default: rItems = "channel/item"; rImage = "channel/image"; rInput = "channel/textinput"; break; } //xmlns="http://purl.org/rss/1.0/" xNode = xElement.attributes.getNamedItem("xmlns"); var rXmlns = ((xNode != null) ? xNode.nodeTypedValue : ""); //xmlns:dc="http://purl.org/dc/elements/1.1/" xNode = xElement.attributes.getNamedItem("xmlns:dc"); var rXmlnsDc = ((xNode != null) ? xNode.nodeTypedValue : ""); if (rXmlnsDc != "") { rDate = "dc:date"; xNode = xElement.selectSingleNode("channel"); if (xNode != null) { xNodeSub = xNode.selectSingleNode("dc:language"); if (xNodeSub != null) rLanguage = xNodeSub.nodeTypedValue; } } //xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xNode = xElement.attributes.getNamedItem("xmlns:rdf"); var rXmlnsRdf= ((xNode != null) ? xNode.nodeTypedValue : ""); //xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xNode = xElement.attributes.getNamedItem("xmlns:sy"); var rXmlnsSy = ((xNode != null) ? xNode.nodeTypedValue : ""); if (rXmlnsSy != "") { xNode = xElement.selectSingleNode("channel"); if (xNode != null) { xNodeSub = xNode.selectSingleNode("sy:UpdatePeriod"); if (xNodeSub != null) rSyPeriod = xNodeSub.nodeTypedValue; xNodeSub = xNode.selectSingleNode("sy:UpdateFrequency"); if (xNodeSub != null) rSyFreq = xNodeSub.nodeTypedValue; } } //xmlns:content="http://purl.org/rss/1.0/modules/content/" xNode = xElement.attributes.getNamedItem("xmlns:content"); var rXmlnsContent = ((xNode != null) ? xNode.nodeTypedValue : ""); if (rXmlnsContent != "") rContent = "content:encoded"; //obtain image/title/link properties xNode = xElement.selectSingleNode( rImage ); if (xNode != null) { xNodeSub = xNode.selectSingleNode("title"); if (xNodeSub != null) rsTitle= xNodeSub.nodeTypedValue; xNodeSub = xNode.selectSingleNode("url"); if (xNodeSub != null) rsImage= xNodeSub.nodeTypedValue; xNodeSub = xNode.selectSingleNode("link"); if (xNodeSub != null) rsLink = xNodeSub.nodeTypedValue; } //enumerate RSS items var xNodes = xElement.selectNodes( rItems ); for (i=0; i < xNodes.length; i++){ //get variables for this resource var xNode = xNodes.item(i); xNodeSub = xNode.selectSingleNode("title"); var sTitle= ((xNodeSub != null) ? xNodeSub.nodeTypedValue : ""); xNodeSub = xNode.selectSingleNode("description"); var sDesc = ((xNodeSub != null) ? xNodeSub.nodeTypedValue : ""); sDesc = sDesc.replace(/<a[\s]*[^>]href="([^"]+)"[^>]*>/gim,"<a onClick=\"window.parent.openSearchWindow('$1')\">"); xNodeSub = xNode.selectSingleNode("link"); var sLink = ((xNodeSub != null) ? xNodeSub.nodeTypedValue : ""); if (sLink == ""){ xNodeSub = xNode.selectSingleNode("guid"); var sLink = ((xNodeSub != null) ? xNodeSub.nodeTypedValue : ""); } if (rContent != ""){ xNodeSub = xNode.selectSingleNode( rContent ); var sContent = ((xNodeSub != null) ? xNodeSub.nodeTypedValue : ""); sContent = sContent.replace(/<a[\s]*[^>]href="([^"]+)"[^>]*>/gim,"<a onClick=\"window.parent.openSearchWindow('$1')\">"); }else{ var sContent = ""; } //append this record sBuild = ""; sBuild+= "<table width=\"100%\" border=\"0\" onClick=\"window.parent.openSearchWindow('" + sLink + "')\"><tr>"; if (rsLink != ""){ sBuild+= "<td width=\"5%\">"; sBuild+= "<a href=\"" + rsLink + "\" title=\"" + rsTitle + "\">"; if (rsImage != ""){ sBuild+= "<img src=\"" + rsImage + "\" border=\"0\" />"; }else{ sBuild+= rsTitle; } sBuild+= "</a></td>"; }else{ sBuild+= "<td width=\"5%\">"; sBuild+= "<a href=\"http://reliableanswers.com/x/dqsd/?rss=" + sUrl + "\">"; if (rsImage != ""){ sBuild+= "<img src=\"" + rsImage + "\" border=\"0\" />"; }else{ sBuild+= "[RSSX]"; } sBuild+= "</a></td>"; } sBuild+= "<td>"; sBuild+= "<p align=\"left\"><b>" + sTitle + "</b></p>"; sBuild+= "</td></tr>\n"; sBuild+= "<tr><td colspan=\"2\">"; sBuild+= "<p>" + sDesc + "</p>"; if (sContent != ""){ sBuild+= "<hr />" + sContent; } sBuild+= "</td></tr>\n"; sBuild+= "</table>\n\n"; rssxSearchArray[rssxSearchArray.length] = sBuild; } if (rssxSearchArray.length > 0){ if (rssxDisplayAgain == false) displayRssxSearchPopup(); } }catch(e){ alert("RSSX: Failure!\n" + e.number + "::" + e.description); } } var rssxSearchPopup; var rssxSearchIndex = 0; var rssxSearchArray = Array(); var rssxDisplayAgain= false; var rssxSearchURL = ''; if (typeof rssxTimeOutAfter == "undefined") rssxTimeOutAfter = 6000; function displayRssxSearchPopup(){ if (typeof rssxTimeOutAfter == "undefined") rssxTimeOutAfter = 8000; var windowW = 380; rssxSearchPopup = window.createPopup(); var rssxContent = rssxSearchArray[0]; rssxSearchArray = rssxSearchArray.slice(1); var rssxSearchPopupBody = rssxSearchPopup.document.body; var rssxSearchPopupBodyCode = "<html><head></head><body>"; rssxSearchPopupBodyCode += "<table id=rstable border=0 cellspacing=1 cellpadding=2 width=100% height=100%>"; rssxSearchPopupBodyCode += "<tr><td valign=top><style>" + convertStylesToInline() + "</style>"; rssxSearchPopupBodyCode += "<tr><td valign=top style='text-align: center' class=helpboxDescriptions>" + rssxContent; rssxSearchPopupBodyCode += "</tr></td></table></body></html>"; rssxSearchPopupBody.innerHTML = rssxSearchPopupBodyCode; rssxSearchPopup.document.body.style.border="outset 2px"; rssxSearchPopup.document.body.style.background='menu'; rssxSearchPopup.document.body.style.overflowY='auto'; // Temporarily show the popup to determine the proper final height for the popup. rssxSearchPopup.show(0, 0, windowW, 0); var windowH = rssxSearchPopupBody.scrollHeight + 6; rssxSearchPopup.hide(); // Put a cap on the popup height windowH = windowH > window.screen.height-100 ? window.screen.height-100 : windowH; // Display it rssxSearchPopup.show((buttonalign == "left" ? 0 : document.body.clientWidth - windowW), -windowH, windowW, windowH, document.body); // Set next display + timeout if (rssxSearchArray.length > 0){ rssxDisplayAgain = true; setTimeout("rssxSearchPopup.hide();rssxSearchPopup='';displayRssxSearchPopup();",rssxTimeOutAfter); }else{ rssxDisplayAgain = false; setTimeout("rssxSearchPopup.hide();rssxSearchPopup='';",rssxTimeOutAfter); } } ]]></script> <copyright> Copyright (c) 2004 Shawn K. Hall Distributed under the terms of the GNU Public License, Version 2 (http://www.gnu.org/copyleft/gpl.txt) </copyright> </search>