Pour aller plus loin avec RDFa

Gautier Poupeau

Cet article vous montre le fonctionnement de RDFa en instaurant les bases. Vous pourrez ensuite voir un petit exemple d'application pour mettre en œuvre le RDFa. Il y a aussi une petite liste non exhaustive de plugins pour Firefox qui permettent de traiter le RDFa contenu dans les pages Web.

Commentez

- Titre : Pour aller plus loin avec RDFa

- Auteur : Gautier Poupeau

- Parution : 22 mai 2011

- Mise à jour : 5 janvier 2016

- Public visé :

- Licence : Copyright ® 2011-2016 Gautier Poupeau. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Introduction

- II. Et si on sémantisait un peu le Web

- III. La knowledge box

- III-A. Explication de la knowledge box

- III-B. Le code de la knowledge box

- IV. Extensions Firefox

- V. Comment utiliser ces extensions

- V-A. Petit mode d'emploi côté utilisateur

- V-B. Comment ça marche ?

- VI. Divers

I - Introduction

RDFa est une syntaxe qui vise à inclure des triples RDF dans des pages Web en XHTML. Le principe de base est le même que les Microformats. La syntaxe est différente, mais surtout, là où les microformats proposent de nouveaux vocabulaires, RDFa réutilise les propriétés définies dans des vocabulaires RDF (Dublin Core, SKOS, Geo, OWL et tous les autres…) et même les instances définies dans d'autres fichiers RDF que l'on peut pointer via son URI.

II - Et si on sémantisait un peu le Web

Je répète à longueur de temps que structurer un contenu en XML, et a fortiori en HTML, ne constitue pas une sémantisation, mais permet d'indiquer le rôle joué par la portion d'information dans le contexte d'un document. Les normes du Web sémantique ont à l'inverse vocation à aider à la sémantisation du contenu. Mais, à force de le répéter sans rien montrer de probant, vous allez finir par croire que c'est une chimère. Soyons clairs, nous sommes encore loin du compte, mais nous avons fait des avancées, exemple avec RDFa.

RDFa fait déjà énormément parler de lui, comme le prouvera ma prochaine pelote. Kesako ? RDFa est une syntaxe qui vise à inclure des triples RDF dans des pages Web en XHTML. Exemple simple, si dans ma page Web, j'inclus le nom du créateur de la page, au lieu de l'exprimer une fois dans l'en-tête et une fois dans le corps de ma page, j'ajoute cette information simplement dans le corps de ma page à l'endroit prévu :

<span property="dc:creator">Gautier Poupeau</span>

En indiquant la propriété Dublin Core « creator », j'ai bien précisé que la chaîne de caractères « Gautier Poupeau » est le créateur du document. Je peux même raffiner, en indiquant un lien vers ma description dans mon fichier FOAF, qui correspond à l'URI qui me décrit :

<span rel="dc:creator" href="http://www.lespetitescases.net/foaf_got.rdf#GP">
Gautier Poupeau
</span>

Si vous voulez d'autres exemples et des explications plus complètes, je vous renvoie au très bon article de Bob duCharme sur XML.com. Pour ceux qui connaissent, cela vous rappellera le principe des microformats. Le principe de base est effectivement le même, la syntaxe est un peu différente, mais surtout, là où les microformats proposent de nouveaux vocabulaires, RDFa réutilise les propriétés définies dans des vocabulaires RDF (Dublin Core, SKOS, Geo, OWL et tous les autres…) et même les instances définies dans d'autres fichiers RDF que l'on peut pointer via son URI. RDFa offre donc une puissance supplémentaire, mais par ricochet, présente une complexité plus grande, d'où l'importance que les deux syntaxes coexistent.

