This article will demonstrate how we can build an RSS Feed Reader in PL/SQL. We will use DBMS_XMLPARSER to read an RSS feed from an URL and parsethe RSS document, then using the DBMS_XMLDOM package we will analyze the document and then make use of the DBMS_XSLPROCESSOR package to transform the RSS document into a presentable format. 

Many websites today publish RSS feeds. These feeds contain news items, the latest article publications, the most recent entries in discussion forums, software releases etc. The information available from RSS Feeds is structured according to a generic (almost) standard structure. That means that we can easily create software that processes RSS Feeds! Of course many RSS Feed Readers are available, for example as plugins for FireFox or other browsers, for Eclipse (created by my colleague Jeroen, see his article soon to be published on the weblog) or just as stand-alone tool.

In this article we create our own RSS Feed Reader, in PL/SQL of all programming languages!

....

Some of the RSS Feeds that we can read programmatically:

http://technology.amis.nl/blog/?feed=rss2
http://rss.cnn.com/rss/cnn_topstories.rss
http://newsrss.bbc.co.uk/rss/newsonline_world_edition/front_page/rss.xml
http://www.oracle.com/technology/syndication/rss_otn_news.xml
http://blogs.oracle.com/readingLists/oracleblogs.xml

Retrieve, Parse and Report

We will use the supplied package utl_http to retrieve our RSS document. This package is fed a URL and returns the HttpResponse that is received from the WebServer behind that URL. You could say that using UTL_HTTP the database acts like a Web Browser! Well, actually: we do not even need to use UTL_HTTP ourselves as DBMS_XMLPARSER can parse content from an URL directly! (underneath it will probably leverage utl_http, but we need not bother).

Since we know that the response from an RSS feed returned from the URL is in fact an XML Document, we can parse the text into an XML Document, using the  DBMS_XMLPARSER package.

     rssFeedDoc    dbms_xmldom.domdocument;<br />   begin<br />     rssFeedDoc   := dbms_xmlparser.parse(url);<br />&nbsp;    ...

Now that we have the RSS Feed as parsed XML Document, we can process its contents using the functions and procedures in the DBMS_XMLDOM package:

   rssItemsList:= dbms_xmldom.GETELEMENTSBYTAGNAME(rssFeedDoc, 'item');<br />   itemNode:= dbms_xmldom.item(rssItemsList,0);<br />&nbsp;

It is quite easy to read the relevant node-values into fields of our PL/SQL Record type variable and then write a brief summary from each RSS Feed entry to the output. The entire code block:

declare<br /> <br /> type rss_item_type is record<br /> ( title    varchar2(2000)<br /> , link     varchar2(200)<br /> , pubDate  varchar2(200)<br /> , author   varchar2(200)<br /> , category varchar2(500)<br /> , description varchar2(4000)<br /> );<br /><br /> url varchar2(500):= 'http://technology.amis.nl/blog/?feed=rss2';<br /> rssFeedDoc    dbms_xmldom.domdocument;<br /> itemNode      dbms_xmldom.domnode;<br /> childnode     dbms_xmldom.domnode;<br /> myParser      dbms_xmlparser.Parser;<br /> rssItemsList  dbms_xmldom.domnodeList  ;<br /> rssItemFields dbms_xmldom.domnodeList  ;<br /> childNodeText varchar2(32000);<br /> <br /> l_rss_item        rss_item_type;<br /> l_empty_rss_item  rss_item_type;<br /> <br /> procedure pl(text in varchar2)<br /> is<br /> begin<br />   if length(text)&gt; 255<br />   then<br />     for i in 1..(trunc(length(text)/255)+1) loop<br />       dbms_output.put_line(substr(text,1+ 255*(i-1),255));<br />     end loop;<br />   else<br />     dbms_output.put_line(text);<br />   end if;<br /> end pl;<br /><br /> procedure report_rss_item(p_rss_item in rss_item_type)<br /> is<br /> begin<br />   pl(p_rss_item.title||' by '||p_rss_item.author);<br />   pl('Published on: '||p_rss_item.pubDate);<br />   pl('Category: '||p_rss_item.category);<br />   pl('==');<br />   pl('Description: '||p_rss_item.description);<br />   pl('----------------------------------------');<br />   pl(' ');<br /> end report_rss_item;<br /><br /> <br />begin<br />   myParser := dbms_xmlparser.newParser;<br />   rssFeedDoc   := dbms_xmlparser.parse(url);<br />   rssItemsList:= dbms_xmldom.GETELEMENTSBYTAGNAME(rssFeedDoc, 'item');<br />   l_rss_item:= l_empty_rss_item;<br />   pl('RSS Feed from AMIS Technology Weblog - most recent '||dbms_xmldom.getlength(rssItemsList)||' articles:');<br />   pl('=================================================================');<br />   for i in 1..dbms_xmldom.getlength(rssItemsList) loop<br />     itemNode:= dbms_xmldom.item(rssItemsList,i-1);<br />     rssItemFields:= dbms_xmldom.getChildNodes(itemNode);<br />     for j in 1..dbms_xmldom.getlength(rssItemFields) loop<br />       childnode:= dbms_xmldom.item(rssItemFields, j-1);<br />       childNodeText:= dbms_xmldom.getNodeValue(dbms_xmldom.getFirstChild(childnode));<br />       case dbms_xmldom.getNodeName(childnode)<br />       when 'title'<br />       then l_rss_item.title := childNodeText;<br />       when 'link'<br />       then l_rss_item.link := childNodeText;<br />       when 'pubDate'<br />       then l_rss_item.pubDate := childNodeText;<br />       when 'dc:creator'<br />       then l_rss_item.author := childNodeText;<br />       when 'description'<br />       then l_rss_item.description := childNodeText;<br />       when 'category'<br />       then l_rss_item.category := childNodeText;<br />       else null;<br />       end case;             <br />     end loop;<br />     report_rss_item(l_rss_item);<br />   end loop;<br />end;<br />/ <br />

