I wanted to do RSS 2.0 first given that it has the most momentum at the moment, but that’s hardly the only accepted syndication format. Here’s the formats and the players involved (consider it the abridged, highlights-only history of syndication by yours truly)….



  • RSS 0.9 : Netscape/Dan Libby (considered obsolete and too complex by most – RDF specification based – Netscape dropped out of the game about the time the simplified version 0.91 was proposed, big mistake – RSS stands for “RDF Site Summary”)

  • RSS 0.91 : Netscape/Dan Libby (never got off the ground – it is argued by some that this didn’t even constitute a version… but it’s documented, but it is analogous to Visual FoxPro version 4… you hear about people who have the beta, but never really seen it.)

  • RSS 0.91 : UserLand Software/Dave Winer (officially obsoleted by RSS 2.0 – UserLand picks up the ball and runs with it – RSS stands for “Rich Site Summary“)

  • RSS 0.92 : UserLand Software (officially obsoleted by RSS 2.0)

  • RSS 0.93 : UserLand Software (officially obsoleted by RSS 2.0)

  • RSS 0.94 : UserLand Software (officially obsoleted by RSS 2.0)

  • RSS 1.0 : RSS-DEV Working Group (Active – not from 0.94 as you may think, it is actually considered a branch from 0.90 and RDF specification based – not affiliated with UserLand Software – RSS stands for “RDF Site Summary“)

  • RSS 2.0 : UserLand Software (Active – next generation taking over where 0.94 left off – RSS stands for “Really Simple Syndication“)

  • ATOM 0.1-1.0 IETF Atom Publishing Format and Protocol (atompub) Working Group. (Active – entirely seperate from all previous efforts, IETF didn’t come into the picture until ATOM 0.3, has a very good chance of becoming the internet standard for syndication. Note: UserLand/Dave Winer offered to merge with ATOM in 2004, ATOM has so far declined the offer. Work on the specification is on-going and affectionately referred to as the ATOM Project)

My blog offers RSS 2.0 and ATOM 0.2 syndication, so here’s the code to grab ATOM into Visual FoxPro tables via a schema and the XMLAdapter (I need to dig into the ATOM 1.0 specification before I can do a more thorough job, but this is a good start)…







LOCAL loXMLAdapter, loBrowser, lcXSD, lcATOMContent, lcXMLHeader, lcXMLFooter


