FLASH INFORMATIQUE FI



SPARQL, langage et protocole d’interrogation de métadonnées




Francis LAPIQUE


Cet article, le troisième d’une série consacré au Web sémantique, a pour sujet SPARQL, un langage et protocoles de requêtes pour l’interrogation de métadonnées sous forme de fichiers RDF ou plus exactement un langage d’interrogation de triplets RDF. Rappelons qu’un triplet RDF est une association :

sujet, objet, predicat

.
J’invite les lecteurs peu familiarisés avec ce formalisme à lire ou relire les articles précédents sur RDF/RDFS et OWL.
Dernièrement, les spécifications de SPARQL Query Language for RDF, SPARQL Protocol for RDF et SPARQL Query Results XML Format s’enchaînent à un rythme rapide, les dernières qui datent respectivement du 4 octobre et 6 avril 2006 montrent la volonté du consortium W3C de faire des ces drafts des recommandations officielles et celle de proposer des technologies matures pour le Web sémantique (WS).
Le site du W3C consacré au WS précise dans sa page d’accueil la vision de cette démarche. Nous traduisons :

"Le Web sémantique est un Web de données. De nombreuses données que nous utilisons tous les jours sont présentes sur l’Internet mais ne sont pas accessibles aux échanges (le Web proprement dit). C’est le cas de mon compte en banque, de mes photographies, de mes dates de rendez-vous. Mais je ne peux pas les rapprocher pour connaître par exemple ce que je faisais le jour où j’ai été photographié, ni l’état de mon compte en banque ce jour-là. Pourquoi ne peut-on pas le faire ? Parce que les données sont encapsulées dans des applications et que les applications ne sont pas conçues pour les échanger. Le Web Sémantique porte sur deux choses. Il définit des formats communs pour l’échange des données, alors que le Web traditionnel ne définit que les modalités d’échange des documents. Par ailleurs, il offre un langage commun permettant aux données de renvoyer à des objets du monde réel d’une façon identique. Ceci permet à une personne ou à une machine de construire des bases de données puis des réseaux de bases de données qui ne seront pas connectées par des liens physiques mais par le fait qu’elles désignent des objets identiques."

Pour illustrer ce langage dans une pratique il faut un moteur SPARQL et des exemples de graphes RDF. Pour le moteur j’ai choisi ARQ un élément du projet Jena qui est un cadre de développement pour les applications du WS. Pour les exemples RDF j’ai choisi FOAF (Friend Of A Friend) ? [1], un projet collaboratif visant à utiliser RDF pour créer un nouveau type de document décrivant des personnes et accessible en ligne.

FOAF les amis de mes amis...

Plus qu ’un discours, trois exemples.

exemple 1

<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:foaf="http://xmlns.com/foaf/0.1/"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
<foaf:Person>
  <foaf:name>Jimmy Wales</foaf:name>
  <foaf:mbox rdf:resource="mailto:jwales@bomis.com" />
  <foaf:homepage rdf:resource="http://www.jimmywales.com/" />
  <foaf:nick>Jimbo</foaf:nick>
  <foaf:depiction rdf:resource="http://www.jimmywales.com/aus_img_small.jpg" />
  <foaf:interest>
    <rdf:Description rdf:about="http://www.wikimedia.org" rdfs:label="Wikipedia" />
  </foaf:interest>
  <foaf:knows>
    <foaf:Person>
      <foaf:name>Angela Beesley</foaf:name> <!-- Wikimedia Board of Trustees -->
    </foaf:Person>
  </foaf:knows>
</foaf:Person>
</rdf:RDF>

exemple 2

<foaf:Person>
 <foaf:name>Peter Parker</foaf:name>
 <foaf:gender>Male</foaf:gender>
 <foaf:title>Mr</foaf:title>
 <foaf:givenname>Peter</foaf:givenname>
 <foaf:family_name>Parker</foaf:family_name>
<foaf:mbox_sha1sum>cf2f4bd069302febd8d7c26d803f63fa7f20bd82</foaf:mbox_sha1sum>
 <foaf:homepage rdf:resource="http://www.peterparker.com"/>
 <foaf:weblog rdf:resource="http://www.peterparker.com/blog/"/>