The output of this PL/SQL code for the AMIS Technology WebLog RSS Feed:

RSS Feed from AMIS Technology Weblog - most recent 10 articles:<br />=================================================================<br />Building an RSS Feed Reader in PL/SQL - using utl_http, dbms_xmldom and<br />dbms_xslprocessor for parsing and transforming by Lucas Jellema<br />Published on: Sat, 29 Apr 2006 18:22:53 +0000<br />Category: XML<br />==<br />Description: This article will demonstrate how we can build an RSS Feed Reader<br />in PL/SQL. We will use utl_http to read an RSS feed from an URL, parse the RSS<br />document using the DBMS_XMLDOM package and then make use of the<br />DBMS_XSLPROCESSOR package to tran<br />sform the RSS document into a presentable format.&amp;#160;Many websites today<br />publish RSS [...]<br />----------------------------------------<br />Getting used to Oracle SQL Developer by Patrick Sinke<br />Published on: Fri, 28 Apr 2006 15:30:34 +0000<br />Category: Devel. + PL/SQL tools<br />==<br />Description: <br />&amp;#160;It took a few months, but I finally start appreciating the<br />Oracle<br />SQL Developer developed by Oracle (The Project Formerly Known As<br />Raptor).<br />There are still some bugs, for instance with debugging through<br />a<br />firewall (hey, didn&amp;#8217;t we<br />have the same problem with JDeveloper?) and<br />some features are missing, but<br />it&amp;#8217;s quite usable. Especially when there<br />is no TOAD or [...]<br />----------------------------------------<br />Software Deploying using ANT by bertjan<br />Published on: Thu, 27 Apr 2006 16:13:45 +0000<br />Category: KC Software Engineering<br />==<br />Description: <br />  Some time ago a customer of AMIS asked me to setup the aut
omatic<br />... <br />

Let’s add a bit of XSL-T transformation to our code.

Using the dbms_xslprocessor package for XSL-T transformations

The presentation of the RSS items has been programmed somewhat clumsily. We do not really benefit from the fact that the RSS Feed is available as XML Document. Using an XSLT stylesheet, we do not need to programmatically extract individual nodes and print their contents to the output.

The XSL-T Stylesheet is first defined in a simple VARCHAR2 variable that subsequently is parsed into an XMLDocument.

 myParser      dbms_xmlparser.Parser;<br /> proc        dbms_xslprocessor.processor;<br /> xsltdomdoc  dbms_xmldom.domdocument;<br /> xsl         dbms_xslprocessor.stylesheet;<br /> outdomdocf  dbms_xmldom.domdocumentfragment;<br /> outnode     dbms_xmldom.domnode;<br /> ...<br />  xsldoc     varchar2(32000):= <br />   '&lt;?xml version=&quot;1.0&quot;?&gt; <br />    &lt;xsl:stylesheet version=&quot;1.0&quot; xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;&gt;<br />      ...<br />    &lt;/xsl:stylesheet&gt;';<br />   ...<br />   -- get XSLT stylesheet in stylesheet type variable<br />   myParser := dbms_xmlparser.newParser;<br />   dbms_xmlparser.parseBuffer(myParser, xsldoc);<br />   xsltdomdoc := dbms_xmlparser.getDocument(myParser);<br />   xsl        := dbms_xslprocessor.newstylesheet(xsltdomdoc, '');<br />   <br /><br />

