Problem: RSS parsen
ernst kuzorra
- perl
hallo,
ich habe folgendes problem.
ich bekomme fogende rss datei, auf deren inhalt ich keinen einfluss habe.
<?xml version='1.0' encoding='ISO-8859-1' ?>
<rss version='2.0' xmlns:bb='http://www.blablabla2.de'>
<channel>
<title>der titel</title>
<link>http://www.inter.net</link>
<description>beschreibung</description>
<managingEditor>alle@inter.net</managingEditor>
<image>
<url>http://www.inter.net/logo.gif</url>
<title>logo</title>
<link>http://www.inter.net</link>
<width>100</width>
<height>50</height>
</image>
<language>de</language>
<lastBuildDate>2006-06-29T00:00:00</lastBuildDate>
<copyright>none</copyright>
<item>
<title>juhuu</title>
<description>die juhuu beschreibung</description>
<bb:name>linkliste</bb:name>
<bb:einzelteile>
<bb:einzelurl>http://url1.de</bb:einzelurl>
<bb:einzeltext>der text zu http://url1.de</bb:einzeltext>
</bb:einzelteile>
<bb:einzelteile>
<bb:einzelurl>http://url2.de</bb:einzelurl>
<bb:einzeltext>der text zu http://url2.de</bb:einzeltext>
</bb:einzelteile>
<bb:einzelteile>
<bb:einzelurl>http://url3.de</bb:einzelurl>
<bb:einzeltext>der text zu http://url3.de</bb:einzeltext>
</bb:einzelteile>
</item>
</channel>
</rss>
via perl moechte ich diese parsen.
ich komme an alle elemente, bis auf die des namespace bb.
was mache ich falsch und kann mir da jemand helfen?
ich habe es mit XML::RSS versucht
#!/usr/bin/perl
use XML::RSS;
my $rss = new XML::RSS ();
$rss->parsefile('datei.xml');
print $rss->{items}->[0]->{title}."\n"; #funktioniert
print $rss->{items}->[0]->{bb}->{name}."\n"; #funktioniert nicht
print $rss->{items}->[0]->{bb}->{einzelteile}->[0]->{einzelurl}."\n"; #funktioniert schon gar nicht
und auch mit XML::RSS::Parser
#!/usr/bin/perl
use XML::RSS::Parser;
use FileHandle;
my $p = XML::RSS::Parser->new;
XML::RSS::Parser->register_ns_prefix('bb','http://irgendeine.url'); #???
my $fh = FileHandle->new('datei.xml');
my $feed = $p->parse_file($fh);
foreach my $aussen ( $feed->query('//item') ) {
my $innen=XML::RSS::Parser->ns_qualify($aussen, 'bb'); #???
print $aussen->query('title')->text_content."\n"; #funktioniert
print $innen->query('name')->text_content."\n"; #funktioniert nicht
bei XML::RSS::Parser hab ich ausserdem ueberhaupt keine ahnung, wie ich an das array bb:einzelteile komme.
sowohl XML::RSS als auch XML::RSS::Parser sind auf dem aktuellen stand, aber ich mache wohl jede menge denkfehler.
bin fuer jede hilfe dankbar.
Hallo nach Schalke,
<rss version='2.0' xmlns:bb='http://www.blablabla2.de'>
Kleiner Hinweis für die Grundlagen von XML-Namensräume: die URI (hier: http://www.blablabla2.de") ist wichtig, nicht das Präfix (hier: "bb"). In diesem Beispiel wird das Präfix "bb" für den XML-Namensraum an die URI gebunden. Man hätte auch das Präfix "blablubb" nennen können.
XML::RSS::Parser->register_ns_prefix('bb','http://irgendeine.url'); #???
Hier suchst Du aber nicht nach dem XML Namensraum aus dem obigen RSS-Feed – denn der wird durch die URI "http://www.blablabla2.de" beschrieben. Du dagegen suchst nach Elementen aus dem Namensraum der (nicht wirklich stimmigen) URI "http://irgendeine.url" und die gibt's im obigem XML ja nicht.
foreach my $aussen ( $feed->query('//item') ) {
So wie ich relativ Perl-unkundiger die Dokumentation von XML::RSS::Parser durchgucke, dann sieht das so aus, als würde generell der Feed hier mit XPath-Ausdrücken durchgegangen. Relativ grundlegende XML-Verarbeitung also im Gegensatz zu anderen APIs, die den Zugriff auf RSS-Feeds bieten.
print $aussen->query('title')->text_content."\n"; #funktioniert
print $innen->query('name')->text_content."\n"; #funktioniert nicht
Ein XML-Namensräume berücksichtigender XPath-Ausdruck würde dann wohl so aussehen:
print $aussen->query("bb:name")->text_content;
Dies funktioniert aber nur, wenn das im XPath-Ausdruck benötigte Präfix "bb" richtig an die richtige den XML Namensraum bestimmende URI gebunden ist – das Du mit register_ns_prefix() gemacht hast. Dort hättest Du auch ein anderes Präfix verwenden können, vorausgesetzt, Du bindest das an die richtige URI:
~~~perl
XML::RSS::Parser->register_ns_prefix('xyz','http://www.blablabla2.de');
...
$aussen->query("xyz:name")->text_content
Sprich: die komischen xmlns-URIs sind wichtig und man braucht sie, damit man weiss, wonach man im XML-Dokument sucht. Es sind also nicht nur irgendwelche „komischen URLs“ Auch wenn die hier wohl eher unschön gewählt wurden.
> sowohl XML::RSS als auch XML::RSS::Parser sind auf dem aktuellen stand, aber ich mache wohl jede menge denkfehler.
Jain. Es läuft ja schon, Du bist nur darüber gestolpert, dass dieses XML::RSS XPath-Ausdrücke zum Finden von Elementen im XML benutzt. Aber Du brauchst das ja, schließlich suchst Du nach eingefügtem XML, das kein anderer kennt. Ein RSS-Parser mit einem eher objektorientierten, abstrahierten Ansatz wie z.B. [XML::RAI](http://search.cpan.org/~tima/XML-RAI-1.301/lib/XML/RAI.pm) würde da nichts nützen, das Ding weiss ja, wonach es im Feed sucht, den komischen XML-Namensraum aus dem bb:einzelteile stammen kennt aber sonst wohl kaum jemand.
Nebenbei: Der RSS-Feed ist teilweise auch nicht so toll, zum Beispiel gehorcht das Format des Datums in <lastBuildDate> nicht den von der [RSS 2.0 Spezifikation](http://blogs.law.harvard.edu/tech/rss) verlangtem doofen Format nach RFC 822. Solltest Du Kontakt zum Anbieter des Feeds haben, solltest Du ihm die Benutzung des [Feed Validators](http://feedvalidator.org/) ans Herz legen; damit kommt man solchen Fehlern gut auf die Spur, ohne sich mit all den Problemchen rund um RSS auszukennen.
Grüße aus Dortmund,
Tim