lcXMLHeader = GetHeader()
lcXSD = VFPATOMSchema()
*!* Atom .02 feed, need to dig into 1.0 specification
http://ietfreport.isoc.org/idref/draft-ietf-atompub-format/
lcATOMContent = RetrieveATOM(“http://www.sweetpotatosoftware.com/SPSBlog/SyndicationServiceExperimental.asmx/GetAtom“)
lcXMLFooter = GetFooter()


oXMLAdapter = NEWOBJECT(‘XMLAdapter’)


oXMLAdapter.LOADXML(lcXMLHeader + lcXSD+ lcATOMContent + lcXMLFooter)


CLOSE DATABASES ALL
oXMLAdapter.TABLES(1).TOCURSOR && Generator
oXMLAdapter.TABLES(2).TOCURSOR && Author
oXMLAdapter.TABLES(3).ToCursor && Entry
oXMLAdapter.TABLES(4).ToCursor && Feed
SET


*****************************
FUNCTION GetHeader()
*****************************
 LOCAL lcHeader
 TEXT TO lcHeader NOSHOW
<?xml version=”1.0″ encoding=”utf-8″ ?>
<VFPDataSet>
 ENDTEXT
 RETURN lcHeader
ENDFUNC


*****************************
FUNCTION GetFooter()
*****************************
 LOCAL lcFooter
 TEXT TO lcFooter NOSHOW
</VFPDataSet>
 ENDTEXT
 RETURN lcFooter
ENDFUNC


*****************************
FUNCTION VFPATOMSchema()
*****************************
 LOCAL lcXML
*!* Use bare minimum abbreviated notation to show all that is necessary
TEXT TO lcXML NOSHOW
<xsd:schema xmlns:tns=”
http://purl.org/atom/ns#” attributeFormDefault=”unqualified” elementFormDefault=”qualified” targetNamespace=”http://purl.org/atom/ns#” xmlns:xsd=”http://www.w3.org/2001/XMLSchema“>
  <xsd:import namespace=”
http://www.w3.org/XML/1998/namespace” />
  <xsd:element name=”feed”>
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name=”title” type=”xsd:string” />
        <xsd:element name=”link” type=”xsd:string” />
        <xsd:element name=”modified” type=”xsd:dateTime” />
        <xsd:element name=”tagline” type=”xsd:string” />
        <xsd:element name=”generator”>
          <xsd:complexType>
            <xsd:simpleContent>
              <xsd:extension base=”xsd:string”>
                <xsd:attribute name=”name” type=”xsd:string” use=”required” />
              </xsd:extension>
            </xsd:simpleContent>
          </xsd:complexType>
        </xsd:element>
        <xsd:element name=”author”>
          <xsd:complexType>
            <xsd:sequence>
              <xsd:element name=”name” type=”xsd:string” />
            </xsd:sequence>
          </xsd:complexType>
        </xsd:element>
        <xsd:element maxOccurs=”unbounded” name=”entry”>
          <xsd:complexType>
            <xsd:sequence>
              <xsd:element name=”title” type=”xsd:string” />
              <xsd:element name=”link” type=”xsd:string” />
              <xsd:element name=”id” type=”xsd:string” />
              <xsd:element name=”issued” type=”xsd:dateTime” />
              <xsd:element name=”modified” type=”xsd:dateTime” />
              <xsd:element name=”created” type=”xsd:dateTime” />
              <xsd:element name=”content” type=”xsd:string” />
            </xsd:sequence>
          </xsd:complexType>
        </xsd:element>
      </xsd:sequence>
      <xsd:attribute name=”version” type=”xsd:decimal” use=”required” />
    </xsd:complexType>
  </xsd:element>
</xsd:schema>
ENDTEXT
 RETURN lcXML
ENDFUNC


*****************************
FUNCTION RetrieveATOM(tcURL)
*****************************
 #DEFINE INTERNET_OPEN_TYPE_PRECONFIG 0
 #DEFINE SYNCHRONOUS 0
 #DEFINE INTERNET_FLAG_RELOAD 2147483648


 DECLARE INTEGER InternetOpen IN WININET STRING Agent, ;
  INTEGER AccessType, STRING ProxyName, ;
  STRING ProxyBypass, INTEGER Flags


 DECLARE INTEGER InternetOpenUrl IN WININET ;
  INTEGER hInternetSession, STRING Url, STRING Header, ;
  INTEGER HeaderLength, INTEGER Flags, INTEGER Context


 DECLARE INTEGER InternetReadFile IN WININET INTEGER file, ;
  STRING @Buffer, INTEGER NumberOfBytesToRead, INTEGER @BytesRead


 DECLARE SHORT InternetCloseHandle IN WININET INTEGER hInst


 LOCAL lcAgent, lhInternetSession, lhFile, llOK, lnReturn, lcReadBuffer, lnBytesRead, lcRetVal


 lcAgent = “VFP ATOM 0.2 Reader”
 lhInternetSession = InternetOpen(lcAgent, INTERNET_OPEN_TYPE_PRECONFIG, “”, “”, SYNCHRONOUS)


 IF lhInternetSession = 0
  ? “Problem Encountered: Internet session cannot be established”
 ELSE
  lhFile = InternetOpenUrl( lhInternetSession, tcURL, ”, 0, INTERNET_FLAG_RELOAD, 0)
  IF lhFile = 0
   ? “Problem Encountered: URL cannot be opened”
  ELSE
   lcRetVal = “”
   llOK = .T.
   
   DO WHILE llOK
    lcReadBuffer = SPACE(1500)
    lnBytesRead = 0
    lnReturn = InternetReadFile(lhFile, @lcReadBuffer, LEN(lcReadBuffer), @lnBytesRead)
    IF (lnBytesRead > 0)
     lcRetVal = lcRetVal + LEFT(lcReadBuffer, lnBytesRead)
    ENDIF
    llOK = (lnReturn = 1 AND lnBytesRead > 0)
   ENDDO
   
   InternetCloseHandle(lhFile)
   InternetCloseHandle(lhInternetSession)
   lcRetVal = SUBSTR(lcRetVal, ATC(“<feed”, lcRetVal))
   
   RETURN LEFT(lcRetVal, ATC(“</feed>”, lcRetVal) + 9)
  ENDIF
 ENDIF
 RETURN “”
ENDFUNC