Then we can use the dbms_xmlprocessor to use this stylesheet for transforming the RSS Feed document into a more report-oriented XML document:

&nbsp;--apply stylesheet to DOM document   <br />   proc       := dbms_xslprocessor.newProcessor;

The entire block of code:

declare<br /> <br /><br />-- url varchar2(500):= 'http://technology.amis.nl/blog/?feed=rss2';<br /> --url varchar2(500):= 'http://rss.cnn.com/rss/cnn_topstories.rss ';<br /> url varchar2(500):= 'http://newsrss.bbc.co.uk/rss/newsonline_world_edition/front_page/rss.xml ';<br />--http://www.oracle.com/technology/syndication/rss_otn_news.xml<br />--http://blogs.oracle.com/readingLists/oracleblogs.xml<br /><br /><br /> rssFeedDoc    dbms_xmldom.domdocument;<br /> itemNode      dbms_xmldom.domnode;<br /> childnode     dbms_xmldom.domnode;<br /> myParser      dbms_xmlparser.Parser;<br /> rssItemsList  dbms_xmldom.domnodeList  ;<br /> rssItemFields dbms_xmldom.domnodeList  ;<br /> childNodeText varchar2(32000);<br /> proc        dbms_xslprocessor.processor;<br /> <br /> xsltdomdoc  dbms_xmldom.domdocument;<br /> xsl         dbms_xslprocessor.stylesheet;<br /> outdomdocf  dbms_xmldom.domdocumentfragment;<br /> outnode     dbms_xmldom.domnode;<br /> buf         varchar2(32000); <br /> <br />  xsldoc     varchar2(32000):= <br />   '&lt;?xml version=&quot;1.0&quot;?&gt; <br />    &lt;xsl:stylesheet version=&quot;1.0&quot; xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;&gt;<br />      &lt;xsl:output encoding=&quot;utf-8&quot;/&gt;<br />&lt;xsl:template match=&quot;/&quot;&gt;<br />         &lt;rssItems&gt;<br />         &lt;xsl:apply-templates select=&quot;//item&quot;/&gt;<br />        &lt;/rssItems&gt;<br />      &lt;/xsl:template&gt;      <br />      &lt;xsl:template match=&quot;//item&quot;&gt;<br />         &lt;rssItem&gt;<br />           &lt;xsl:value-of select=&quot;title&quot;/&gt;&lt;xsl:text&gt;<br />           by: &lt;/xsl:text&gt;<br />           &lt;xsl:value-of select=&quot;creator&quot;/&gt;&lt;xsl:text&gt;<br />           Published on: &lt;/xsl:text&gt;&lt;xsl:value-of select=&quot;pubDate&quot;/&gt;<br />           &lt;xsl:text&gt;<br />           Category: &lt;/xsl:text&gt;&lt;xsl:value-of select=&quot;category&quot;/&gt;<br />           &lt;xsl:text&gt;<br />           ==<br />           &lt;/xsl:text&gt;&lt;xsl:value-of select=&quot;description&quot;/&gt;&lt;xsl:text&gt;<br />           -----------------------------------------------------------------------<br />           &lt;/xsl:text&gt;<br />           &lt;/rssItem&gt;<br />      &lt;/xsl:template&gt;<br />    &lt;/xsl:stylesheet&gt;';<br /> <br /> procedure pl(text in varchar2)<br /> is<br /> begin<br />   if length(text)&gt; 255<br />   then<br />     for i in 1..(trunc(length(text)/255)+1) loop<br />       dbms_output.put_line(substr(text,1+ 255*(i-1),255));<br />     end loop;<br />   else<br />     dbms_output.put_line(text);<br />   end if;<br /> end pl;<br /><br /> <br /> <br />begin<br />   rssFeedDoc   := dbms_xmlparser.parse(url);<br /><br />   -- get XSLT stylesheet in stylesheet type variable<br />   myParser := dbms_xmlparser.newParser;<br />   dbms_xmlparser.parseBuffer(myParser, xsldoc);<br />   xsltdomdoc := dbms_xmlparser.getDocument(myParser);<br />   xsl        := dbms_xslprocessor.newstylesheet(xsltdomdoc, '');<br /><br />   <br />   --apply stylesheet to DOM document   <br />   proc       := dbms_xslprocessor.newProcessor;<br />   outdomdocf := dbms_xslprocessor.processxsl(proc, xsl, rssFeedDoc);<br />   outnode    := dbms_xmldom.makenode(outdomdocf); <br />   dbms_xmldom.writetobuffer(outnode, buf);<br />   pl('RSS Feed from AMIS Technology Weblog - most recent articles:');<br />   pl('=================================================================');<br />   pl(buf);<br />end;<br />/ <br />