</foaf:Person>

exemple 3

<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
       xmlns:foaf="http://xmlns.com/foaf/0.1/"
       xmlns:dc="http://purl.org/dc/elements/1.1/"
       xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#">
<foaf:Person rdf:ID="peter">
 <foaf:name>Peter Parker</foaf:name>
 <foaf:depicts rdf:resource="http://www.peterparker.com/peter.jpg"/>
   <foaf:based_near>
   <geo:Point geo:lat="51.473" geo:long="-2.5432"/>
   </foaf:based_near>
</foaf:Person>

<foaf:Person rdf:ID="spiderman">
 <foaf:name>Spiderman</foaf:name>
</foaf:Person>

<foaf:Person rdf:ID="green-goblin">
 <foaf:name>Green Goblin</foaf:name>
</foaf:Person>

<!-- codepiction -->
<foaf:Image rdf:about="http://www.peterparker.com/photos/spiderman/statue.jpg">
 <dc:title>Battle on the Statue Of Liberty</dc:title>

 <foaf:depicts rdf:resource="#spiderman"/>
 <foaf:depicts rdf:resource="#green-goblin"/>

 <foaf:maker rdf:resource="#peter"/>
</foaf:Image>
</rdf:RDF>

On peut noter que la notion de personne (introduite par la balise ) est décrite par plusieurs caractéristiques, parmi lesquelles name, title, nickname, gender, etc. On remarquera également que les adresses email des différents individus dont il est fait référence n’apparaissent pas en tant que telles dans le fichier, mais sont représentées de façon codée et que la balise introduit des connaissances.

Cyril Fievet fait une bonne présentation du projet FOAF

Le principe en est simple : chaque personne est identifiée par un fichier FOAF, qui peut être placé n’importe où sur le Web, et qui contient, dans des champs normés et en XML, des informations la décrivant.
Chacun peut bien sûr choisir le nombre et la profondeur des informations le concernant. Les champs d’un fichier FOAF peuvent être le nom, l’adresse email, l’adresse du site Web et/ou du blog, les adresses des photos, les études suivies, les centres d’intérêt, les amis - et bien d’autres choses, selon les spécifications actuelles. La dernière version de FOAF établit une liste de plusieurs dizaines de champs possibles, répartis en cinq grandes catégories : les données de base (nom, prénom, etc.), les informations personnelles (centres d’intérêt, connaissances...), les comptes en lignes (email, messageries instantanées...), les documents et images (textes produits par la personne, photos personnelles...), et enfin les groupes et projets.
Cette dernière catégorie est particulièrement intéressante : elle permet le rattachement d’une personne à une organisation (association, entreprise) mais surtout, plus généralement, à un groupe quelconque. Il peut s’agir d’un groupe structuré (parti politique), informel, ou simplement d’une communauté en ligne. FOAF permet donc de représenter le regroupement d’individus selon plusieurs groupes, à la manière des fonctions proposées par les nombreuses communautés en ligne.
On le voit, les champs FOAF sont conçus pour exprimer de façon détaillée les caractéristiques d’un individu et ses liens - ?au sens large du terme ?- avec d’autres entités sur l’Internet, qu’il s’agisse de documents, d’images, ou d’autres individus. Et l’on comprend l’intérêt de ce qui pourrait devenir un Web sémantique pour les personnes. FOAF pourrait permettre de répondre à des requêtes extrêmement complexes, du genre : y a-t-il des Parisiens qui travaillent chez Microsoft, tiennent un blog, et s’intéressent à la nanotechnologie ?, ou simplement regrouper de façon automatique des gens qui ont sans le savoir des affinités très similaires (par exemple qui aime les mêmes genres de musique, lisent les mêmes blogs et pratiquent les mêmes sports...).
L’une des possibilités offertes par FOAF, qui illustre bien la puissance du procédé, est d’ailleurs la fusion de documents. Supposons que Pierre crée son fichier FOAF, et qu’il ne dispose pas de photos de lui-même. L’un de ses amis, Paul, a lui aussi un fichier FOAF, dans lequel il indique l’adresse d’une photo le montrant en compagnie de Pierre. Il est alors très facile, de façon automatisée, de fusionner les deux fichiers FOAF pour que la question Où peut-on consulter une photo de Pierre ? fournisse une réponse, en renvoyant sur la photo présentant Pierre et Paul. Sans nécessiter d’annuaire centralisé, FOAF permet par essence de lier les personnes - ?et leurs attributs ou caractéristiques ?- entre elles, comme si tout était décrit dans une base de données unique.

Le moteur SPARQL ARQ 0.9.5

ARQL est le moteur SPARQL du projet Jena. Pour l’installation il faut ramener la dernière distribution ARQ-1.x.zip et faire les exports nécessaires :

$ export ARQROOT=~/ARQ-0.9.5
$ chmod +rx $ARQROOT/bin/*
$ export PATH=$PATH:$ARQROOT/bin

et ajouter au CLASSPATH tous les fichiers jar du répertoire lib/ de la distribution.

ARQdir/lib/antlr-2.7.5.jar;ARQdir/lib/arq.jar;ARQdir/lib/commons-logging.jar;
ARQdir/lib/concurrent.jar;ARQdir/lib/icu4j_3_4.jar;ARQdir/lib/jakarta-oro-2.0.8.jar;
ARQdir/lib/jena.jar;ARQdir/lib/junit.jar;ARQdir/lib/log4j-1.2.12.jar;
ARQdir/lib/xercesImpl.jar;ARQdir/lib/xml-apis.jar

L’installation est finie, on peut lancer le moteur en passant la commande sparql.

$ sparql
Usage: [--data URL] [exprString | --query file]

Le tutorial d’ARQL est à l’adresse Pour le monde Windows on peut faire l’installation sous Cygwin.

Exemples de mise en oeuvre de SPARQL

Comme premier exemple, cherchons l’URL du blog de la personne de la communauté FOAF dont le nom est Dave Beckett. Cette communauté FOAF est décrite par un graphe bloggers.rdf dont nous reproduisons ci-dessous un extrait concernant Dave Beckett.

<foaf:Agent rdf:nodeID="id2244837">
<foaf:name>Dave Beckett</foaf:name>
<rdf:type rdf:resource="http://xmlns.com/foaf/0.1/Person"/>
<foaf:weblog>
<foaf:Document rdf:about="http://journal.dajobe.org/journal/">
<dc:title>Journalblog by Dave Beckett</dc:title>
<rdfs:seeAlso>
<rss:channel rdf:about="http://journal.dajobe.org/journal/comments.rdf">
<foaf:maker rdf:nodeID="id2244837"/>
<foaf:topic rdf:resource="http://www.w3.org/2001/sw/"/>
<foaf:topic rdf:resource="http://www.w3.org/RDF/"/>
</rss:channel>
</rdfs:seeAlso>
</foaf:Document>
</foaf:weblog>
<foaf:interest rdf:resource="http://www.w3.org/2001/sw/"/>
<foaf:interest rdf:resource="http://www.w3.org/RDF/"/>
</foaf:Agent>

Cette requête, traduite en dialecte SPARQL, se présente sous la forme de :

PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?url
FROM    <http://planetrdf.com/bloggers.rdf>
WHERE  {
   ?contributor foaf:name "Dave Beckett" .
   ?contributor foaf:weblog ?url .
}

La première ligne précise l’espace de nom c’est un raccourci pour, la clause SELECT nomme la variable qui sera renvoyée - ici  ?url (les variables SPARQL sont préfixées par ?), la clause FROM de la troisième ligne precise l’URI du dataset, la clause WHERE de la quatrième ligne est la série de graph pattern que l’on cherche à satisfaire. Le premier  ?contributor foaf:name "Dave Beckett" représente l’ensemble des sujets, la variable  ?contributor , liée à l’objet "Dave Beckett" par le prédicat foaf:name, le second l’ensemble des objets  ?url lié aux sujets  ?contributor par le prédicat foaf:weblog. La commande se fait comme suit (ex1.rq est le nom du fichier qui contient le code SPARQL) : #sparql —query ex1.rq.
Le résultat se présente sous la forme d’un tableau avec en première ligne le nom de la variable et en deuxième, le résultat :

----------------------------------------
| url                                  |
========================================
| <http://journal.dajobe.org/journal/> |
----------------------------------------

Vous pouvez à l’image de SQL ajouter une clause DISTINCT après SELECT ou LIMIT, OFFSET, et ORDER après WHERE. Juste à titre d’information, le framework Jena permet d’écrire un programme Java équivalent à la commande :

// Open the bloggers RDF graph from the filesystem
InputStream in = new FileInputStream(new File("bloggers.rdf"));

// Create an empty in-memory model and populate it from the graph
Model model = ModelFactory.createMemModelMaker().createModel();
model.read(in,null); // null base URI, since model URIs are absolute
in.close();

// Create a new query
String queryString =
        "PREFIX foaf: <http://xmlns.com/foaf/0.1/> " +
        "SELECT ?url " +
        "WHERE {" +
        "      ?contributor foaf:name \"Dave Beckett\" . " +
        "      ?contributor foaf:weblog ?url . " +
        "      }";

Query query = QueryFactory.create(queryString);

// Execute the query and obtain results
QueryExecution qe = QueryExecutionFactory.create(query, model);
ResultSet results = qe.execSelect();

// Output query results       
ResultSetFormatter.out(System.out, results, query);

// Important - free up resources used running the query
qe.close();

Pour plus d’information voici un pointeur sur l’API. L’option OPTIONAL, comme son nom le laisse entendre, permet de dire qu’un pattern peut-être optionnel. Dans l’exemple qui suit, on cherche à satisfaire le pattern  ?person foaf:name ?name et éventuellement celui  ?person foaf:depiction ?depiction :

PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name ?depiction
FROM    <bloggers.rdf>
WHERE {
       ?person foaf:name ?name .
       OPTIONAL {
           ?person foaf:depiction ?depiction .
       } .
     }


-------------------------------------------------------------------
| name               | mbox                                       |
===================================================================
| "Gregory Williams" | "d2063cf95ead7f1f364538ef6a0a086577713dcd" |
| "Danny Weitzner"   | "mailto:jon@foobar.xxx"                    |
-------------------------------------------------------------------

On peut imbriquer les OPTIONAL.
Dans le dataset bloggers.rdf, de l’exemple ci-contre, une personne a protégé explicitement son adresse de courrier des spammeurs en faisant appel à la balise foaf:mbox_sha1sum une autre ne l’a pas fait (balise foaf:mbox) et le reste n’ont pas fourni cette information. Pour trouver les personnes ayant un courrier et non les autres, on fait une UNION des deux pattern  ?person foaf:mbox ?mbox et  ?person foaf:mbox_sha1sum ?mbox.

PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
SELECT ?name ?mbox
FROM    <bloggers.rdf>
WHERE {
 ?person foaf:name ?name .
 {
     { ?person foaf:mbox ?mbox } UNION { ?person foaf:mbox_sha1sum ?mbox }
 }
}

Dans le dataset bloggers.rdf la seule personne accompagnée d’une image est "Tim Berners-Lee".

-------------------------------------------------------------------------------------
| name              | depiction                                                     |
=====================================================================================
| "Tim Berners-Lee" | <http://weblogs.elearning.ubc.ca/brian/archives/radiokid.jpg> |
| "Dave Beckett"    |                                                               |
| "Danny Ayers"     |                                                               |
| "John Barstow"    |                                                               |
-------------------------------------------------------------------------------------

Le mot-clef FILTER impose des contraintes sur les variables. Par exemple dans le dataset rss.rdf on trouve une référence à un flux RSS en date du 18 septembre 2006.

........
  <foaf:made>
     <rss:channel rdf:about="http://philwilson.org/rssify.php">
       <rss:title>philwilson.org</rss:title>
        <dc:date>2006-09-18T09:10:00Z</dc:date>
     </rss:channel>
   </foaf:made>    
   ........
   .........

Imaginons que l’on veuille connaître tous les articles datant de septembre 2006.

PREFIX rss:   <http://purl.org/rss/1.0/>
PREFIX xsd:   <http://www.w3.org/2001/XMLSchema#>
PREFIX  dc:   <http://purl.org/dc/elements/1.1/>
SELECT ?item_title ?pub_date
FROM <rss.rdf>
WHERE {
     ?item rss:title ?item_title .
     ?item dc:date ?pub_date .
     FILTER ( xsd:dateTime(?pub_date) >= "2006-09-01T00:00:00Z"^^xsd:dateTime &&  
              xsd:dateTime(?pub_date) < "2006-10-01T00:00:00Z"^^xsd:dateTime )
     }

Dans un premier temps on recherche les éléments liés par le prédicat rss:title, et dans un second la date de ceux-ci au moyen du prédicat dc:date en appliquant le filtre. && est l’opérateur booléen ET, quant à xsd:dateTime(?pub_date) et "2006-09-01T00:00:00Z"^^xsd:dateTime, ce sont deux casting en type xsd:dateTime.

---------------------------------------------
| item_title       | pub_date               |
=============================================
| "philwilson.org" | "2006-09-18T09:10:00Z" |
---------------------------------------------

Dans le document SPARQL Query Language for RDF du W3C, les exemples de graphes RDF présentés ne font pas appel à la syntaxe RDF/XML que nous avons vue jusqu’ici. C’est une notation dite Turtle (Terse RDF Triple Language), équivalente.

@prefix dc:   <http://purl.org/dc/elements/1.1/> .
@prefix :     <http://example.org/book/> .
@prefix ns:   <http://example.org/ns#> .

:book1  dc:title  "SPARQL Tutorial" .
:book1  ns:price  42 .
:book2  dc:title  "The Semantic Web" .
:book2  ns:price  23 .

En grammaire Turtle dans l’exemple montré : book1 identifie un noeud, dc:title un prédicat et "The Semantic Web" un objet. ARQ comprend cette notation, ainsi en notant ex1.ttl cet exemple et ex2.rq ce code SPARQL.

PREFIX  dc:  <http://purl.org/dc/elements/1.1/>
PREFIX  ns:  <http://example.org/ns#>

SELECT  ?title ?price
FROM <ex1.ttl>
WHERE   { ?x dc:title ?title .
         OPTIONAL { ?x ns:price ?price . FILTER (?price < 30) }

       }

La commande :

#sparql --query ex2.rq produit le résultat: ------------------------------
| title              | price |
==============================
| "The Semantic Web" | 23    |
| "SPARQL Tutorial"  |       |
------------------------------

Le graphe référencé par la directive FROM est le graphe défaut. On peut nommer un graphe via la clause FROM NAMED et travailler avec des collections de graphes. Soit les trois graphesLa commande :

# Default graph (stored at dft.ttl)
@prefix dc: <http://purl.org/dc/elements/1.1/> .

<bob.ttl>    dc:publisher  "Bob Hacker" .
<alice.ttl>  dc:publisher  "Alice Hacker" .

# Named graph: bob.ttl
@prefix foaf: <http://xmlns.com/foaf/0.1/> .

_:a foaf:name "Bob" .
_:a foaf:mbox <mailto:bob@oldcorp.example.org> .

# Named graph: alice.ttl
@prefix foaf: <http://xmlns.com/foaf/0.1/> .

_:a foaf:name "Alice" .
_:a foaf:mbox <mailto:alice@work.example.org> .

et la requête ex3.rq :

PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX dc: <http://purl.org/dc/elements/1.1/>

SELECT ?who ?g ?mbox
FROM <dft.ttl>
FROM NAMED <alice.ttl>
FROM NAMED <bob.ttl>
WHERE
{
  ?g dc:publisher ?who .
  GRAPH ?g { ?x foaf:mbox ?mbox }
}

la commande : sparql —query ex3.rq donne comme résultat :

--------------------------------------------------------------------------------
| who            | g                                                 | mbox    |
================================================================================
| "Alice Hacker" | <file:///xxxx/alice.ttl> | <mailto:alice@work.example.org>  |
| "Bob Hacker"   | <file:///xxxx/bob.ttl>   | <mailto:bob@oldcorp.example.org> |
--------------------------------------------------------------------------------

Le pattern  ?g dc:publisher ?who est résolu dans le graphe défaut, tandis que celui  ?x foaf:mbox ?mbox l’est dans les graphes alice.ttl et bob.ttl introduits par le mot-clé GRAPH. Un exemple concret : voici mon profil FOAF et à titre d’exemple j’ai indiqué une connaissance mortenf.

<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:foaf="http://xmlns.com/foaf/0.1/"
xmlns:admin="http://webns.net/mvcb/">
<foaf:Person rdf:ID="me">
<foaf:name>Francis Lapique</foaf:name>
<foaf:title>M.</foaf:title>
<foaf:givenname>Francis</foaf:givenname>
<foaf:family_name>Lapique</foaf:family_name>
<foaf:mbox_sha1sum>266cb9fe0141fbad7c000bd53e89923926722a22</foaf:mbox_sha1sum>
<foaf:homepage rdf:resource="http://www.epfl.ch"/>
<foaf:workplaceHomepage rdf:resource="http://www.epfl.ch"/>
<foaf:knows>
<foaf:Person>
<foaf:name>mortenf</foaf:name>
<foaf:mbox_sha1sum>7ed2aeef52364e17ae9613bb477dc2bf0fe06a02</foaf:mbox_sha1sum></foaf:Person>
</foaf:knows>
</foaf:Person>
</rdf:RDF>

Je veux un service qui m’indique les 10 derniers articles de mes connaissances. Sur la base de l’exemple précédent, la requête est la suivante.

PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX rss:  <http://purl.org/rss/1.0/>
PREFIX dc:   <http://purl.org/dc/elements/1.1/>

SELECT ?title ?known_name ?link

FROM <http://www.wasab.dk/morten/index.rdf>
FROM NAMED <profil.rdf>

WHERE {
       GRAPH <profil.rdf> {
         ?me foaf:name "Francis Lapique" .
         ?me foaf:knows ?known_person .
         ?known_person foaf:name ?known_name .
       } .
         
       ?item dc:creator ?known_name .
       ?item rss:title ?title .
       ?item rss:link ?link .
       ?item dc:date ?date.
       
     }

ORDER BY DESC(?date) LIMIT 10


---------------------------------------------------------------------------------------------
| title                                                                 | known_name | link                                                                                             |
================================================================================================================================ =============================================================================================
| "digg.dk"                                                             | "mortenf"  | "http://digg.dk/"                                                                                             |
| "Web 2.0 Colour Palette"                                              | "mortenf"  | "http://www.modernlifeisrubbish.co.uk/web -2.0-colour-palette.asp"                                                                    |
| "OSX Keyboard Shortcuts"                                              | "mortenf"  | "http://developer.apple.com/documentation /UserExperience/Conceptual/OSXHIGuidelines/XHIGKeyboardShortcuts/chapter_20_section_1.html" |
| "Top 10 Best Wordpress Plugins"                                       | "mortenf"  | "http://www.johnchow.com/index.php/my-top -10-best-wordpress-plugins/"                                                                |
| "Top 10 over udsagn der har ført til eksklusion fra Dansk Folkeparti" | "mortenf"  | "http://www.baldersf.dk/2006/10/10/top-10 -over-udsagn-der-har-f%C3%B8rt-til-eksklusion-fra-dansk-folkeparti/"                        |
| "Apple Gazette"                                                       | "mortenf"  | "http://www.applegazette.com/"                                                                                             |

En première partie, on va rechercher mes connaissances dans le graphe profil.rdf et en deuxième les dernières contributions de mes connaissances dans le dataset. En précisant à sparql que l’on veut un résultat sous la forme XML il est aisé de construire une application AJAX. On trouve sur le web des applications qui vont dans ce sens, en visualisant l’activité de grandes communautés virtuelles. Vous pouvez remarquer que dans le profil de "Peter Parker" vous trouvez une référence à sa localisation, je vous laisse imaginer les potentiels d’application en intégrant l’API Google Maps et les problèmes éthiques et de sécurité que cela va poser.
Il est possible d’avoir un filtre sur des tag. Par exemple considérer le graphe suivant ou les deux objets "Robert" et "Roberto" ont respectivement les tags EN et ES.

@prefix foaf:    <http://xmlns.com/foaf/0.1/> .
_:a  foaf:name     "Robert"@EN.
_:a  foaf:name     "Roberto"@ES.
_:a  foaf:mbox     <mailto:bob@work.example> .

Pour trouver les références à l’espagnol, on passe la requête suivante :

PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name ?mbox
WHERE { ?x foaf:name  ?name ;
           foaf:mbox  ?mbox .
        FILTER ( lang(?name) = "ES" ) }

#sparql --query lang.rq  --graph lang.ttl.

--------------------------------------------
| name         | mbox                      |
============================================
| "Roberto"@ES | <mailto:bob@work.example> |
--------------------------------------------

SPARQL propose d’autres formes d’interrogation que SELECT, il en existe trois autres ASK, DESCRIBE et CONSTRUCT. ASK va répondre par OUI ou NON à une question, exemple :

Étant donné le graphe ask.ttl :

@prefix foaf:     <http://xmlns.com/foaf/0.1/> .
_:a  foaf:name     "Alice" .
_:a  foaf:homepage   <http://work.example.org/alice/> .
_:b  foaf:name     "Bob" .
_:b  foaf:mbox     <mailto:bob@work.example> .

et la requête ask.rq

PREFIX foaf:    <http://xmlns.com/foaf/0.1/>
ASK  { ?x foaf:name  "Alice" }

la commande :

sparql --query ask.rq  --graph ask.ttl

donne comme réponse :

Ask => Yes

CONSTRUCT permet de construire un graphe. Sur la base du graphe

@prefix  foaf:  <http://xmlns.com/foaf/0.1/> .
_:a    foaf:name   "Alice" .
_:a    foaf:mbox   <mailto:alice@example.org> .

et de la demande :

PREFIX foaf:    <http://xmlns.com/foaf/0.1/>
PREFIX vcard:   <http://www.w3.org/2001/vcard-rdf/3.0#>
CONSTRUCT   { <http://example.org/person#Alice> vcard:FN ?name }
WHERE       { ?x foaf:name ?name }

on construit la propriété vcard

@prefix vcard: <http://www.w3.org/2001/vcard-rdf/3.0#> .
<http://example.org/person#Alice> vcard:FN "Alice" .

DESCRIBE permet d’obtenir des informations détaillées, par exemple la requête suivante :

PREFIX ent:  <http://org.example.com/employees#>
DESCRIBE ?x WHERE { ?x ent:employeeId "1234" }

vous propose comme résultat :

@prefix foaf:   <http://xmlns.com/foaf/0.1/> .
@prefix vcard:  <http://www.w3.org/2001/vcard-rdf/3.0> .
@prefix exOrg:  <http://org.example.com/employees#> .
@prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix owl:    <http://www.w3.org/2002/07/owl#>

_:a     exOrg:employeeId    "1234" ;
 
       foaf:mbox_sha1sum   "ABCD1234" ;
       vcard:N
        [ vcard:Family       "Smith" ;
          vcard:Given        "John"  ] .

foaf:mbox_sha1sum  rdf:type  owl:InverseFunctionalProperty .

SPARQL et AJAX

Le document SPARQL Protocol for RDF édité par Kendall Clark, propose un protocole pour transmettre et renvoyer des résultats pour un service de traitement de requêtes SPARQL.
Joseki est une application web qui prend en compte protocole et langage SPARQL. Le Quick start d’installation de Joseki est des plus simple :

  • Set the JOSEKIROOT environment variable to the location of the installation.
  • Run the script rdfserver (bin/ or bat/). This will run an HTTP server on port 2020.
  • Go to http://localhost:2020/query.html.

    Si vous ne demandez pas une transformation XSLT vous avez directement les résultats sous la forme d’un fichier XML :
<?xml version="1.0"?>
<sparql
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:xs="http://www.w3.org/2001/XMLSchema#"
   xmlns="http://www.w3.org/2005/sparql-results#">
 <head>
   <variable name="item_title"/>
   <variable name="pub_date"/>
 </head>
 <results ordered="false" distinct="false">
   <result>
     <binding name="item_title">
       <literal>philwilson.org</literal>
     </binding>
     <binding name="pub_date">
       <literal>2006-09-18T09:10:00Z</literal>
     </binding>
   </result>
 </results>
</sparql>

L’intégration dans une application AJAX est alors évidente. Une indication tout de même. On ne peut pas, pour des raisons de sécurité, passer la requête http://localhost:2020/sparql?query... comme telle , il faut passer par l’intermédiaire d’un proxy.

try
  {
     this.request.open(‘GET', ‘http://localhost/sparql/sparql?query...', true);
     this.request.send(null);
  } catch (e)

Conclusion

En guise de conclusion quelques lectures : un billet sur une extension de MediaWiki Semantic MediaWiki (SMW)
« J’avoue que j’ai été bluffé par cette application appelée Semantic Mediawiki et qui constitue une extension au logiciel Mediawiki. À la lecture du résumé de l’article, je m’attendais à un simple export des données d’un site utilisant Mediawiki (exemple au hasard : wikipedia !) vers RDF. Cela aurait été une première étape déjà intéressante, nous permettant de récupérer les liens sémantiques existants non typés entre les différentes définitions de la Wikipedia et ainsi de disposer d’un thésaurus dont j’ai rappelé il y a peu l’intérêt de la publication en RDF sur le Web. D’ailleurs, une société proposait depuis plusieurs mois un export mensuel des données de la Wikipedia anglophone et je me demandais ce que ce projet pouvait donner de plus.
En lieu et place du résumé, c’est le texte complet de la communication que j’aurais dû lire ce qui m’aurait renseigné sur la nature réelle des ambitions des développeurs. En réalité, grâce à ce logiciel, on voit les prémices de la réponse à la question systématique
 : comment les utilisateurs pourront-ils ajouter des renseignements sémantiques ? Avec un minimum d’organisation ? en utilisant RDF, sa complexité et sa syntaxe barbare ? Et surtout facilement ? Réponse élémentaire, mes chers lecteurs : avec la syntaxe wiki. À ce stade de ce billet, vous allez me rétorquer que c’est évident, d’accord et alors ?
Avant d’aller plus loin, je vous conseille la lecture du précédent billet si le concept de RDF n’est pas complètement clair pour vous... ».

Un autre lien intéressant traitant la question SQL, XQuery, and SPARQL : What’s Wrong With This Picture ?, un projet Tabulator.
Le prochain et dernier article consacré aux technologies du WS aura comme sujet les moteurs d’inférence.

[1] Spécifications du vocabulaire FOAF (mai 2004) http://xmlns.com/foaf/0.1/, voir également http://www.foaf-project.org, http://rdfweb.org, http://rdfweb.org/topic/FAQ



Cherchez ...

- dans tous les Flash informatique
(entre 1986 et 2001: seulement sur les titres et auteurs)
- par mot-clé

Avertissement

Cette page est un article d'une publication de l'EPFL.
Le contenu et certains liens ne sont peut-être plus d'actualité.

Responsabilité

Les articles n'engagent que leurs auteurs, sauf ceux qui concernent de façon évidente des prestations officielles (sous la responsabilité du DIT ou d'autres entités). Toute reproduction, même partielle, n'est autorisée qu'avec l'accord de la rédaction et des auteurs.


Archives sur clé USB

Le Flash informatique ne paraîtra plus. Le dernier numéro est daté de décembre 2013.

Taguage des articles

Depuis 2010, pour aider le lecteur, les articles sont taggués:
  •   tout public
    que vous soyiez utilisateur occasionnel du PC familial, ou bien simplement propriétaire d'un iPhone, lisez l'article marqué tout public, vous y apprendrez plein de choses qui vous permettront de mieux appréhender ces technologies qui envahissent votre quotidien
  •   public averti
    l'article parle de concepts techniques, mais à la portée de toute personne intéressée par les dessous des nouvelles technologies
  •   expert
    le sujet abordé n'intéresse que peu de lecteurs, mais ceux-là seront ravis d'approfondir un thème, d'en savoir plus sur un nouveau langage.