Introduction▲
Il a quelques semaines, Florian Casabianca publiait un excellent article sur la manipulation des flux RSS à l'aide du framework 3.5. Il y explique notamment comment à l'aide de l'objet SyndicationFeed, il est très facile de lire et/ou de créer des flux RSS aussi bien au format RSS 2.0 qu'ATOM 1.0 (les standards de RSS les plus utilisés à ce jour). Cet article m'a rappelé une plateforme au sein de Windows, appelée tout simplement « Windows RSS Platform » qui permet, surtout depuis l'arrivée d'Internet Explorer 7 d'agréger vos flux RSS au sein d'une liste unique appelée Common Feed List. Cette liste est une sorte d'annuaire commun de flux RSS qu'il vous est alors permis de modifier ou d'intégrer directement au sein de votre application.
C'est sa manipulation que je vous propose de découvrir au sein de ce tutoriel.
I. Présentation▲
I-A. Flux RSS▲
RSS ou Really Simple Syndication est un « format de fichier XML dont le contenu est généré dynamiquement depuis une base de données. C'est un format de syndication de contenu. Le sigle peut également signifier : Rich Site Summary ou Real-time Simple Syndication. » (Hugo Etiévant - dico des développeurs).
En quelques mots plus clairs, il s'agit la plupart du temps de résumés de news, permettant d'un seul coup d'œil de connaître les « gros titres » ou nouvelles informations d'un site web. Bien souvent, ces flux RSS, présents sur les sites de tout genre, sont générés dynamiquement à partir des dernières nouvelles saisies, et se contentent de lister les titres ainsi que les premiers mots de ces news. Cela permet à l'utilisateur, d'avoir un agrégateur de flux RSS et en une seule page, d'avoir un résumé de plusieurs sites web comme sur la capture d'écran suivante :
I-B. Subscription▲
Ces flux RSS sont normalement disponibles au grand public et peuvent se trouver soit via des annuaires de RSS soit simplement en naviguant sur vos sites préférés. Aujourd'hui, la plupart des navigateurs vous indiquent lorsqu'un flux est disponible. Ainsi, tandis que Mozilla Firefox affichera le logo RSS à droite de la barre d'URL, Internet Explorer affichera un bouton listant les flux RSS disponibles.
En cliquant sur l'un des flux disponibles, vous pourrez alors vous inscrire (c'est gratuit et instantané) au flux RSS. Dans cette page qui s'est ouverte, vous sont listées les dernières nouvelles du site en question. Notez que l'affichage que vous avez est réalisé par votre navigateur web. Un flux RSS n'est en réalité qu'un simple fichier XML comme l'exemple suivant :
<rss
version
=
"2.0"
>
<channel >
<title>
Titre du flux</title>
<link>
http://monflux.com</link>
<description>
Ceci est un exemple de flux</description>
<lastBuildDate>
Sat, 13 Oct 2007 17:29:38 Z</lastBuildDate>
<category
domain
=
"CategoryScheme"
>
Catégorie du flux</category>
<item>
<guid
isPermaLink
=
"false"
>
ItemID</guid>
<link>
http://monsite/items</link>
<title>
Titre de l'item</title>
<description>
Contenu de l'item</description>
</item>
</channel>
</rss>
I-C. Common Feed List▲
Où sont donc enregistrés ces flux RSS auxquels vous vous inscrivez? Cela dépend. Certains navigateurs web comme Mozilla Firefox utilisent leur propre moteur interne afin de les afficher comme des favoris dynamiques, tandis qu'Internet Explorer les enregistre dans un annuaire local : la Common Feed List.
Cette dernière est visible à l'intérieur même d'IE7 (Internet Explorer 7) dans un panel latéral, mais peut, et c'est là que réside tout son intérêt, être utilisé à l'intérieur d'autres applications.
II. Utilisation▲
II-A. Plateforme RSS Windows▲
Commençons par voir quelle est l'architecture de cette « plateforme RSS » et quelles interfaces nous sont proposées pour l'interroger ou la piloter.
Notre objet principal sera donc le FeedsManager qui servira de grand conteneur dans lequel tous les autres éléments se trouveront. Dans ce conteneur peuvent déposer des dossiers (FeedFolder) ou directement des flux RSS (Feed). Normalement, les flux RSS sont censés être rangés dans des dossiers, mais si par hasard vous les placez à même le conteneur (FeedManager), celui-ci est alors considéré comme le RootFolder et donc propose les mêmes méthodes qu'un objet FeedFolder.
Enfin, un flux RSS est composé d'un nombre dynamique de FeedItems qui correspondent à chaque billet publié dans le fichier RSS distant.
II-B. Intégration de la Common Feed List▲
II-B-1. Listing des flux existants▲
Nous venons de voir qu'Internet Explorer était l'exemple même de l'intégration de cet annuaire de flux au sein d'une application. Il faut savoir que cette intégration peut se faire sous des dizaines de formes possibles puisque c'est vous qui choisissez les informations que vous affichez et surtout, comment vous les affichez. Pour ma part, j'ai eu envie d'avoir un panneau latéral listant les flux et les rangeant dans leurs dossiers respectifs, ces dossiers étant représentés par des groupes dans une listView.
L'intégration se fait donc en deux étapes. Tout d'abord, je vais créer les groupes dans ma listView puis je fais lister les flux en les plaçant dans le bon groupe.
Je commence par récupérer une instance de mon FeedManager.
FeedsManager myFMng =
new
FeedsManager
(
);
Petit problème, cet objet FeedManager n'est pas connu par Visual Studio. Il manque donc une référence.
Ajoutez la libraire Microsoft Feeds à votre projet puis importez-la avec :
using
Microsoft.
Feeds.
Interop;
II-B-2. Récupération des billets▲
Avoir une liste de flux est intéressant, mais il peut être plus intéressant d'afficher leur contenu. Ces éléments, des news ou bien des billets de blog, sont constitués de différents éléments en fonction du format du flux RSS. Les plus communs sont RSS 2.0 et ATOM 1.0 qui, pour chaque élément, spécifient son titre, son auteur et sa description (souvent un résumé). Heureusement pour nous, l'API Microsoft nous fournit un objet IFeedItem qui représente chaque élément et qui fournit plusieurs propriétés permettant d'obtenir le nom de l'auteur, le lien vers le billet ou la description d'une news.
Dans notre cas, nous allons, lorsqu'un flux est sélectionné, lister tous ses éléments dans une listView puis, lorsqu'un de ces éléments sera sélectionné, son contenu sera affiché dans un webBrowser intégré.
private
void
listView1_SelectedIndexChanged
(
object
sender,
EventArgs e)
{
if
(
listView1.
SelectedItems.
Count >
0
)
{
updateFeed
(
listView1.
SelectedItems[
0
].
Text);
// méthode qui va mettre à jour la liste des billets
}
else
clearFields
(
);
}
Et voici la méthode updateFeed(). Dans mon exemple, je traite différemment les flux qui sont placés dans un sous-dossier et ceux qui sont à la racine. Selon votre configuration, il sera sûrement plus intéressant de travailler avec le « Path » d'un flux, ce qui correspond à son « dossier\son nom ».
Ainsi, après avoir récupéré le dossier dans lequel le flux se trouve, je récupère une référence dans le FeedManager puis je vais énumérer ses Items en récupérant les informations qui m'intéressent pour construire ma listView.
///
<
summary
>
/// Récupère la liste des billets
///
<
/summary
>
///
<
param
name
=
"feed"
><
/param
>
private
void
updateFeed
(
String feed)
{
clearFields
(
);
IFeed myF =
null
;
if
(
listView1.
SelectedItems[
0
].
Group.
Name !=
"Autres"
)
{
IFeedFolder curFol =
(
IFeedFolder)myRootFld.
GetSubfolder
(
listView1.
SelectedItems[
0
].
Group.
Name);
myF =
(
IFeed)curFol.
GetFeed
(
feed);
}
else
if
(
myRootFld.
ExistsFeed
(
listView1.
SelectedItems[
0
].
Text))
{
myF =
(
IFeed)myRootFld.
GetFeed
(
feed);
}
if
(
myF !=
null
)
{
foreach
(
IFeedItem fit in
(
IFeedsEnum)myF.
Items)
{
ListViewItem lvi =
new
ListViewItem
(
fit.
Title);
lvi.
SubItems.
Add
(
fit.
Author);
lvi.
SubItems.
Add
(
fit.
PubDate.
ToShortDateString
(
));
listView2.
Items.
Add
(
lvi);
listView2.
Items[
listView2.
Items.
Count -
1
].
BackColor =
(
listView2.
Items.
Count %
2
==
0
) ?
Color.
Gainsboro :
Color.
White;
}
}
}
II-C. Modifier la Common Feed List▲
II-C-1. Ajout d'un dossier de rangement▲
Lorsque vous ajoutez un flux, vous pouvez soit l'ajouter à la racine du FeedManager soit le ranger dans un sous-dossier, fonctionnalité très intéressante lorsque vous avez un grand nombre de flux RSS.
Supposons que nous souhaitions ajouter un sous-dossier nommé « test », il nous suffit d'avoir une référence vers le dossier racine de notre FeedManager puis d'appeler la méthode CreateSubFolder :
myRootFld.
CreateSubfolder
(
"test"
);
II-C-2. Ajout d'un flux▲
Nous avons vu comment intégrer la Common Feed List au sein d'une application, mais nous allons maintenant chercher à la modifier. Il faut savoir que si vous la modifiez dans votre application, elle sera également modifiée dans toute application qui l'utilise (Internet Explorer 7 par exemple).
Comme première modification, nous allons donc ajouter notre propre flux RSS. Ici, je souhaiterais ajouter le flux RSS de la rubrique Dotnet dont l'URL est http://dotnet.developpez.com/rss.php. Je vais appeler mon flux « rubrique dotnet » afin de le reconnaitre facilement.
Pour cela, j'utilise la méthode CreateFeed();
if
(!
myFMng.
IsSubscribed
(
"http://dotnet.developpez.com/rss.php"
))
{
(
myRootFld.
CreateFeed
(
"rubrique Dotnet"
,
"http://dotnet.developpez.com/rss.php"
);
}
je vérifie si je ne suis pas déjà inscrit sur cette adresse afin de ne pas avoir de flux en double.
Dans le cas précédent, nous avons ajouté un flux à la racine de notre FeedManager, mais maintenant que nous savons comment créer des sous-dossiers, autant y placer directement notre flux. Il nous suffit de récupérer une référence vers le sous-dossier désiré plutôt que le dossier racine
if
(!
myFMng.
IsSubscribed
(
txtUrl.
Text))
{
((
IFeedFolder)myRootFld.
GetSubfolder
(
"test"
).
CreateFeed
(
"rubrique Dotnet"
,
"http://dotnet.developpez.com/rss.php"
);
}
Il ne nous reste plus qu'à vérifier que notre flux se trouve effectivement dans notre sous-dossier.
II-C-3. Suppression▲
Il est bien sûr possible de supprimer un flux. Pour cela, il suffit d'obtenir l'objet IFeed souhaité et d'appeler la méthode Delete().
Dans l'exemple suivant, je récupère l'objet grâce à la méthode GetFeed() et le nom du feed qui est affiché dans ma listView puis je le supprime.
((
IFeed)myRootFld.
GetFeed
(
listView1.
SelectedItems[
0
].
Text)).
Delete
(
);
Pour faire plus propre, et éviter d'avoir une listView désynchronisée du vrai FeedManager, il aurait été mieux de créer une classe personnelle ayant une propriété Nom (type string) et une autre de type IFeed et nous aurions binder cette liste directement sur une combobox ou listbox.
Cela permet ainsi de récupérer directement l'objet IFeed désiré. Je n'ai pas fait cela, car il m'aurait fallu créer un contrôle dérivant de ListView pour gérer son DataBinding. Avec une combobox, cela ressemble à ceci :
List<
maClass>
maList =
new
List<
maClass>(
);
foreach
(
IFeed feed in
root.
Feeds)
{
maList.
Add
(
new
maClass
(
feed.
Name,
feed));
}
maCombobox.
DataSource =
maList;
maCombobox.
DisplayMember =
"Nom"
;
maCombobox.
ValueMember =
"Feed"
;
maCombobox.
DataBind
(
);
...
public
class
maClass
(
)
{
// les getsetter sont enlevés pour une meilleure lisibilité
public
string
Nom;
public
IFeed Feed;
public
maClass
(
string
nom,
string
feed)
{
this
.
Nom =
nom;
this
.
Feed =
feed;
}
}
III. Pour aller plus loin - les évènements▲
Il existe des évènements que l'on peut gérer directement dans l'application. Quels sont ces évènements allez vous me dire, et bien il s'agit d'informations sur les flux, comme quand par exemple, un flux est mis à jour. Ainsi, dans l'application de démo, lorsque vous cliquez sur un flux, ses données sont listées, mais si le flux a été supprimé en dehors de votre application, vous allez avoir une belle exception. La solution est alors de détecter quand celui-ci est supprimé et de le supprimer de votre côté (en rafraichissant la liste dans mon cas).
Reprenons un bout de code pour avoir une instance de notre FeedManager :
FeedsManager manager =
new
FeedsManager
(
);
IFeedFolder root =
(
IFeedFolder)manager.
RootFolder;
Puis nous créons notre watcher qui va « écouter » les évènements. Une fois de plus un cast explicite est nécessaire :
IFeedFolderEvents_Event watcher;
watcher =
(
IFeedFolderEvents_Event) root.
GetWatcher
(
FEEDS_EVENTS_SCOPE.
FES_ALL,
FEEDS_EVENTS_MASK.
FEM_FOLDEREVENTS);
Il ne nous reste plus qu'à mettre l'évènement que l'on souhaite.
watcher.
FeedDeleted +=
watcher_FeedDeleted;
Ainsi que la méthode appelée qui recharge notre liste quand un flux est supprimé :
public
void
watcher_FeedDeleted
(
string
path)
{
LoadExistingFeeds
(
);
//recharge la liste des feeds et les dossiers
}
Les évènements sont nombreux, il y en a pour les flux, mais également pour les dossiers. Que cela soit du renommage, du téléchargement, de la mise à jour, suppression, ajout ou autre, vous pouvez être tenu au courant de quasiment tout ce qui est possible. Vous trouverez la liste des évènements possibles à cette URL
Conclusion▲
Nous avons découvert tout au long de cet article qu'il existait un annuaire commun de flux RSS sur Windows et qu'il était possible de l'intégrer ou de le manipuler au sein d'une application .Net.
Les utilisations possibles sont nombreuses, allant du simple agrégateur RSS à la fonctionnalité qui surveille un flux bien précis pour être au courant d'une mise à jour logiciel et pourquoi pas télécharger automatiquement la nouvelle version. Il existe encore plein d'autres possibilités et je vous laisse donc faire bon usage de cette technologie.
Liens▲
Manipuler les flux RSS 2.0 et Atom 1.0 avec le Framework 3.5 par Florian Casabianca
Windows RSS Platform (MSDN)
sources du projet de démonstration utilisé au sein de cet article.
Remerciements▲
Je tiens à remercier Fleur-Anne Blain pour ses conseils pour l'amélioration de cet article.