The results: 

RSS Feed from AMIS Technology Weblog - most recent articles:<br />=================================================================<br />&lt;rssItems&gt;<br />  &lt;rssItem&gt;Building an RSS Feed Reader in PL/SQL - using<br />dbms_xmlparser, dbms_xmldom and dbms_xslprocessor for parsing and transforming<br /><br />by: <br />           Published on: Sat, 29 Apr 2006 18:22:53 +0000<br /><br />Category: General<br /><br />==<br />           <br />This article will demonstrate how we can build an RSS Feed Reader<br />in PL/SQL. We will use DBMS_XMLPARSER to read an RSS feed from an URL and<br />parsethe RSS document, then using the DBMS_XMLDOM package we will analyze the<br />document and then<br />make use of the DBMS_XSLPROCESSOR package to transform the RSS document into a<br />[...]<br /><br />-----------------------------------------------------------------------<br /><br />&lt;/rssItem&gt;<br />  &lt;rssItem&gt;Getting used to Oracle SQL Developer<br />           by: <br /><br />Published on: Fri, 28 Apr 2006 15:30:34 +0000<br />           Category: Devel. +<br />PL/SQL tools<br />           ==<br />           <br />&amp;amp;#160;It took a few months, but I<br />finally start appreciating the Oracle<br />SQL Developer developed by Oracle (The<br />Project Former<br />ly Known As Raptor).<br />There are still some bugs, for instance with debugging<br />through a<br />firewall (hey, didn&amp;amp;#8217;t we have the same problem with<br />JDeveloper?) and<br />some features are missing, but it&amp;amp;#8217;s quite usable. <br />

Web Publishing our RSS Feed using MOD_PLSQL

Using the MOD_PLSQL extension to the Apache Web Server, we can easily create a PL/SQL procedure that publishes the RSS Feed we have read from the Internet URL. Using a proper XSLT-stylesheet, we can turn the RSS XML Document into a pretty presentable HTML page. With the following XSL-T stylesheet:

&lt;?xml version=&quot;1.0&quot;?&gt; <br />    &lt;xsl:stylesheet version=&quot;1.0&quot; xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;&gt;<br />      &lt;xsl:output encoding=&quot;utf-8&quot;/&gt;<br />&lt;xsl:template match=&quot;/&quot;&gt;<br />&lt;h2&gt;RSS Feed from AMIS Technology Weblog - most recent articles:&lt;/h2&gt;&lt;hr /&gt;<br />         &lt;ul&gt;<br />         &lt;xsl:apply-templates select=&quot;//item&quot;/&gt;<br />        &lt;/ul&gt;<br />      &lt;/xsl:template&gt;      <br />      &lt;xsl:template match=&quot;//item&quot;&gt;<br />&lt;li&gt;<br />         &lt;xsl:element name=&quot;a&quot;&gt;<br />           &lt;xsl:attribute name=&quot;target&quot;&gt;&lt;xsl:text&gt;_blank&lt;/xsl:text&gt;&lt;/xsl:attribute&gt;<br />           &lt;xsl:attribute name=&quot;href&quot;&gt;&lt;xsl:value-of select=&quot;link&quot; /&gt;&lt;/xsl:attribute&gt;<br />           &lt;xsl:value-of select=&quot;title&quot; /&gt;<br />         &lt;/xsl:element&gt;<br />         &lt;span style=&quot;font-family:sans-serif;font-size:8pt&quot;&gt;<br />         &lt;xsl:attribute name=&quot;title&quot;&gt;&lt;xsl:value-of select=&quot;description&quot; /&gt;&lt;/xsl:attribute&gt;<br />         &lt;xsl:text&gt;( Published on: &lt;/xsl:text&gt;&lt;xsl:value-of select=&quot;pubDate&quot; /&gt;&lt;xsl:text&gt;)&lt;/xsl:text&gt;&lt;/span&gt;<br />       &lt;/li&gt;<br />      &lt;/xsl:template&gt;<br />    &lt;/xsl:stylesheet&gt; <br />

