RSS-News-Feeds sind eine tolle Sache, um sich auf dem Laufenden zu
halten. Ursprünglich von Netscape erfunden, boomen diese XML-Zusammenfassungen
von Nachrichten mit den vielen Blog-Seiten, die es im
Internet inzwischen gibt. Auch viele Internetauftritte medialer Unternehmen,
wie Tageszeitungen, Fernsehsendern, Nachrichtenportale etc., bieten
inzwischen RSS-Feeds, die der geneigte Leser in spezielle Programme laden
kann, von denen es inzwischen eine unüberschaubare Anzahl gibt.
Die Frage, die ich mir nun gestellt habe ist, warum ich ein externes
Programm installieren muss, wenn RSS-Feeds doch in einer XML-Struktur
vorliegen, die zum einen sehr artverwandt ist mit HTML und es zum anderen in
ASP verschiedene Techniken gibt XML-Daten zu verarbeiten.
Wie bereits erwähnt ist ein News-Feed eine XML-Datei mit festgelegter
Struktur. Zur Zeit gibt im Internet die beiden sehr verbreiteten Varianten RSS und RDF, die von ganz
unterschiedlichen Organisationen entworfen wurden und deren
Grundstruktur ich zunächst vorstellen möchte.
RSS 0.91 und RSS 2.0
<rss>
<channel>
<title>...</title>
<link>...</link>
<description>...</description>
<item>
<title>...</title>
<link>...</link>
<description>...</description>
</item>
</channel>
</rss>
RDF
<rdf:RDF>
<channel>
<title>...</title>
<link>...</link>
<description>...</description>
</channel>
<item>
<title>...</title>
<link>...</link>
<description>...</description>
</item>
</rdf:RDF>
Wie man sieht, beinhaltet das jeweilige Root-Element zum einen
beschreibende Elemente für den sog. "Channel", d.h. den
Feed selbst, und im weiteren die einzelnen Nachrichtenelemente, die wiederum
beschreibende Tags enthalten. Die jeweiligen Spezifikationen, die man im
Internet nachschlagen kann, enthalten noch weit mehr Tags als ich in diesem
kurzen Beispiel dargestellt habe, aber für die korrekte Darstellung der
Inhalte sind mehr Tags zunächst nicht nötig.
Um einen Feed verarbeiten zu können, legen wir für die zu erstellende
ASP-Seite den Übergabeparameter url fest, den wir zu Beginn
zunächst auslesen:
strFeedURL = Request.QueryString("url")
Für die Verarbeitung der XML-Datei müssen wir Sie zunächst laden. Dies
übernimmt das Objekt ServerXMLHTTP des Microsoft'schen
XML-Parsers MSXML:
Set objXMLHTTP = Server.CreateObject("MSXML2.ServerXMLHTTP")
objXMLHTTP.Open "GET", strFeedURL, False
objXMLHTTP.Send()
Mit dem letzten Parameter False der Methode Open
weisen wir das Objekt an, die Daten synchron zu laden, d.h. es geht erst mit
der Verarbeitung weiter, wenn das letzte Byte angekommen ist. True
kann man nur verwenden, wenn man, z.B. in JavaScript, mit
CallBack-Funktionen und Events arbeiten kann.
Den empfangenen Text kann man sich nun z.B. mit der Anweisung
response.write objXMLHTTP.responseText anschauen. Zur Verarbeitung
benötigen wir jedoch ein DOMDocument des XML-Parsers, dem
wir das XML-Objekt zuweisen:
Set objDoc = Server.CreateObject("MSXML2.DOMDocument")
Set objDoc = objXMLHTTP.ResponseXML
Über die Variable objDoc können wir nun auf das Root-Element
des XML-Baums zugreifen und es in einer eigenen Variable vom Typ IXMLDOMElement ablegen:
Set objRoot = objDoc.documentElement
An diesem Punkt können wir über den Namen des ersten Nodes, d.h. des
Roots, entscheiden um was für ein Format es sich bei
dem übergebenen Feed handelt und entsprechend der sich unterscheidenden
Struktur ein paar Zugriffsvariablen belegen. Für die Channel-Informationen
dient ein kleines Array (arrFeedInfo), in dem diese zunächst
für die spätere Ausgabe zwischengespeichert werden. Als erste Informationen
legen wir hier den Feed-Typ ab.
Dim arrFeedInfo(3)
Select Case UCase(objRoot.nodeName)
Case "RDF:RDF"
strChannelPath = "//rdf:RDF/channel"
strEntryPath = "//rdf:RDF"
arrFeedInfo(0) = "RDF"
Case "RSS"
strChannelPath = "//rss/channel"
strEntryPath = "//rss/channel"
arrFeedInfo(0) = "RSS " & objRoot.GetAttribute("version")
End Select
Für die weiteren Channel-Informationen nutzen wir nun die Zugriffvariable
strChannelPath. Es wird jeweils zunächst mit der XPath-Methode
selectSingleNode das gewünschte Node-Objekt ermittelt und dann der darin
enthaltene Text ausgelesen.
Set objNode = objDoc.selectSingleNode(strChannelPath & "/title")
arrFeedInfo(1) = objNode.text
Set objNode = objDoc.selectSingleNode(strChannelPath & "/link")
arrFeedInfo(2) = objNode.text
Set objNode = objDoc.selectSingleNode(strChannelPath & "/description")
arrFeedInfo(3) = objNode.text
Damit hätten wir schon einmal den ersten Teil der Daten, den wir auf der
Seite ausgeben können:
Response.Write("Feed-Typ: " & arrFeedInfo(0))
Response.Write("Feed-Titel: " & arrFeedInfo(1))
Response.Write("Feed-Link: " & arrFeedInfo(2))
Response.Write("Feed-Beschreibung: " & arrFeedInfo(3))
'Trennzeile
Response.Write("<br><hr><br>")
Der zweite Teil
besteht aus den einzelnen Nachrichten. Um diese in einer Schleife
durchlaufen zu können, benötigen wir zunächst einmal ein Objekt, das wir nun
über die Zugriffsvariable strEntryPath ermitteln:
Set objNode = objDoc.selectSingleNode(strEntryPath)
Ausgehend von dem den Einträgen übergeordneten Node, wird nun in einer
ersten Schleife jedes Kindelement betrachtet und entschieden, ob es den
Namen "ITEM" trägt. Ist dies der Fall, so werden über ein weiteres
Node-Objekt, das auf den gefundenen Ast zeigt, wiederum alle Kindelemente
abgerufen und die darin enthaltenen beschreibenden Informationen für das
Item in dem Hilfsarray arrFeedEntry abgelegt und schließlich
mit einer abschließenden Trennzeile ausgegeben.
'Alle Kindelemente durchlaufen
For Each objEntry In objNode.childNodes
'Nur Items auslesen
If UCase(objEntry.nodeName) = "ITEM" Then
'Alle Kindelemente des Items durchlaufen
For Each objChild In objEntry.childNodes
'Beschreibende Daten ermitteln
Select Case UCase(objChild.nodeName)
Case "TITLE": arrFeedEntry(0) = objChild.text
Case "LINK": arrFeedEntry(1) = objChild.text
Case "DESCRIPTION": arrFeedEntry(2) = objChild.text
End Select
Next
Response.Write("Titel: " & arrFeedEntry(0))
Response.Write("Link: " & arrFeedEntry(1))
Response.Write("Beschreibung: " & arrFeedEntry(2)
'Trennzeile
Response.Write("<br><hr><br>")
End If
Next
Set objChild = Nothing
Set objNode = Nothing
Set objRoot = Nothing
Set objXMLHTTP = Nothing
Wie es sich gehört werden als Abschluss alle Objekte zerstört. Man kann
nun den Code so erweitern, dass die Ausgaben etwas sinnfälliger
gestaltet werden. Zudem kann man weitere in den jeweiligen Spezifikationen
enthaltene Tags auslesen und darstellen.
Spezifikationen
Wie bereits oben erwähnt, gibt es aktuell mehrere Feed-Formate, die zum Teil aufeinander aufbauen.
Unter folgenden Links können die einzelnen Spezifikationen eingesehen werden: