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>