SPARQL Protocol and RDF Query Language/Requêtes d'exportation

Début de la boite de navigation du chapitre

Dans le chapitre « le protocole SPARQL », nous avons vu que l’on pouvait obtenir différents formats en sortie en fonction des paramètres de la requête HTTP et du type de requête SPARQL.

Requêtes d'exportation
Icône de la faculté
Chapitre no 8
Leçon : SPARQL Protocol and RDF Query Language
Chap. préc. :Requêtes de découverte
Chap. suiv. :Système d'implication
fin de la boite de navigation du chapitre
En raison de limitations techniques, la typographie souhaitable du titre, « SPARQL : Requêtes d'exportation
SPARQL Protocol and RDF Query Language/Requêtes d'exportation
 », n'a pu être restituée correctement ci-dessus.

Nous allons revenir sur chacun de ces formats en sortie et nous arrêter sur le format JSON avec le langage Javascript.

Exporter des données

modifier

Avec une requête SELECT

modifier

La réponse d'une requête SELECT est un "SPARQL result" (tableau de résultat) qui peut prendre le format :

  • XML
  • JSON qu'on utilisera un peu plus loin avec Javascript
  • texte avec tabulation ou HTML, etc. (pour l'afficher dans le navigateur, c’est en fonction de votre triplestore)

Pour être certain du format en sortie, il faut utiliser le paramètre output dans la requête HTTP.

Par exemple, voici la requête GET HTTP pour obtenir le format XML :

http://dbpedia.org/sparql/?output=xml&query=SELECT ?siteweb WHERE { <http://dbpedia.org/resource/Star_Trek> <http://xmlns.com/foaf/0.1/homepage> ?siteweb }

Résultat en XML :

<sparql xmlns="http://www.w3.org/2005/sparql-results#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.w3.org/2001/sw/DataAccess/rf1/result2.xsd">
 <head>
  <variable name="siteweb"/>
 </head>
 <results distinct="false" ordered="true">
  <result>
   <binding name="siteweb"><uri>http://www.startrek.com</uri></binding>
  </result>
 </results>
</sparql>

Par exemple, voici la requête GET HTTP pour obtenir le format JSON :

http://dbpedia.org/sparql/?output=json&query=SELECT ?siteweb WHERE { <http://dbpedia.org/resource/Star_Trek> <http://xmlns.com/foaf/0.1/homepage> ?siteweb }

Résultat au format JSON :

{ "head": { "link": [], 
            "vars": ["siteweb"] 
          },
  "results": { "distinct": false, 
               "ordered": true, 
               "bindings": [
                             { "siteweb": { "type": "uri", 
                                            "value": "http://www.startrek.com" 
                                          }
                             } 
                           ] 
             } 
}

Par exemple, voici la requête GET HTTP pour obtenir le format JSONP :

http://dbpedia.org/sparql/?output=json&callback=ma_fonction&query=SELECT ?siteweb WHERE { <http://dbpedia.org/resource/Star_Trek> <http://xmlns.com/foaf/0.1/homepage> ?siteweb }

Résultat au format JSONP :

ma_fonction(

{ "head": { "link": [], 
            "vars": ["siteweb"] 
          },
  "results": { "distinct": false, 
               "ordered": true, 
               "bindings": [
                             { "siteweb": { "type": "uri", 
                                            "value": "http://www.startrek.com" 
                                          }
                             } 
                           ] 
             } 
})

Par exemple, voici la requête GET HTTP pour obtenir le format HTML avec Dbpedia :

http://dbpedia.org/sparql/?output=html&query=SELECT ?siteweb WHERE { <http://dbpedia.org/resource/Star_Trek> <http://xmlns.com/foaf/0.1/homepage> ?siteweb }

Résultat en HTML:

<table class="sparql" border="1">
  <tr>
    <th>siteweb</th>
  </tr>
  <tr>
    <td>http://www.startrek.com</td>
  </tr>
</table>

Par exemple, voici la requête GET HTTP pour obtenir le format RDF avec Dbpedia :

http://dbpedia.org/sparql/?output=RDF&query=SELECT ?siteweb WHERE { <http://dbpedia.org/resource/Star_Trek> <http://xmlns.com/foaf/0.1/homepage> ?siteweb }

Résultat en HTML:

<rdf:RDF xmlns:res="http://www.w3.org/2005/sparql-results#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:nodeID="rset">
<rdf:type rdf:resource="http://www.w3.org/2005/sparql-results#ResultSet" />
    <res:resultVariable>siteweb</res:resultVariable>
    <res:solution rdf:nodeID="r0">
      <res:binding rdf:nodeID="r0c0"><res:variable>siteweb</res:variable><res:value rdf:resource="http://www.startrek.com"/></res:binding>
    </res:solution>
  </rdf:Description>
</rdf:RDF>

N3 (Notation3)

modifier

N3 (Notation3) ressemble au format Turtle. DBPedia peut répondre en Notation3 avec, par exemple, cette requête :

http://dbpedia.org/sparql/?output=N3&query=SELECT ?siteweb WHERE { <http://dbpedia.org/resource/Star_Trek> <http://xmlns.com/foaf/0.1/homepage> ?siteweb }

Résultat en N3:

@prefix res: <http://www.w3.org/2005/sparql-results#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
_:_ a res:ResultSet .
_:_ res:resultVariable "siteweb" .
_:_ res:solution [
      res:binding [ res:variable "siteweb" ; res:value <http://www.startrek.com> ] ] .

Les autres formats

modifier

N'hésitez pas à lire attentivement la documentation de votre base de données pour connaître les valeurs autorisées pour le paramètre output d'une requête HTTP.

Avec une requête CONSTRUCT

modifier

Une requête CONSTRUCT retourne un graphe RDF/XML. Le graphe obtenu est construit en fonction du patron qui est indiqué dans la clause CONSTRUCT.

Prenons par exemple la requête : Les écoles de Birmingham laïques pour les élèves de 15 ans avec moins de 300 élèves.

On veut importer les résultats dans un autre triplestore. Ce triplestore peut prendre en entrée un fichier RDF/XML (format de sauvegarde et d'importation massive). Sans savoir fabriquer un document RDF/XML, je fabrique la requête SPARQL où je remplace la définition SELECT par une définition CONSTRUCT où j'indique la structure des données que je veux obtenir.

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX sch-ont: <http://education.data.gov.uk/def/school/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX geo:<http://www.w3.org/2003/01/geo/wgs84_pos#>
CONSTRUCT { 
<http://solution/1> <http://solution/goodschool> ?school.
?school a sch-ont:School;
sch-ont:establishmentName ?name;
sch-ont:websiteAddress ?web  .   
}
WHERE {
?school a sch-ont:School;
sch-ont:establishmentName ?name;
sch-ont:schoolCapacity ?capacity ;
sch-ont:religiousCharacter sch-ont:ReligiousCharacter_Does_not_apply ;
sch-ont:statutoryHighAge ?ageMax ;
sch-ont:statutoryLowAge ?ageMin ;
geo:long ?long;
geo:lat ?lat;
sch-ont:districtAdministrative ?da .        
?da rdfs:label "Birmingham".
OPTIONAL {?school sch-ont:websiteAddress ?web .}
OPTIONAL {
		?school sch-ont:address ?address.
		?address sch-ont:address1 ?address1;
		sch-ont:postcode ?postcode;
		sch-ont:town ?town.
		OPTIONAL {?address sch-ont:address2 ?address2. }
	}
FILTER (?capacity < 300 && ?ageMax >= 15 && ?ageMin <= 15 )
}
ORDER BY DESC(?capacity)
LIMIT 2

Cela donnera la solution en RDF/XML :

<?xml version="1.0"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about="http://solution/1">
<p:goodschool xmlns:p="http://solution/" rdf:resource="http://education.data.gov.uk/id/school/134908" />
</rdf:Description>
<rdf:Description rdf:about="http://education.data.gov.uk/id/school/134908">
<p:type xmlns:p="http://www.w3.org/1999/02/22-rdf-syntax-ns#" rdf:resource="http://education.data.gov.uk/def/school/School" />
</rdf:Description>
<rdf:Description rdf:about="http://education.data.gov.uk/id/school/134908">
<p:establishmentName xmlns:p="http://education.data.gov.uk/def/school/">Elmhurst School for Dance In Association With Birmingham Royal Ballet</p:establishmentName>
</rdf:Description>
<rdf:Description rdf:about="http://solution/1">
<p:goodschool xmlns:p="http://solution/" rdf:resource="http://education.data.gov.uk/id/school/135378" />
</rdf:Description>
<rdf:Description rdf:about="http://education.data.gov.uk/id/school/135378">
<p:type xmlns:p="http://www.w3.org/1999/02/22-rdf-syntax-ns#" rdf:resource="http://education.data.gov.uk/def/school/School" />
</rdf:Description>
<rdf:Description rdf:about="http://education.data.gov.uk/id/school/135378">
<p:establishmentName xmlns:p="http://education.data.gov.uk/def/school/">Sz School</p:establishmentName>
</rdf:Description>
</rdf:RDF>

Comme pour une requête SELECT, CONSTRUCT retourne un graphe RDF en XML, ou bien en Turtle, ou en N3, etc. C'est en fonction du paramètre output (dans une requête HTTP POST ou GET). Attention, le format de sortie est en fonction du triplestore utilisé, mais le format RDF/XML est celui indiqué dans la recommandation.

Avec une requête DESCRIBE

modifier

Une requête DESCRIBE retourne un document en Turtle ou un document RDF en XML. Pour obtenir un format comme Turtle, il faut le préciser avec le paramètre output.

Par exemple, voici la requête GET HTTP pour obtenir le détail d'une référence dans le silo Data.gov.uk Education : http://gov.tso.co.uk/education/sparql/?output=turtle&query=DESCRIBE <http://education.data.gov.uk/id/school/134908>

Résultat en Turtle:

<http://education.data.gov.uk/id/school/134908> <http://education.data.gov.uk/def/school/dateofLastISIVisit> "2008-10-16"^^<http://www.w3.org/2001/XMLSchema#date> .
<http://education.data.gov.uk/id/school/134908> <http://education.data.gov.uk/def/school/compSchoolAge> "139"^^<http://www.w3.org/2001/XMLSchema#int> .
...

Cette requête est utile si on veut exporter par exemple les prédicats et les valeurs associées à une référence précise.

Exporter dans votre programme Javascript

modifier

Parmi les formats d'exportation, il en existe un qui est de plus en plus utilisé : le JSON.

La raison de cet engouement est que le format JSON peut être chargé en mémoire dans du Javascript sans avoir besoin de transformer la réponse SPARQL en XML avec les méthodes SAX ou DOM.

Par exemple, si la variable doc contient une réponse SPARQL en JSON, en utilisant la ligne suivante, on obtiendra un objet :

obj = eval('(' + req.responseJSON + ')');

Nous l’utiliserons ensuite de cette manière, par exemple, pour en faire un tableau HTML :

table = '<table>';
table += '<tr>';
//print variables
for(var var in obj.head.vars)
{
    table += '<th>';
    table += obj.head.vars[var];
    table += '</th>';
}
table += '</tr>';
//print results 
for(var index in obj.results.bindings)
{
    table += '<tr>';
    for(var var in obj.results.bindings[index])
    {
        table += '<td>';
        table += obj.results.bindings[index][var].value ;
        table += '</td>';	
    }
    table += '</tr>';
}	 
table += '</table>';

Voici l'exemple d'une fonction javascript pour faire une requête SPARQL :

function download_datasets(endpoint,query){	
	//send request
	var req = new XMLHttpRequest();
	req.open("GET", endpoint + '/?output=json&query=' + escape(query.replace('\\n','')),true); 
	req.onreadystatechange = function (aEvt) {
		  if (req.readyState == 4) {
			     if(req.status == 200 || req.status == 0){
					if (req.responseText == "") 
					   { 
						messageWaiting = "Error : The domain in the query is different of Web site...";
						return;
					   }
					OBJECT_VarGlobal = eval('(' + req.responseText + ')'); 
				        div.innerHTML =  makeTable(doc_datasets);
			      }else
			    	 messageWaiting = "Error loading response";
                   }
	   }; 
	req.send(null); 
}

Vous voici, après 8 chapitres, équipé pour utiliser SPARQL en long, en large et en travers ! Le prochain chapitre abordera les futures étapes de l'implémentation de SPARQL, qui s'adresse donc à un public très motivé ;)