Afin de faciliter l'édition de fils RSS, j'ai écrit ce petit programe en perl avec une interface graphique Tk donc compatible Windows, Linux, Unix et autres Mac-OS X. C'est vraiment rudimentaire mais cela peut servir de base pour développer des choses plus complexes si besoin. C'est un canevas, une preuve de concept.

#! /usr/bin/perl-w # PerlTk RSS Feed Editor # Creative commons, habett, 2005
J'ai maximisé l'usage des modules avec beaucoup d'explicité mais seul XML::RSS devrait manquer d'une distribution classique comme ActivePerl.
use Tk; use Tk::widgets qw(TextUndo Scrollbar LabEntry NoteBook); use XML::RSS; use strict; use Carp; use diagnostics; use locale;
On commence par créer un objet fil RSS dont on va forcer l'encodage en ISO 8859-1 pour simplifier les choses. On lit un fil vide puis on le charge et parse avec le sub qui convient.
# lecture d'un fil blanc my $rss = new XML::RSS(encoding=>"ISO-8859-1"); my $file="blank.xml"; readfeed($file);
On passe maintenant aux artifices d'interface graphique avec Tk. Notez le lien dynamique que permet textvariable sur certains widgets.
# création de la fenêtre
my $mainwindow = MainWindow->new();
$mainwindow->configure(-title => "Daal, EdRSS");
$mainwindow->optionAdd('*TextUndo.Background' => '#fff5e1');
my $z="#";
$mainwindow->Button(-text => 'Ouvrir un feed',-width=>80,
-command => \&loadfeed)->pack(-side=>"top",-anchor=>"n",-fill=>'x',-padx=>10,-pady=>10);
# Infos générales
my $title = $mainwindow->LabEntry(-label=>"Titre",-labelPack=>[-anchor=>"n"],-width=>80,
-textvariable=>$rss->channel("title"))->pack(-side=>"top",-anchor=>"nw",-padx =>10,-pady=>10);
my $description = $mainwindow->LabEntry(-label=>"Description",-labelPack =>[-anchor=>"n"],-width=>80,
-textvariable=>$rss->channel("description"))->pack(-side=>"top",-anchor=>"nw",-padx=>10,-pady=>10);
my $link = $mainwindow->LabEntry(-label=>"URL",-labelPack=>[-anchor=>"n"],-width=>80,
-textvariable=>$rss->channel("link"))->pack(-side=>"top",-anchor=>"nw",-padx=>10,-pady=>10);
# création d'un nouvel item
$mainwindow->Button(-text=>'Nouvel item',-width=>80,-foreground=>'blue',
-command => \&nouvelle)->pack(-side=>"top",-anchor=>"n",-fill=>'x',-padx=>10,-pady=>10);
Il est fait appel au widget NoteBook pour symboliser les différents élément du fil. Comme on le vera plus tard, nous avons restreint à 15 le nombre d'items lors de l'édition, conformément aux usages actuels.
#NoteBook des items du feed my $w_book = $mainwindow->NoteBook()->pack(-padx=>10,-pady=>10); my (@text,@w_page); &book; # quitter et/ou enregistrer $mainwindow->Button(-text=>'Quitter sans enregistrer',-width=>80,-relief=>'sunken',-foreground=>'red', -command=> \&quit)->pack(-anchor=>"s",-fill=>'x',-padx=>10,-pady=>10); $mainwindow->Button(-text=>'Enregistrer et quitter',-width=>80,-foreground=>'darkgreen', -command=>\&saveclose)->pack(-anchor=>"s",-fill=>'x',-padx=>10,-pady=>10);
Une fois l'interface construite, reste à lancer les opérations et à les terminer.
MainLoop(); exit(0);
Passons aux procédures, la première est celle d'ajout d'un élément au fil. Comme convenu, on limite le nombre d'items à 15. Une fois le traitement fair sur le fil, on fait appel à la procédure &book; pour mettre à jour l'affichage.
sub nouvelle {
# nouvel élément au feed
$rss->channel(title=>$title->get,link=>$link->get,description=>$description->get,lastBuildDate=>&tome);
my $i = 0;
foreach my $item (@{$rss->{'items'}}) {
$i++;
$item->{'title'}=$item->{'title'}->get;
$item->{'link'}=$item->{'link'}->get;
$item->{'description'}=$text[$i]->Contents;
}
pop(@{$rss->{'items'}}) if (@{$rss->{'items'}} == 15);
$rss->add_item(title=>'Nouveau',link=>"http://",pubDate=>&tome,mode=>'insert');
$rss->save($file);
&book;
}
Création d'un masque d'ouverture de fichier adapté.
sub loadfeed {
# Wiget adapté aux fils avec extension xml ou rss
my @types = (["Feeds", ['.xml','.rss']],["All Files", "*"] );
$file = $mainwindow->getOpenFile(-filetypes => \@types);
&readfeed;
&book;
}
Procédure d'affichage avec nettoyage préalable par le vide.
sub book {
# netoyage du notebook
my @totej = $w_book->pages;
foreach(@totej) {
$w_book->delete($_);
}
# recréation du notebook
my $i = 0;
&readfeed ($file);
foreach my $item (@{$rss-gt;{'items'}}) {
$i++;
$w_page[$i] = $w_book->add("$i",-label=>"$z$i");
$item->{'title'} = $w_page[$i]->Entry(-relief=>'sunken',-width=>80,-textvariable=>$item->{'title'})->pack;
$item->{'link'} = $w_page[$i]->Entry(-relief=>'sunken',-width=>80,-textvariable=>$item->{'link'})->pack;
$text[$i] = $w_page[$i]->TextUndo(-relief=>'sunken',-width=>69,-height=>4,-wrap=>'word')->pack;
$text[$i]->Insert($item->{'description'});
$text[$i]->focus;
$w_page[$i]->pack;
}
$title->delete(0,"end");
$title->insert("end",$rss->channel('title'));
$link->delete(0,"end");
$link->insert("end",$rss->channel('link'));
$description->delete(0,"end");
$description->insert("end",$rss->channel('description'));
}
Maintenant, très classiquement, lire, enregistrer, quitter.
sub readfeed {
#lecture puis parse du feed
my $file = shift;
return unless $file;
return unless -e $file;
my $textfile;
open (IN, $file);
$textfile .= $_ while ();
close (IN);
$rss->parse($textfile);
}
sub saveclose {
# enregistrement du feed
$rss->channel(title=>$title->get,link=>$link->get,description=>$description->get);
my $i=0;
foreach my$item (@{$rss->{'items'}}) {
$i++;
$item->{'title'}=$item->{'title'}->get;
$item->{'link'}=$item->{'link'}->get;
my $temp=$text[$i]->Contents;
chomp($temp);
$item->{'description'}=$temp;
}
$rss->save($file);
exit;
}
sub quit {
exit(0);
}
Pour avoir une date conforme aux standards du genre, notez la petite manipulation sur gmtime.
sub tome {
my ($wday,$month,$dayn,$time,$year) = split(/ /,scalar gmtime);
return "$wday, $dayn $month $year $time GMT";
}
C'est tout. Le code aurait pû être plus modularisé mais il est fonctionnel. Grâce à XML::RSS, il a la vertu d'être agnostique en matière de version/format de fil.