Maintenant que je vous ai brossé à grands traits les RDFa, passons au vif du sujet : « et si on sémantisait un peu le Web ». Depuis peu, nous disposons de bases importantes de données structurées en RDF : Wordnet, DBpedia dont je vous ai déjà parlé, Geonames sur les informations géographiques qui intègre les informations de l'INSEE, par exemple, et le mouvement va aller en s'accélérant. Pour sémantiser, il suffit alors d'indiquer qu'une portion d'informations équivaut à un objet défini par une URI dans un fichier RDF, c'est précisément le sens de la propriété OWL « sameAs » (P.-S. perso Alex, j'attends avec impatience le billet à ce sujet). Si je reprends l'exemple précédent :

<span rel="owl:sameAs" href="http://www.lespetitescases.net/foaf_got.rdf#GP">
Gautier Poupeau
</span>

Quelles utilités ? Il existe de multiples utilisations, mais par exemple, si j'indique une liste de noms dans un document HTML, je pourrais via ce système et le FOAF respectif de chaque personne voir quelle est la relation entre les différentes personnes, si la relation est indiquée dans leur FOAF. On peut aussi imaginer un moteur de recherche renvoyant vers ce blog, si une personne fait une requête en relation avec un intérêt décrit dans mon FOAF…

Mais, restons, si vous le voulez bien sur le moteur de recherche, si à présent, en lieu et place d'un fichier FOAF, j'indique une URI vers DBpedia, par exemple :

<span id="sartre" about="#sartre" rel="owl:sameAs" href="http://dbpedia.org/page/Jean-Paul_Sartre">
Jean-Paul Sartre
</span>

Le moteur de recherche indexe non seulement ma page Web, mais aussi la notice de Jean-Paul Sartre en RDF dans DBpedia qu'il associe à cette page Web. Je vais alors décupler les possibilités de recherche. Imaginons que je fasse la requête : « philosopher french existentialist ». Même si ces trois mots n'apparaissent pas dans ma page Web d'origine, comme ils apparaissent dans la notice en RDF, le moteur doit être capable de me renvoyer cette page. Un autre exemple avec un nom de lieu :

<span id="paris" about="#paris" rel="owl:sameAs" href="http://dbpedia.org/resource/Paris">
Paris
</span>

La notice de Paris dans DBpedia indique le nom de Paris dans les différentes langues, donc si une personne effectue la requête « Parigi », le moteur sera capable de donner en réponse ma page qui contient, quant à elle, la forme « Paris ».

Je pense que vous avez compris le principe et vous serez d'accord avec moi que, dans ce cas-là, le processus de sémantisation est enclenché et cela ne me semble pas bien compliqué à implémenter dans le crawler d'un moteur de recherche. Je laisse mes lecteurs bibliothécaires imaginer les possibilités avec un thésaurus comme Rameau.

Mais, j'entends d'ici les esprits chagrins qui vont voir au moins deux problèmes dans cette proposition.

Premièrement, certains pourraient y voir un moyen de faire augmenter leur page Rank en liant vers des fichiers RDF en relation avec les dernières séries à la mode, avec le sexe et j'en passe… Il existe une parade. Il suffit que les moteurs de recherche n'indexent ces informations que si elles sont liées avec des triple store RDF que les moteurs de recherche reconnaissent et qu'ils savent dignes de confiance. On pourrait aussi imaginer un système qui n'indexe que dans le cas où la chaîne de caractères concernée est présente dans l'objet RDF. Ça limite les possibilités, mais comme « le monde est infâme et méchant », il faut bien se prémunir.

Deuxièmement, il est clair qu'avant que tout le monde n'ajoute ce genre d'information, de l'eau aura coulé sous les ponts et ce n'est pas demain la veille que Google implémentera ce genre de fonctionnalités. Complètement d'accord avec vous. Mais, de plus en plus de sites Web possèdent un moteur de recherche interne, il est donc tout à fait possible de déployer un tel système pour améliorer la pertinence des résultats de votre moteur interne.

Bref, c'est à vous de jouer avec vos données, surtout qu'il existe d'autres possibilités avec RDFa, j'y reviendrai. Quant aux éditeurs de moteur de recherche, vu la concurrence acharnée qu'ils se livrent, avant longtemps ils feront la course pour implémenter cette fonctionnalité.

III - La knowledge box

III-A - Explication de la knowledge box

En vue d'explorer les possibilités de RDFa, j'ai mis au point une petite application. Dans la barre à droite sur ce blog, j'ai ajouté une boîte dite Knowledge box. Son principe est simple. En cliquant sur un terme, le résumé de sa définition dans Wikipédia et un lien vers la page de Wikipédia francophone s'affichent.

En soi, l'idée n'est pas révolutionnaire et j'aurais pu le faire sans déployer toute l'artillerie des technologies du Web sémantique, mais ce qui me paraît intéressant dans cette expérience, c'est de montrer les atouts de disposer d'une syntaxe normalisée pour repérer des entités, RDFa, qui peut être exploitée de différentes façons afin de disposer d'une base de données structurée dans une syntaxe normalisée avec des URI identifiant chaque concept, Dbpedia en RDF et d'un langage de requêtes normalisé, Sparql. Bref, j'aurais pu faire cette expérience avec une base de données MySQL et quelques scripts PHP, mais dans ce cas, il aurait fallu que je maintienne les définitions et ma solution n'aurait pu être implémentée que sur mon site. Évidemment, nous sommes encore loin du rêve de Tim Berners-Lee d'agents intelligents capables de rapatrier et d'agréger les données pour répondre à une question précise, mais imaginez les possibilités d'une telle application dans une bibliothèque numérique qui afficherait les données des notices d'autorités, mises à la disposition de tous en RDF ou dans une édition critique en ligne qui afficherait les notices biographiques provenant de l'agrégation de toutes les bases de données prosopographiques qui traînent dans les labos d'histoire en France… Je suis sûr que vous trouverez plein d'autres idées.

Maintenant, concrètement, un script PHP parse le contenu du billet via Xpath et récupère toutes les chaînes de caractères des nœuds dont l'attribut rel contient la propriété OWL « owl:sameAs ». L'URI indiquée permet de construire la requête en Sparql pour interroger l'entrepôt de données RDF de DBpedia. Le résultat est affiché sur cette page grâce à AJAX et le tour est joué. Bon, c'est codé avec les pieds, mais si certains d'entre vous sont intéressés, ce sera un plaisir de donner le script. Je vais continuer à l'améliorer (si certains veulent m'aider, ce sera aussi avec plaisir), pour diversifier les données RDF interrogées, les différentes propriétés affichées (une image, les coordonnées géographiques…) et si, en tant que lecteur, ça vous intéresse, n'hésitez pas à me le préciser, je généraliserai cette knowledge box à tous les billets.

III-B - Le code de la knowledge box

Plusieurs d'entre vous m'ont demandé le code de la knowledge box. C'est avec plaisir que je vous en fais part, mais autant vous prévenir tout de suite je suis un très mauvais codeur quand il s'agit d'utiliser un langage de programmation. Merci d'avance pour votre indulgence à ce sujet.

Six parties composent la knowledge box :

- la classe PHP, RAP (RDF API for PHP) mise au point par Chris Bizer, permet d'interroger le SPARQL endpoint de Dbpedia ;

- un script PHP qui utilise cette classe et qui rapatrie les données ;

- un script JavaScript très très simple pour l'AJAX ;

- un bout de code PHP à introduire dans un bloc de Drupal ;

- les triples RDFa dans votre contenu.

Pour RAP, il suffit de le télécharger et de le poser dans votre arborescence. Attention au chemin, il nous sera utile pour y faire référence dans le script PHP.

Le script PHP permet d'interroger le serveur SPARQL de Dbpedia, de construire la requête et de formater la réponse qui revient en HTML.

<!--Le chemin vers RAP -->
define("RDFAPI_INCLUDE_DIR", "./api/");
include(RDFAPI_INCLUDE_DIR . "RdfAPI.php");
<!--Ici on récupère l'argument URI dans l'URL qui correspond à l'objet du triple RDF, par exemple, http:/dbpedia.org/resource/Tim_Berners-Lee-->
$uri=$_GET['uri'];
<!--J'instancie un appel au serveur SPARQL de Dbpedia-->
$client = ModelFactory::getSparqlClient("http://dbpedia.org/sparql");
<!--Je demande les résultats au format XML, mais pour l'instant il semble qu'il y ait un bogue et c'est du HTML zarbi qui est renvoyé-->
$client->setOutputFormat("xml");
<!--La requête en SPARQL : concrètement, je récupère le résumé en français et le lien vers la page de la Wikipédia francophone-->
$querystring = "
PREFIX owl: >http://www.w3.org/2002/07/owl#>
PREFIX xsd: >http://www.w3.org/2001/XMLSchema#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX dc: <http://purl.org/dc/elements/1.1/>
PREFIX : <http://dbpedia.org/resource/>
PREFIX dbpedia2: <http://dbpedia.org/property/>
PREFIX dbpedia: <http://dbpedia.org/>
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
SELECT ?hasValue ?wikifr
WHERE {
{ <".$uri."> <http://dbpedia.org/abstract> ?hasValue.
<".$uri."> <http://dbpedia.org/property/wikipage-fr> ?wikifr
}
FILTER ( lang(?hasValue) = \"fr\" )
}
";
$query = new ClientQuery();
$query->query($querystring);
$result = $client->query($query);
$result="<div>".$result."</div>";
<!--Mise en forme du résultat avec un peu de XPath et simpleXML de PHP5-->
$xml = new SimpleXMLElement($result);
if ($xml->xpath('/div/table/tr[2]')) {
foreach($xml->xpath('/div/table/tr[2]') as $line) {
echo "<span>".$line->td[0]."</span><br/><a href=".$line->td[1].">En savoir plus</a>";
}
}
else {
echo "pas d'information";
}

Le script JavaScript pour l'AJAX est ultra simple. Il se contente de ramener la page Web query.php à laquelle je fais passer l'argument URI :

function objAjax(){
var xhr = null;
if(window.XMLHttpRequest) // Firefox et autres
xhr = new XMLHttpRequest();
else if(window.ActiveXObject){ // Internet Explorer
try {
xhr = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
}
else { // XMLHttpRequest non supporté par le navigateur
alert("Votre navigateur ne supporte pas les objets XMLHTTPRequest...");
xhr = false;
}
return xhr
}
/*** Méthode qui sera appelée sur le clic du bouton*/
function go(arg1){
var xhr = objAjax()
// On définit ce qu'on va faire quand on aura la réponse
xhr.onreadystatechange = function(){
if(xhr.readyState == 1) {
document.getElementById('reponse').innerHTML="<img src='http://www.lespetitescases.net/images/spinner.gif'/>"
}
// On ne fait quelque chose que si on a tout reçu et que le serveur est OK
if(xhr.readyState == 4 && xhr.status == 200){
var reponse=xhr.responseText.replace( /\\u0*([0-9A-F]*)/g, '&#x$1;' );
var reponse=reponse.replace(/\\n/g, '<br/>');
document.getElementById('reponse').innerHTML=reponse;
}
}
var url="http://lespetitescases.net/essai/rapi/query.php?uri="+arg1
xhr.open("GET",url,true);
xhr.send(null);
}

Dans Drupal (je vous laisse adapter en fonction de votre CMS), il faut créer un nouveau bloc que j'ai limité à un billet, pour l'instant, avec ce code dont l'idée est d'analyser le contenu pour trouver les attributs RDFa (dans cet exemple, je me suis contenté de l'attribut rel et de la valeur owl:sameAs) :

if (arg(0) == 'node' && is_numeric(arg(1)) && is_null(arg(2))) {
//Je récupère l'ID du node
$nid = (int)arg(1);
//Je vais récupérer le corps de ce node dans la base de données MYsql
$sql = "SELECT title,body FROM node_revisions WHERE nid={$nid}";
$result = db_query(db_rewrite_sql($sql));
while ($anode = db_fetch_object($result)) {
$content=$anode->body;
$content="<div>".$content."</div>";
$xml = new SimpleXMLElement($content);
//Je fais une requête XPath pour trouver tous les nœuds qui comportent l'attribut rel avec la valeur owl:sameAs
if ($xml->xpath('//node()[@rel="owl:sameAs"]')) {
echo "<ul>";
//Pour chacun de ces nœuds, je le mets en forme
foreach($xml->xpath('//node()[@rel="owl:sameAs"]') as $triple) {
$url=$triple['href'];
$string=$triple;
//Je fais l'appel au JavaScript en passant en argument l'URI objet.
echo "<li><a href='#' onclick='go(\"".$url."\")'>".$triple."</a></li>";
}
echo "</ul><span id='reponse'></span><br/>";
}
else {
echo "<p>Pas de triplets RDFa dans ce billet</p>";
}
}
}

Et pour finir, il faut introduire les triplets en RDFa dans votre contenu :

<span id="php" about="#php" rel="owl:sameAs" href="http://dbpedia.org/resource/PHP">PHP</span>

Pour retrouver l'URI, vous pouvez utiliser l'interrogation plein texte de Dbpedia avec bif:contains.

Comment améliorer cette knowledge box ? Je vois plusieurs pistes :

- amélioration du code ;-) ;

- permettre à l'utilisateur de rapatrier d'autres propriétés, c'est-à-dire paramétrer la requête SPARQL ;

- ne pas se limiter à Dbpedia, mais rapatrier des informations contenues dans un fichier FOAF, par exemple, ou dans un autre RDF triple Store ;

- afficher une carte de Yahoo Maps ou de Google Maps quand le sujet est un lieu ;

- et toutes vos idées…

Il n'y a pas de licence, vu la bidouille de ce code, mais vous pouvez le récupérer, l'adapter, le triturer, l'améliorer…

IV - Extensions Firefox

Operator est une extension Firefox qui permet d'exploiter les données encodées en microformats ou en RDFa dans une page Web. J'ai mis au point deux scripts utilisateur pour Operator :

- le plugin ISBN offre un lien vers Amazon ou Library Thing d'un ouvrage dont on a indiqué l'ISBN en RDFa ;

- le plugin Explore URL permet de visualiser dans del.icio.us si une page Web a été référencée.

V - Comment utiliser ces extensions

Dans ma quête d'exemples simples de l'intérêt du Web sémantique pour tous, ma route ne pouvait ignorer l'extension Firefox Operator, dont la dernière version supporte RDFa, d'autant plus que Charles avait lancé un défi que je me devais de relever.

Pour ceux qui ne connaissent pas encore Operator, cette extension permet de repérer dans une page Web des annotations sémantiques à la base écrites avec les microformats pour effectuer des actions comme repérer un lieu dans Google Maps, récupérer une carte de visite…

Après une longue réflexion, j'ai trouvé deux utilisations originales :

- un exemple très bibliothéconomique pour visualiser un ouvrage dans Amazon ou Library Thing à partir de l'ISBN ;

- un autre plus narcissique pour visualiser dans del.icio.us si une page Web a été référencée.

V-A - Petit mode d'emploi côté utilisateur

- Première étape : vous installez Opérator à partir du site de Mozilla addons.

- Deuxième étape : un des avantages d'Operator est de pouvoir ajouter des scripts utilisateur, il vous faut donc télécharger les deux scripts que j'ai mis au point : isbn.js et sioc_delicious.js et les enregistrer sur votre disque.

- Troisième étape : vous cliquez sur Options de la barre d'outils d'Opérator et dans l'onglet « User scripts » vous importez les deux scripts en cliquant sur Nouveau et vous relancez votre navigateur.

- Quatrième étape : vous cliquez sur Options de la barre d'outils d'Opérator et dans l'onglet « Actions » vous ajoutez « Show with Amazon », « Show with Library Thing » et « Explore URL with del.icio.us » et vous relancez le navigateur.

- Cinquième étape : vous pouvez tester les deux premières actions sur la page Lu, écouté, vu de ce blog (attention, certains ouvrages ne donnent aucun résultat dans Library Thing, car je pense que le livre n'y est pas enregistré) et la troisième sur la page d'accueil (si certaines URL ne donnent pas de résultat, c'est tout simplement parce qu'aucune personne n'a enregistré cette URL dans del.icio.us, mais vous pouvez résoudre ce problème).

V-B - Comment ça marche ?

Concrètement, j'ai donc ajouté du RDFa dans mes pages.

Pour les livres et l'ISBN, j'ai utilisé Dublin Core, la propriété dc:identifier et l'espace de noms urn:isbn défini par la RFC 3187 de l'IETF ce qui donne :

<div about="http://lespetitescases.net/harry-potter-VII" property="dc:title"
content="Harry Potter and the Deathly Hallows">
<h2>Harry Potter and the Deathly Hallows</h2>
<span property="dc:identifier" content="urn:isbn:0747591059"
style="display: none;">urn:isbn:0747591059</span>
<p>[...]</p>
</div>

Le script détecte la présence de la propriété dc:identifier et s'il contient urn:isbn, il récupère l'ISBN et construit l'URL vers Amazon et Library Thing.

Les applications possibles de cet exemple sont multiples. Ainsi on peut, en changeant le script, renvoyer vers d'autres sites qui peuvent servir une notice à partir de l'ISBN, comme le SUDOCWorldCat ou . On peut aussi implémenter ces RDFa dans des bibliographies ou dans des catalogues de bibliothèques pour accéder directement à la notice sur un autre site pour l'acheter ou vérifier sa disponibilité dans une bibliothèque.

Pour repérer qui référence un lien dans del.icio.us, j'ai utilisé l'ontologie SIOC (Semantically-Interlinked Online Communities) qui, au passage, vient d'être soumise au W3C (alors, Alex, ça fait quoi d'avoir son nom sur un futur standard du W3C) ce qui donne :

<h2 class="sioc:post"
about="http://www.lespetitescases.net/le-web-semantique-rencontre">
<span property="dc:title" content="Le Web sémantique rencontre....">
Le Web sémantique rencontre
</span>
</h2>

Le script repère qu'une ressource est de type sioc:post. Si c'est le cas, il repère l'URL du billet (le contenu de l'attribut about, c'est-à-dire le sujet du triple) et renvoie à la page d'historique de ce lien dans del.icio.us. Dans ce cas-là, à part le plaisir narcissique de savoir si tel ou tel billet est référencé dans del.icio.us, je ne vois pas vraiment d'autres applications, mais je suis persuadé que SIOC est plein de ressources pour trouver d'autres idées.

Vous remarquerez que, dans les deux cas, j'ai utilisé la propriété dc:title. Son contenu est automatiquement récupéré par Operator pour construire le menu déroulant. En cas d'absence, Operator indique l'URI de la ressource ce qui n'est pas très user-friendly, vous en conviendrez.

Je vous laisse vous amuser, implémenter ces RDFa dans vos sites ou créer de nouveaux scripts, honnêtement, ce n'est pas très compliqué et vous ajouterez une pierre à l'édifice du Web sémantique.

VI - Divers

Cet article est tiré du blog http://www.lespetitescases.net nous remercions d'ailleurs Gautier Poupeau pour son autorisation de transcrire son blog sur developpez.com, ainsi que Claude Leloup pour la correction orthographique et à Julien Plu pour la mise en page.