we create the web-page as shown below:

 

Note how we use the HTML attribute title to show the bubble text whenever the cursor hovers over the publication date.

The procedure rss_reader that we now invoke through the MOD_PLSQL module is as follows:

create or replace<br />procedure rss_reader<br />as <br /><br /> url varchar2(500):= 'http://newsrss.bbc.co.uk/rss/newsonline_world_edition/front_page/rss.xml ';<br /><br /> rssFeedDoc    dbms_xmldom.domdocument;<br /> itemNode      dbms_xmldom.domnode;<br /> childnode     dbms_xmldom.domnode;<br /> myParser      dbms_xmlparser.Parser;<br /> rssItemsList  dbms_xmldom.domnodeList  ;<br /> rssItemFields dbms_xmldom.domnodeList  ;<br /> childNodeText varchar2(32000);<br /> proc        dbms_xslprocessor.processor;<br /> <br /> xsltdomdoc  dbms_xmldom.domdocument;<br /> xsl         dbms_xslprocessor.stylesheet;<br /> outdomdocf  dbms_xmldom.domdocumentfragment;<br /> outnode     dbms_xmldom.domnode;<br /> buf         varchar2(32000); <br />
<br />  xsldoc     varchar2(32000):= <br />   '&lt;?xml version=&quot;1.0&quot;?&gt; <br />    &lt;xsl:stylesheet version=&quot;1.0&quot; xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;&gt;<br />      &lt;xsl:output encoding=&quot;utf-8&quot;/&gt;<br />&lt;xsl:template match=&quot;/&quot;&gt;<br />&lt;h2&gt;RSS Feed from AMIS Technology Weblog - most recent articles:&lt;/h2&gt;&lt;hr /&gt;<br />         &lt;ul&gt;<br />         &lt;xsl:apply-templates select=&quot;//item&quot;/&gt;<br />        &lt;/ul&gt;<br />      &lt;/xsl:template&gt;      <br />      &lt;xsl:template match=&quot;//item&quot;&gt;<br />&lt;li&gt;<br />         &lt;xsl:element name=&quot;a&quot;&gt;<br />           &lt;xsl:attribute name=&quot;target&quot;&gt;&lt;xsl:text&gt;_blank&lt;/xsl:text&gt;&lt;/xsl:attribute&gt;<br />           &lt;xsl:attribute name=&quot;href&quot;&gt;&lt;xsl:value-of select=&quot;link&quot; /&gt;&lt;/xsl:attribute&gt;<br />           &lt;xsl:value-of select=&quot;title&quot; /&gt;<br />         &lt;/xsl:element&gt;<br />         &lt;span style=&quot;font-family:sans-serif;font-size:8pt&quot;&gt;<br />         &lt;xsl:attribute name=&quot;title&quot;&gt;&lt;xsl:value-of select=&quot;description&quot; /&gt;&lt;/xsl:attribute&gt;<br />         &lt;xsl:text&gt;( Published on: &lt;/xsl:text&gt;&lt;xsl:value-of select=&quot;pubDate&quot; /&gt;&lt;xsl:text&gt;)&lt;/xsl:text&gt;&lt;/span&gt;<br />       &lt;/li&gt;<br />      &lt;/xsl:template&gt;<br />    &lt;/xsl:stylesheet&gt;';<br /> <br />begin<br />   rssFeedDoc   := dbms_xmlparser.parse(url);<br /><br />   -- get XSLT stylesheet in stylesheet type variable<br />   myParser := dbms_xmlparser.newParser;<br />   dbms_xmlparser.parseBuffer(myParser, xsldoc);<br />   xsltdomdoc := dbms_xmlparser.getDocument(myParser);<br />   xsl        := dbms_xslprocessor.newstylesheet(xsltdomdoc, '');<br /><br />   <br />   --apply stylesheet to DOM document   <br />   proc       := dbms_xslprocessor.newProcessor;<br />   outdomdocf := dbms_xslprocessor.processxsl(proc, xsl, rssFeedDoc);<br />   outnode    := dbms_xmldom.makenode(outdomdocf); <br />   dbms_xmldom.writetobuffer(outnode, buf);<br />   --pl(buf);<br />   htp.htmlOpen;<br />   htp.headOpen;<br />   htp.title('RSS Feed - BBC Headlines');<br />   htp.headClose;   <br />   htp.BodyOpen;<br />   htp.p(buf);<br />   htp.BodyClose;<br />   htp.htmlClose;<br />end;<br />/<br />

Resources

Oracle Documentation: XML Developer’s Guide