Veuillez consulter la page des errata de ce document, laquelle peut contenir des corrections normatives.
Cf. aussi d'éventuelles traductions.
Copyright © 2006-2007 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C liability, trademark and document use rules apply.
RDF est un format de données de graphe orienté et étiqueté pour représenter des informations dans le Web. Cette spécification définit la syntaxe et la sémantique du langage d'interrogation SPARQL pour RDF. SPARQL peut être utilisé pour exprimer des interrogations à travers diverses sources de données, que les données soient stockées nativement comme RDF ou vues comme du RDF via un logiciel médiateur (middleware). SPARQL est capable de rechercher des motifs de graphe (graph patterns) obligatoires et optionnels ainsi que leurs conjonctions et leurs disjonctions. SPARQL gère également le test extensible des valeurs et la contrainte des interrogations par un graphe RDF source. Les résultats des interrogations SPARQL peuvent être des ensembles de résultats ou des graphes RDF.
Cette section décrit le statut de ce document au moment de sa publication. D'autres documents peuvent venir le remplacer. On peut trouver une liste des publications actuelles du W3C et la dernière version de ce rapport technique dans l'index des rapports techniques du W3C à http://www.w3.org/TR/.
Ceci est une recommandation du W3C.
Ce document a été examiné par des membres du W3C, par des développeurs de logiciels, et par d'autres groupes du W3C et des tiers intéressés, et a été approuvé par le Directeur comme recommandation du W3C. C'est un document stable qui peut être utilisé comme document de référence ou cité par un autre document. Le rôle du W3C en produisant la recommandation est d'attirer l'attention sur la spécification et d'en promouvoir le large déploiement. Cela participe à la fonctionnalité et à l'interopérabilité du Web.
Les commentaires à propos de ce document sont à envoyer à public-rdf-dawg-comments@w3.org, une liste de diffusion avec des archives publiques. Les questions et commentaires à propos de SPARQL non liés à cette spécification, y compris les extensions et les caractéristiques, peuvent être débattus sur la liste de diffusion public-sparql-dev@w3.org (archives publiques).
Ce document a été produit par le groupe de travail RDF Data Access, sous l'égide de l'activité Semantic Web du W3C. La première publication de ce document en tant que version préliminaire a eu lieu le 12 octobre 2004, et le groupe de travail a traité beaucoup de commentaires reçus et de problèmes depuis. Il y a eu deux changements répertoriés depuis la recommandation proposée de novembre 2007.
Le rapport de mise en œuvre du langage d'interrogation SPARQL pour RDF du groupe de travail démontre que les objectifs de mises en œuvre interopérables fixés dans la recommandation candidate d'avril 2006 ont été atteints.
Le groupe de travail Data Access a ajourné 12 questions, dont les fonctions agrégées et un langage de mise à jour.
Ce document a été produit par un groupe agissant sous couvert de la politique de brevets du W3C du 5 février 2004. Le W3C tient une liste publique des divulgations de brevets effectuées en rapport avec les produits livrables du groupe ; cette page contient également des instructions pour divulguer un brevet. Quiconque a connaissance véritable d'un brevet qu'il estime contenir des revendications essentielles doit divulguer cette information conformément à la section 6 de la politique de brevets du W3C.
RDF est un format de données de graphe orienté et étiqueté pour représenter des informations dans le Web. RDF est souvent utilisé pour représenter, entre autres choses, des informations personnelles, des réseaux sociaux, des métadonnées à propos d'artefacts numériques ainsi que fournir un moyen d'intégrer des sources d'information disparates. Cette spécification définit la syntaxe et la sémantique du langage d'interrogation SPARQL pour RDF.
Le langage d'interrogation SPARQL pour RDF est conçu pour satisfaire aux cas d'utilisation et aux exigences identifiés par le groupe de travail RDF Data Access dans Cas d'utilisation et exigences de l'accès aux données RDF [UCNR].
Le langage d'interrogation SPARQL est étroitement lié aux spécifications suivantes :
Sauf indication contraire dans le titre de la section, toutes les sections et annexes dans ce document sont normatives.
La section 1 du document introduit la spécification du langage d'interrogation SPARQL. Elle présente l'organisation de ce document de spécification et les conventions observées tout au long de la spécification.
La section 2 de la spécification introduit le langage d'interrogation SPARQL soi-même via une série d'exemples d'interrogations et de résultats d'interrogation. La section 3 poursuit l'introduction du langage d'interrogation avec d'autres exemples qui démontrent l'aptitude de SPARQL à exprimer des contraintes sur les termes RDF apparaissant dans les résultats d'interrogation.
La section 4 présente le détail de la syntaxe du langage d'interrogation SPARQL. Elle accompagne la grammaire complète du langage et définit les structures grammaticales représentant les adresses IRI, les nœuds anonymes (blank nodes), les littéraux (literals) et les variables. La section 4 définit également la signification de plusieurs structures grammaticales utilisées comme sucre syntaxique pour des expressions plus verbeuses.
La section 5 introduit les motifs de graphe élémentaires (basic graph patterns) et les motifs de graphe de groupe (group graph patterns), qui sont les éléments d'assemblage à partir desquels sont construits des motifs d'interrogation (query patterns) SPARQL plus complexes. Les sections 6, 7 et 8 présentent les structures combinant les motifs de graphe SPARQL en des motifs de graphe plus grands. En particulier, la section 6 introduit la capacité à rendre optionnels des morceaux d'une interrogation ; la section 7 introduit la capacité à exprimer la disjonction de motifs de graphe alternatifs ; la section 8 introduit la capacité à contraindre des morceaux d'une interrogation à des graphes sources particuliers. La section 8 présente également le mécanisme de SPARQL pour définir les graphes sources d'une interrogation.
La section 9 définit les structures qui affectent les solutions d'une interrogation en triant, découpant, projetant, limitant et supprimant les copies (duplicates) d'une séquence de solutions.
La section 10 définit les quatre types d'interrogation SPARQL produisant des résultats de formes différentes.
La section 11 définit le système de test des valeurs extensibles de SPARQL. Elle présente également les fonctions et opérateurs utilisables pour contraindre les valeurs apparaissant en résultat d'une interrogation.
La section 12 est une définition formelle de l'évaluation des motifs de graphe et des modificateurs de solution (solution modifiers) de SPARQL.
L'annexe A contient la définition normative de la syntaxe du langage d'interrogation SPARQL, selon une grammaire exprimée en notation EBNF.
Dans ce document, les exemples supposent les liaisons de préfixe d'espace de noms suivantes, sauf indication contraire :
| Préfixe | Adresse IRI |
|---|---|
rdf: |
http://www.w3.org/1999/02/22-rdf-syntax-ns# |
rdfs: |
http://www.w3.org/2000/01/rdf-schema# |
xsd: |
http://www.w3.org/2001/XMLSchema# |
fn: |
http://www.w3.org/2005/xpath-functions# |
Ce document emploie le format de données Turtle [TURTLE] pour montrer explicitement chaque triplet. Le format Turtle permet d'abréger les adresses IRI en préfixes :
@prefix dc: <http://purl.org/dc/elements/1.1/> . @prefix : <http://example.org/book/> . :book1 dc:title "SPARQL Tutorial" .
Les ensembles de résultat (result sets) sont illustrés sous une forme tabulaire.
| x | y | z |
|---|---|---|
| "Alice" | <http://example/a> |
Une « liaison » (binding) est un couple de la forme
(variable, terme RDF).
Dans cet ensemble de résultats, il y a trois variables : x, y et z (données en rubriques de colonne).
Chaque solution apparaît comme une seule rangée dans le corps du tableau. Ici il y a une seule solution, où la
variable x est liée à "Alice", la variable y est liée à <http://example/a>
et la variable z n'est pas liée à un terme RDF. Les variables ne sont pas nécessairement liées
dans une solution.
Le langage SPARQL inclut des adresses IRI, un sous-ensemble des références IRI de RDF qui omet les espaces. Notez que toutes les adresses IRI dans les interrogations SPARQL sont absolues ; elles peuvent ou non contenir un identificateur de fragment [RFC3987, section 3.1]. Les adresses IRI incluent les adresses URI [RFC3986] et les adresses URL. Les formes abrégées (adresses IRI relatives et noms préfixés) dans la syntaxe SPARQL se résolvent en adresses IRI absolues.
Les termes suivants, définis dans Concepts et syntaxe abstraite RDF [CONCEPTS], sont employés dans SPARQL :
La plupart des formes d'interrogation SPARQL contiennent un ensemble de motifs de triplet (triple patterns) appelé un motif de graphe élémentaire (basic graph pattern). Les motifs de triplet sont comme les triplets RDF sauf que chaque sujet, prédicat et objet peut être une variable. Un motif de graphe élémentaire correspond à un sous-graphe des données RDF lorsque les termes RDF (RDF terms) de ce sous-graphe peuvent être substitués par les variables et que le résultat est un graphe RDF équivalent au sous-graphe.
L'exemple ci-dessous montre une interrogation SPARQL pour trouver le titre d'un livre dans le graphe de données fourni.
L'interrogation comprend deux parties : la clause SELECT identifie les variables qui doivent apparaître dans les
résultats d'interrogation (query results), et la clause WHERE fournit le motif de graphe élémentaire
auquel comparer (match against) le graphe de données. Le motif de graphe élémentaire dans cet exemple
se compose d'un seul motif de triplet avec une seule variable (?title) en position d'objet.
Données :
<http://example.org/book/book1> <http://purl.org/dc/elements/1.1/title> "SPARQL Tutorial" .
Interrogation :
SELECT ?title
WHERE
{
<http://example.org/book/book1> <http://purl.org/dc/elements/1.1/title> ?title .
}
Cette interrogation effectuée sur les données ci-dessus a une seule solution :
Résultat d'interrogation :
| title |
|---|
| "SPARQL Tutorial" |
Le résultat d'une interrogation est une séquence de solutions, correspondant aux façons dont le motif de graphe de l'interrogation filtre les données. Il peut y avoir zéro, une ou plusieurs solutions à une interrogation.
Données :
@prefix foaf: <http://xmlns.com/foaf/0.1/> . _:a foaf:name "Johnny Lee Outlaw" . _:a foaf:mbox <mailto:jlow@example.com> . _:b foaf:name "Peter Goodguy" . _:b foaf:mbox <mailto:peter@example.org> . _:c foaf:mbox <mailto:carol@example.org> .
Interrogation :
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name ?mbox
WHERE
{ ?x foaf:name ?name .
?x foaf:mbox ?mbox }
Résultat d'interrogation :
| name | mbox |
|---|---|
| "Johnny Lee Outlaw" | <mailto:jlow@example.com> |
| "Peter Goodguy" | <mailto:peter@example.org> |
Chaque solution représente une façon de lier les variables sélectionnées aux termes RDF pour que le motif d'interrogation corresponde aux données. L'ensemble de résultats donne toutes les solutions possibles. Dans l'exemple ci-dessus, les deux correspondances ont été fournies par les deux sous-ensembles de données suivants :
_:a foaf:name "Johnny Lee Outlaw" . _:a foaf:box <mailto:jlow@example.com> .
_:b foaf:name "Peter Goodguy" . _:b foaf:box <mailto:peter@example.org> .
Il s'agit d'un filtrage de motif de graphe élémentaire ; toutes les variables utilisées dans le motif d'interrogation doivent être liées dans toutes les solutions.
Les données suivantes contiennent trois littéraux RDF :
@prefix dt: <http://example.org/datatype#> .
@prefix ns: <http://example.org/ns#> .
@prefix : <http://example.org/ns#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
:x ns:p "cat"@en .
:y ns:p "42"^^xsd:integer .
:z ns:p "abc"^^dt:specialDatatype .
En Turtle, notez que "cat"@en est un littéral RDF avec une forme lexicale "cat" et une langue en ;
"42"^^xsd:integer est un littéral typé ayant le type de données http://www.w3.org/2001/XMLSchema#integer ;
et "abc"^^dt:specialDatatype est un littéral typé ayant le type de données http://example.org/datatype#specialDatatype.
Ces données RDF constituent le graphe de données pour les exemples d'interrogations aux sections 2.3.1 à 2.3.3.
Dans SPARQL, les étiquettes de langue s'expriment en utilisant le caractère @ et l'étiquette de langue,
comme définie dans les Pratiques exemplaires 47 [BCP47].
L'interrogation suivante n'a aucune solution parce que "cat" n'est pas le même littéral que "cat"@en :
SELECT ?v WHERE { ?v ?p "cat" }
| v |
|---|
Tandis que l'interrogation suivante produira une solution où la variable v est liée à :x
parce que l'étiquette de langue est indiquée et correspond aux données fournies :
SELECT ?v WHERE { ?v ?p "cat"@en }
| v |
|---|
| <http://example.org/ns#x> |
Dans une interrogation SPARQL, les entiers indiquent un littéral typé RDF
avec le type de données xsd:integer. Par exemple, 42 est une forme abrégée de
"42"^^<http://www.w3.org/2001/XMLSchema#integer>.
Le motif dans l'interrogation suivante a une solution avec la variable v liée à :y.
SELECT ?v WHERE { ?v ?p 42 }
| v |
|---|
| <http://example.org/ns#y> |
La section 4.1.2 définit les formes abrégées SPARQL pour les types xsd:float et
xsd:double.
L'interrogation suivante a une solution avec la variable v liée à :z. Le processeur d'interrogation
(query processor) n'a pas besoin d'avoir une connaissance des valeurs dans l'espace du type de données.
Parce que la forme lexicale et l'adresse IRI de type de données sont toutes deux correspondantes, le littéral correspond.
SELECT ?v WHERE { ?v ?p "abc"^^<http://example.org/datatype#specialDatatype> }
| v |
|---|
| <http://example.org/ns#z> |
Les résultats d'interrogation peuvent contenir des nœuds anonymes (blank nodes). Les nœuds anonymes dans les exemples d'ensembles de résultats dans ce document s'écrivent sous la forme d'une chaîne "_:" suivie d'une étiquette de nœud anonyme (blank node label).
Les étiquettes de nœud anonyme s'appliquent dans la portée d'un ensemble de résultats (comme défini dans la spécification
Format XML des résultats d'interrogation SPARQL)
ou, pour la forme d'interrogation CONSTRUCT, du graphe résultat. L'utilisation de la même étiquette à l'intérieur d'un
ensemble de résultats indique le même nœud anonyme.
@prefix foaf: <http://xmlns.com/foaf/0.1/> . _:a foaf:name "Alice" . _:b foaf:name "Bob" .
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?x ?name
WHERE { ?x foaf:name ?name }
| x | name |
|---|---|
| _:c | "Alice" |
| _:d | "Bob" |
Les résultats ci-dessus pourraient tout aussi bien être donnés en utilisant des étiquettes de nœud anonyme différentes, car les étiquettes dans les résultats indiquent seulement si les termes RDF dans les solutions sont les mêmes ou sont différents.
| x | name |
|---|---|
| _:r | "Alice" |
| _:s | "Bob" |
Ces deux résultats donnent les mêmes informations : les nœuds anonymes utilisés pour correspondre à l'interrogation sont différents
dans les deux solutions. Il n'est pas nécessaire qu'il y ait une relation entre une étiquette _:a dans l'ensemble de résultats
et un nœud anonyme dans le graphe de données avec la même étiquette.
Un auteur d'applications ne devrait pas supposer que les étiquettes de nœud anonyme dans une interrogation se rapportent à un nœud anonyme particulier dans les données.
SPARQL offre plusieurs formes d'interrogation. La forme d'interrogation SELECT
retourne des liaisons de variables. La forme d'interrogation CONSTRUCT retourne un graphe RDF. Le graphe
est construit d'après un gabarit (template) utilisé pour générer des triplets RDF en fonction
des résultats concordant avec le motif de graphe de l'interrogation.
Données :
@prefix org: <http://example.com/ns#> . _:a org:employeeName "Alice" . _:a org:employeeId 12345 . _:b org:employeeName "Bob" . _:b org:employeeId 67890 .
Interrogation :
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX org: <http://example.com/ns#>
CONSTRUCT { ?x foaf:name ?name }
WHERE { ?x org:employeeName ?name }
Résultat :
@prefix org: <http://example.com/ns#> .
_:x foaf:name "Alice" .
_:y foaf:name "Bob" .
que l'on peut sérialiser en RDF/XML ainsi :
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:foaf="http://xmlns.com/foaf/0.1/"
>
<rdf:Description>
<foaf:name>Alice</foaf:name>
</rdf:Description>
<rdf:Description>
<foaf:name>Bob</foaf:name>
</rdf:Description>
</rdf:RDF>
Le filtrage du motif de graphe produit une séquence de solutions, où chaque solution est constituée par un
ensemble de liaisons de variables à des termes RDF. Les clauses FILTER SPARQL
restreignent les solutions à celles que l'expression de filtre évalue à true.
Cette section est une introduction informelle aux filtres SPARQL ; leurs sémantiques sont définies à la section 11. Test des valeurs. Les exemples de cette section partagent le graphe d'entrée suivant :
@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 .
Les fonctions de filtre (FILTER) SPARQL comme regex peuvent tester les
littéraux RDF. La fonction regex filtre seulement les littéraux ordinaires sans étiquette de langue.
On peut utiliser regex pour filtrer les formes lexicales d'autres littéraux avec la fonction str.
Interrogation :
PREFIX dc: <http://purl.org/dc/elements/1.1/>
SELECT ?title
WHERE { ?x dc:title ?title
FILTER regex(?title, "^SPARQL")
}
Résultat d'interrogation :
| title |
|---|
| "SPARQL Tutorial" |
Le filtrage par les expressions rationnelles (regular expression) peut être indépendant de la casse
en utilisant le drapeau "i".
Interrogation :
PREFIX dc: <http://purl.org/dc/elements/1.1/>
SELECT ?title
WHERE { ?x dc:title ?title
FILTER regex(?title, "web", "i" )
}
Résultat d'interrogation :
| title |
|---|
| "The Semantic Web" |
Le langage d'expression rationnelle est défini par la spécification Fonctions et opérateurs de XQuery 1.0 et XPath 2.0 et repose sur les expressions rationnelles de XML Schema.
Les clauses FILTER SPARQL peuvent restreindre les expressions arithmétiques.
Interrogation :
PREFIX dc: <http://purl.org/dc/elements/1.1/>
PREFIX ns: <http://example.org/ns#>
SELECT ?title ?price
WHERE { ?x ns:price ?price .
FILTER (?price < 30.5)
?x dc:title ?title . }
Résultat d'interrogation :
| title | price |
|---|---|
| "The Semantic Web" | 23 |
En contraignant la variable price, seul :book2 répond à l'interrogation, puisque seul à avoir un
prix inférieur à 30.5, comme l'impose la condition de filtre.
Outre les types numériques, SPARQL intègre les types xsd:string,
xsd:boolean et xsd:dateTime (cf. la section 11.1 Types de données des opérandes).
La section 11.3 Conversion des opérateurs liste un jeu de fonctions de test,
dont BOUND, isLITERAL et langMATCHES, et d'accesseurs (accessors),
dont STR, LANG et DATATYPE. La section
11.5 Fonctions constructrices liste un jeu de fonctions constructrices XML Schema
intégrées au langage SPARQL pour le transtypage (cast) des valeurs.
Cette section couvre la syntaxe utilisée par SPARQL pour les termes RDF et les motifs de triplet. La grammaire complète est donnée à l'annexe A.
La production IRIref désigne l'ensemble des adresses IRI [RFC3987] ; les adresses IRI constituent une généralisation des adresses URI [RFC3986] et sont entièrement compatibles avec les adresses URI et URL. La production PrefixedName désigne un nom préfixé. La correspondance d'un nom préfixé à une adresse IRI est décrite ci-dessous. Les références IRI (des adresses IRI relatives ou absolues) sont désignées par la production IRI_REF, où les caractères délimiteurs « < » et « > » ne font pas partie des références IRI. Les adresses IRI relatives correspondent aux références irelative-ref à la section 2.2 Définition ABNF des références IRI et des adresses IRI dans [RFC3987] et se résolvent en adresses IRI comme décrit ci-dessous.
[67] |
IRIref |
::= | IRI_REF | PrefixedName |
[68] |
PrefixedName |
::= | PNAME_LN | PNAME_NS |
[69] |
BlankNode |
::= | BLANK_NODE_LABEL | ANON |
[70] |
IRI_REF |
::= | '<' ([^<>"{}|^`\]-[#x00-#x20])* '>' |
[71] |
PNAME_NS |
::= | PN_PREFIX? ':' |
[72] |
PNAME_LN |
::= | PNAME_NS PN_LOCAL |
L'ensemble des termes RDF définis dans la spécification Concepts et syntaxe abstraite RDF comprend des références URI RDF tandis que les termes SPARQL contiennent des adresses IRI. Les références URI RDF contenant des caractères « < », « > », « " », ESPACE, « { », « } », « | », « \ », « ^ » et « ` » ne sont pas des adresses IRI. Le comportement d'une interrogation SPARQL contre des déclarations RDF composées de telles références URI RDF n'est pas défini.
Le mot-clé PREFIX associe une étiquette de préfixe à une adresse IRI. Un nom préfixé se compose d'une
étiquette de préfixe et d'une partie locale, séparés par un caractères DEUX-POINTS « : ». Un nom préfixé
est converti (mapped) en une adresse IRI en concaténant l'addresse IRI associée au
préfixe et la partie locale. L'étiquette de préfixe ou la partie locale peuvent être vides. Notez que les
noms locaux SPARQL admettent les chiffres en tête, contrairement aux
noms locaux XML.
Les adresses IRI relatives sont combinées aux adresses IRI de base conformément au RFC Identificateur de ressource uniforme (URI) — Syntaxe générique [RFC3986] en n'utilisant que l'algorithme de base de la section 5.2. Ni la normalisation fondée sur la syntaxe ni la normalisation fondée sur un schéma (décrites aux sections 6.2.2 et 6.2.3 du RFC 3986) ne sont réalisées. Les caractères admis en plus dans les références IRI sont traités de la même façon que le sont les caractères non réservés dans les références URI, selon la section 6.5 du RFC Identificateurs de ressource internationalisés (IRI) [RFC3987].
Le mot-clé BASE définit l'adresse IRI de base utilisée pour résoudre les adresses IRI relatives,
selon la section 5.1.1 Adresse URI de base incorporée au contenu du RFC 3986. La section
5.1.2 Adresse URI de base de l'entité encapsulante définit comment l'adresse IRI de base
peut provenir d'un document encapsulant, tel qu'une enveloppe SOAP avec une directive xml:base,
ou un document MIME de type multipart avec un en-tête Content-Location. L'« adresse URI de récupération »
(Retrieval URI), identifiée à la section 5.1.3 Adresse URI de base de l'adresse URI de récupération,
est l'adresse URL depuis laquelle une interrogation SPARQL particulière est récupérée. Si aucune des méthodes
précédentes ne définit l'adresse URI de base, c'est l'adresse URI de base par défaut (cf. la section
5.1.4 Adresse URI de base par défaut) qui est utilisée.
Les fragments suivants représentent quelques unes des différentes façons d'écrire la même adresse IRI :
<http://example.org/book/book1>
BASE <http://example.org/book/> <book1>
PREFIX book: <http://example.org/book/> book:book1
La syntaxe générale des littéraux est une chaîne (entre des guillemets doubles, "...", ou bien simples, '...'),
avec soit une étiquette de langue optionnelle (introduite par un caractère « @ »), soit une adresse IRI de type de données
ou un nom préfixé optionnels (introduits par ^^).
Par commodité, les entiers peuvent être écrits directement (sans guillemets ni adresse IRI de type de données explicite)
et sont interprétés comme des littéraux typés de type xsd:integer ; les nombres décimaux dans lesquels il y a un
caractère « . » mais pas d'exposant sont interprétés comme des type xsd:decimal ; les nombres avec des exposants
sont interprétés comme des types xsd:double. Les valeurs de type xsd:boolean peuvent aussi s'écrire
true ou false.
Pour faciliter l'écriture des valeurs littérales contenant elles-mêmes des guillemets, ou longues et comprenant des caractères CHANGEMENT DE LIGNE, SPARQL fournit une structure de citation supplémentaire dans laquelle les littéraux sont englobés par des guillemets doubles ou simples triples.
Voici des exemples de syntaxe littérale dans SPARQL :
"chat"'chat'@fr avec l'étiquette de langue "fr""xyz"^^<http://example.org/ns/userDatatype>"abc"^^appNS:appDataType'''The librarian said, "Perhaps you would enjoy 'War and Peace'."'''1, pareil à "1"^^xsd:integer1.3, pareil à "1.3"^^xsd:decimal1.300, pareil à "1.300"^^xsd:decimal1.0e6, pareil à "1.0e6"^^xsd:doubletrue, pareil à "true"^^xsd:booleanfalse, pareil à "false"^^xsd:booleanLes atomes (tokens) correspondant aux productions INTEGER,
DECIMAL, DOUBLE et BooleanLiteral
équivalent à un littéral typé avec la valeur lexicale de l'atome et le type de données associé
(xsd:integer, xsd:decimal, xsd:double, xsd:boolean).
Les variables d'interrogation (query variables) dans les interrogations SPARQL ont une
portée globale (global scope) ; l'utilisation d'un nom de variable donné partout dans une interrogation
identifie la même variable. Les variables sont préfixées soit par un caractère « ? », soit par un caractère « $ » ; les caractères
« ? » et « $ » ne font pas partie du nom de la variable. Dans une interrogation, $abc et ?abc identifient
la même variable. Les noms possibles des variables sont donnés dans la grammaire SPARQL.
[44] |
Var |
::= | VAR1 | VAR2 |
[74] |
VAR1 |
::= | '?' VARNAME |
[75] |
VAR2 |
::= | '$' VARNAME |
[97] |
VARNAME |
::= | ( PN_CHARS_U | [0-9] ) ( PN_CHARS_U | [0-9] | #x00B7 | [#x0300-#x036F] | [#x203F-#x2040] )* |
Les nœuds anonymes dans les motifs de graphe agissent comme des variables indistinctes, non comme des références à des nœuds anonymes spécifiques dans les données interrogées.
Les nœuds anonymes sont indiqués soit sous forme d'une étiquette, telle que "_:abc", soit sous la forme abrégée "[]".
Un nœud anonyme utilisé seulement à une place dans la syntaxe d'interrogation peut être indiqué avec [].
Un nœud anonyme unique sera utilisé pour former le motif de triplet. Les étiquettes de nœud anonyme s'écrivent ainsi : "_:abc"
pour un nœud anonyme avec l'étiquette "abc". Le même nœud anonyme ne peut pas être utilisé dans deux
motifs de graphe élémentaires différents dans la même interrogation.
La structure [:p :v] peut être utilisée dans les motifs de triplet. Elle crée une étiquette de nœud anonyme qui sert
de sujet à tous les couples prédicat-objet contenus. Le nœud anonyme créé peut aussi être utilisé dans d'autres motifs de triplet
en position de sujet et d'objet.
Les deux formes suivantes :
[ :p "v" ] .
[] :p "v" .
allouent une étiquette de nœud anonyme unique (ici "b57") et sont équivalentes à l'écriture suivante :
_:b57 :p "v" .
Cette étiquette de nœud anonyme allouée peut être utilisée comme sujet ou objet d'autres motifs de triplet. Par exemple, comme sujet :
[ :p "v" ] :q "w" .
ce qui équivaut aux deux triplets suivants :
_:b57 :p "v" . _:b57 :q "w" .
et comme objet :
:x :q [ :p "v" ] .
ce qui équivaut aux deux triplets :
:x :q _:b57 . _:b57 :p "v" .
On peut combiner la syntaxe de nœud anonyme abrégée avec d'autres abréviations pour des sujets communs et des prédicats communs.
[ foaf:name ?name ;
foaf:mbox <mailto:alice@example.org> ]
C'est la même chose que d'écrire le motif de graphe élémentaire suivant pour une étiquette de nœud anonyme allouée exclusivement,
"b18" :
_:b18 foaf:name ?name . _:b18 foaf:mbox <mailto:alice@example.org> .
[39] |
BlankNodePropertyList |
::= | '['PropertyListNotEmpty']' |
[69] |
BlankNode |
::= | BLANK_NODE_LABEL | ANON |
[73] |
BLANK_NODE_LABEL |
::= | '_:' PN_LOCAL |
[94] |
ANON |
::= | '[' WS* ']' |
Les motifs de triplet se présentent comme une liste formée d'un sujet, d'un prédicat et d'un objet, séparés par des caractères blancs ; il existe des façons abrégées d'écrire quelques structures de motif de triplet courantes.
Les exemples suivants expriment la même interrogation :
PREFIX dc: <http://purl.org/dc/elements/1.1/>
SELECT ?title
WHERE { <http://example.org/book/book1> dc:title ?title }
PREFIX dc: <http://purl.org/dc/elements/1.1/>
PREFIX : <http://example.org/book/>
SELECT $title
WHERE { :book1 dc:title $title }
BASE <http://example.org/book/>
PREFIX dc: <http://purl.org/dc/elements/1.1/>
SELECT $title
WHERE { <book1> dc:title ?title }
[32] |
TriplesSameSubject |
::= | VarOrTerm PropertyListNotEmpty | |
[33] |
PropertyListNotEmpty |
::= | Verb ObjectList ( ';' ( Verb ObjectList )? )* |
[34] |
PropertyList |
::= | PropertyListNotEmpty? |
[35] |
ObjectList |
::= | Object ( ',' Object )* |
[37] |
Verb |
::= | VarOrIRIref | 'a' |
On peut écrire des motifs de triplet dont le sujet est commun, le sujet est donc écrit une seule fois et utilisé pour plusieurs motifs de triplet en utilisant le caractère POINT-VIRGULE « ; ».
?x foaf:name ?name ;
foaf:mbox ?mbox .
C'est la même chose que d'écrire les motifs de triplet suivants :
?x foaf:name ?name .
?x foaf:mbox ?mbox .
Si des motifs de triplet partagent à la fois un sujet et un prédicat, les objets peuvent être séparés par un caractère VIRGULE « , ».
?x foaf:nick "Alice" , "Alice_" .
C'est la même chose que d'écrire les motifs de triplet suivants :
?x foaf:nick "Alice" . ?x foaf:nick "Alice_" .
On peut combiner des listes d'objets et des listes de prédicats et d'objets :
?x foaf:name ?name ; foaf:nick "Alice" , "Alice_" .
Cela équivaut à :
?x foaf:name ?name . ?x foaf:nick "Alice" . ?x foaf:nick "Alice_" .
Les collections RDF peuvent
s'écrire comme des motifs de triplet en utilisant la syntaxe "(élément1 élément2 ...)". La forme "()" est une alternative
pour l'adresse IRI http://www.w3.org/1999/02/22-rdf-syntax-ns#nil.
Lorsqu'on l'utilise avec les éléments d'une collection, telle que (1 ?x 3 4), des motifs de triplet avec des
nœuds anonymes sont alloués à la collection. Le nœud anonyme en tête de la collection peut être utilisé comme sujet ou objet dans
d'autres motifs de triplet. Les nœuds anonymes alloués par la syntaxe de la collection n'apparaissent pas ailleurs dans l'interrogation.
(1 ?x 3 4) :p "w" .
Est un sucre syntaxique pour (en remarquant que b0, b1, b2 et b3
n'apparaissent pas ailleurs dans l'interrogation) :
_:b0 rdf:first 1 ;
rdf:rest _:b1 .
_:b1 rdf:first ?x ;
rdf:rest _:b2 .
_:b2 rdf:first 3 ;
rdf:rest _:b3 .
_:b3 rdf:first 4 ;
rdf:rest rdf:nil .
_:b0 :p "w" .
Les collections RDF peuvent être imbriquées et impliquer d'autres formes syntaxiques :
(1 [:p :q] ( 2 ) ) .
Est un sucre syntaxique pour :
_:b0 rdf:first 1 ;
rdf:rest _:b1 .
_:b1 rdf:first _:b2 .
_:b2 :p :q .
_:b1 rdf:rest _:b3 .
_:b3 rdf:first _:b4 .
_:b4 rdf:first 2 ;
rdf:rest rdf:nil .
_:b3 rdf:rest rdf:nil .
[40] |
Collection |
::= | '(' GraphNode+ ')' |
[92] |
NIL |
::= | '(' WS* ')' |
On peut utiliser le mot-clé "a" comme prédicat dans un motif de triplet ; c'est une alternative pour l'adresse IRI
http://www.w3.org/1999/02/22-rdf-syntax-ns#type. Ce mot-clé est sensible à la casse.
?x a :Class1 . [ a :appClass ] :p "v" .
Est un sucre syntaxique pour :
?x rdf:type :Class1 . _:b0 rdf:type :appClass . _:b0 :p "v" .
SPARQL repose sur la correspondance des motifs de graphe (graph patterns). On peut réaliser des motifs de graphe plus complexes en combinant des motifs plus petits de façons diverses :
Dans cette section, nous décrivons les deux types combinant les motifs par conjonction : les motifs de graphe élémentaires, qui combinent les motifs de triplet, et les motifs de graphe de groupe, qui combinent tous les autres motifs de graphe.
Le motif de graphe le plus externe dans une interrogation est appelé le motif d'interrogation (query pattern).
Grammaticalement, il est identifié ci-dessous par GroupGraphPattern :
[13] |
WhereClause |
::= | 'WHERE'? GroupGraphPattern |
Les motifs de graphe élémentaires sont des ensembles de motifs de triplet. Le filtrage par motif de graphe SPARQL est défini par la combinaison des résultats issus de la comparaison de motifs de graphe élémentaires.
Une suite de motifs de triplet interrompue par un filtre compose un seul motif de graphe élémentaire. Tout motif de graphe clôt un motif de graphe élémentaire.
Lorsqu'on utilise des nœuds anonymes de la forme _:abc, la portée des étiquettes des nœuds anonymes est limitée au
motif de graphe élémentaire. On ne peut utiliser une étiquette que dans un seul motif de graphe élémentaire dans une interrogation.
SPARQL est défini pour filtrer des graphes RDF à inférence simple (simple entailment). On peut étendre SPARQL à d'autres formes d'inférence sous certaines conditions, comme décrites ci-dessous.
Dans une chaîne d'interrogation (query string) SPARQL, un motif de graphe de groupe est
délimité par des accolades : {}. Par exemple, le motif d'interrogation de l'interrogation suivante est un
motif de graphe de groupe comprenant un seul motif de graphe élémentaire :
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name ?mbox
WHERE {
?x foaf:name ?name .
?x foaf:mbox ?mbox .
}
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name ?mbox
WHERE { { ?x foaf:name ?name . }
{ ?x foaf:mbox ?mbox . }
}
[20]
|
GroupGraphPattern
|
::= |
'{' TriplesBlock? ( ( GraphPatternNotTriples | Filter ) '.'? TriplesBlock? )* '}'
|
[21]
|
TriplesBlock
|
::= | TriplesSameSubject ( '.' TriplesBlock? )?
|
[22] |
GraphPatternNotTriples |
::= |
OptionalGraphPattern | GroupOrUnionGraphPattern | GraphGraphPattern
|
Le motif de groupe :
{ }
filtre tout graphe (y compris le graphe vide) avec une solution qui ne lie pas de variables. Par exemple :
SELECT ?x
WHERE {}
correspond à une solution dans laquelle la variable x n'est pas liée.
Une contrainte, exprimée par le mot-clé FILTER, est une restriction des solutions sur tout le groupe où le filtre apparaît.
Toutes les formes suivantes ont les mêmes solutions :
{ ?x foaf:name ?name .
?x foaf:mbox ?mbox .
FILTER regex(?name, "Smith")
}
{ FILTER regex(?name, "Smith")
?x foaf:name ?name .
?x foaf:mbox ?mbox .
}
{ ?x foaf:name ?name .
FILTER regex(?name, "Smith")
?x foaf:mbox ?mbox .
}
Ce groupe comprend un seul motif de graphe élémentaire ; ce motif de graphe élémentaire est composé de deux motifs de triplet :
{
?x foaf:name ?name .
?x foaf:mbox ?mbox .
}
Ce groupe comprend un seul motif de graphe élémentaire et un filtre ; ce motif de graphe élémentaire est composé de deux motifs de triplet ; le filtre ne rompt pas le motif de graphe élémentaire en deux motifs de graphe élémentaires :
{
?x foaf:name ?name . FILTER regex(?name, "Smith")
?x foaf:mbox ?mbox .
}
Ce groupe comprend trois éléments : un motif de graphe élémentaire composé d'un seul motif de triplet, un groupe vide et un autre motif de graphe élémentaire composé d'un seul motif de triplet :
{
?x foaf:name ?name .
{}
?x foaf:mbox ?mbox .
}
Les motifs de graphe élémentaires permettent aux applications d'effectuer des interrogations où le motif d'interrogation entier doit correspondre pour qu'il y ait une solution. Pour chaque solution d'une interrogation contenant seulement des motifs de graphe de groupe avec au moins un motif de graphe élémentaire, chaque variable est liée à un terme RDF dans une solution. Toutefois, on ne peut pas supposer la présence de structures complètes et régulières dans tous les graphes RDF. Il est utile d'avoir des interrogations qui puissent ajouter des informations à la solution où l'information est disponible, mais qui ne rejettent pas la solution parce que des parties du motif d'interrogation ne correspondent pas. Cette fonction est offerte par le filtrage optionnel (optional matching) : si la partie optionnelle ne correspond pas, elle ne crée aucune liaison mais n'élimine pas la solution.
On peut définir syntaxiquement des parties optionnelles dans le motif de graphe en appliquant le mot-clé OPTIONAL
au motif de graphe :
motif OPTIONAL { motif }
Cette forme syntaxique :
{ OPTIONAL { motif } }
équivaut à la suivante :
{ { } OPTIONAL { motif } }
[23] |
OptionalGraphPattern |
::= | 'OPTIONAL' GroupGraphPattern |
Le mot-clé OPTIONAL est associatif à gauche (left-associative) :
motif OPTIONAL { motif } OPTIONAL { motif }
est la même chose que :
{ motif OPTIONAL { motif } } OPTIONAL { motif }
Dans un filtrage optionnel, soit le motif de graphe optionnel correspond à un graphe, en définissant et ajoutant ainsi des liaisons à une ou plusieurs solutions, soit il laisse une solution inchangée sans ajouter de liaisons supplémentaires.
Données :
@prefix foaf: <http://xmlns.com/foaf/0.1/> . @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . _:a rdf:type foaf:Person . _:a foaf:name "Alice" . _:a foaf:mbox <mailto:alice@example.com> . _:a foaf:mbox <mailto:alice@work.example> . _:b rdf:type foaf:Person . _:b foaf:name "Bob" .
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name ?mbox
WHERE { ?x foaf:name ?name .
OPTIONAL { ?x foaf:mbox ?mbox }
}
Avec les données précédentes, le résultat d'interrogation est :
| name | mbox |
|---|---|
| "Alice" | <mailto:alice@example.com> |
| "Alice" | <mailto:alice@work.example> |
| "Bob" |
Il n'y a pas de valeur pour mbox dans la solution où le nom est "Bob".
Cette interrogation trouve les noms des personnes dans les données. S'il y a un triplet avec le prédicat mbox
et le même sujet, une solution contiendra également ce triplet. Dans cet exemple, on ne donne qu'un seul motif de triplet dans la
partie à filtrage optionnel de l'interrogation mais, en général, la partie optionnelle peut être un motif de graphe quelconque.
Le motif de graphe optionnel doit correspondre entièrement pour affecter la solution d'interrogation.
On peut fournir des contraintes dans un motif de graphe optionnel. Par exemple :
@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 .
PREFIX dc: <http://purl.org/dc/elements/1.1/>
PREFIX ns: <http://example.org/ns#>
SELECT ?title ?price
WHERE { ?x dc:title ?title .
OPTIONAL { ?x ns:price ?price . FILTER (?price < 30) }
}
| title | price |
|---|---|
| "SPARQL Tutorial" | |
| "The Semantic Web" | 23 |
Le prix du livre intitulé "SPARQL Tutorial" n'apparaît pas parce que le motif de graphe optionnel ne conduisait pas à une solution
impliquant la variable "price".
Les motifs de graphe sont définis récursivement. Un motif de graphe peut avoir zéro ou plus motifs de graphe optionnels, et toute partie d'un motif d'interrogation peut avoir une partie optionnelle. Dans cet exemple, il y a deux motifs de graphe optionnels.
@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> .
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name ?mbox ?hpage
WHERE { ?x foaf:name ?name .
OPTIONAL { ?x foaf:mbox ?mbox } .
OPTIONAL { ?x foaf:homepage ?hpage }
}
Résultat d'interrogation :
| name | mbox | hpage |
|---|---|---|
| "Alice" | <http://work.example.org/alice/> | |
| "Bob" | <mailto:bob@work.example> |
SPARQL fournit un moyen de combiner les motifs de graphe de telle sorte que l'un des motifs de graphe alternatifs peut correspondre. Si plusieurs alternatives correspondent, toutes les solutions de motifs possibles sont trouvées.
Les alternatives de motifs sont indiquées syntaxiquement par le mot-clé UNION.
@prefix dc10: <http://purl.org/dc/elements/1.0/> . @prefix dc11: <http://purl.org/dc/elements/1.1/> . _:a dc10:title "SPARQL Query Language Tutorial" . _:a dc10:creator "Alice" . _:b dc11:title "SPARQL Protocol Tutorial" . _:b dc11:creator "Bob" . _:c dc10:title "SPARQL" . _:c dc11:title "SPARQL (updated)" .
PREFIX dc10: <http://purl.org/dc/elements/1.0/>
PREFIX dc11: <http://purl.org/dc/elements/1.1/>
SELECT ?title
WHERE { { ?book dc10:title ?title } UNION { ?book dc11:title ?title } }
Résultat d'interrogation :
| title |
|---|
| "SPARQL Protocol Tutorial" |
| "SPARQL" |
| "SPARQL (updated)" |
| "SPARQL Query Language Tutorial" |
Cette interrogation trouve les titres des livres dans les données, que le titre soit enregistré en utilisant des propriétés Dublin Core en version 1.0 ou en version 1.1. Pour déterminer exactement comment l'information a été enregistrée, l'interrogation pourrait utiliser des variables différentes pour les deux alternatives :
PREFIX dc10: <http://purl.org/dc/elements/1.0/>
PREFIX dc11: <http://purl.org/dc/elements/1.1/>
SELECT ?x ?y
WHERE { { ?book dc10:title ?x } UNION { ?book dc11:title ?y } }
| x | y |
|---|---|
| "SPARQL (updated)" | |
| "SPARQL Protocol Tutorial" | |
| "SPARQL" | |
| "SPARQL Query Language Tutorial" |
Cela retournera un résultat avec la variable x liée aux solutions du segment gauche de l'UNION,
et la variable y liée aux solutions du segment droit. Si aucune partie de la forme UNION ne correspondait,
alors le motif de graphe ne correspondrait pas.
La forme UNION combine les motifs de graphe ; chaque possibilité alternative peut contenir plusieurs motifs de triplet :
PREFIX dc10: <http://purl.org/dc/elements/1.0/>
PREFIX dc11: <http://purl.org/dc/elements/1.1/>
SELECT ?title ?author
WHERE { { ?book dc10:title ?title . ?book dc10:creator ?author }
UNION
{ ?book dc11:title ?title . ?book dc11:creator ?author }
}
| author | title |
|---|---|
| "Alice" | "SPARQL Protocol Tutorial" |
| "Bob" | "SPARQL Query Language Tutorial" |
Cette interrogation ne correspondra à un livre que si son titre et son prédicat d'auteur sont tous deux de la même version de Dublin Core.
[25] |
GroupOrUnionGraphPattern |
::= | GroupGraphPattern
|
Le modèle de données RDF exprime l'information sous forme de graphes consistant en triplets avec un sujet, un prédicat et un objet. Beaucoup de magasins de données RDF contiennent plusieurs graphes RDF et des données d'enregistrement (record information) pour chaque graphe, permettant à une application d'effectuer des interrogations impliquant des informations issues de plusieurs graphes.
Une interrogation SPARQL est exécutée auprès d'un ensemble de données RDF (RDF Dataset) qui représente une collection de graphes. Un ensemble de données RDF comprend un graphe anonyme, le graphe par défaut, et zéro ou plus graphes nommés où chaque graphe nommé est identifié par une adresse IRI. Une interrogation SPARQL peut comparer des parties différentes du motif d'interrogation à des graphes différents, comme décrit à la section 8.3 Interrogation de l'ensemble de données.
Un ensemble de données RDF peut contenir zéro graphe nommé ; un ensemble de données RDF contient toujours un seul graphe par défaut. Une interrogation n'a pas besoin d'inclure un filtrage du graphe par défaut ; l'interrogation peut juste inclure un filtrage des graphes nommés.
Le graphe utilisé pour filtrer un motif de graphe élémentaire est le graphe actif (active graphe).
Dans les sections précédentes, toutes les interrogations sont illustrées en exécution par rapport à un seul graphe,
le graphe par défaut d'un ensemble de données RDF comme graphe actif. On utilise le mot-clé GRAPH
pour établir l'un parmi tous les graphes nommés dans l'ensemble de données comme graphe actif pour une partie de l'interrogation.
La définition de l'ensemble de données RDF ne restreint pas les relations des graphes nommées et du graphe par défaut. L'information peut être répétée dans des graphes différents ; les relations entre les graphes peuvent être exposées. Deux arrangements sont utiles :
# Graphe par défaut @prefix dc: <http://purl.org/dc/elements/1.1/> . <http://example.org/bob> dc:publisher "Bob" . <http://example.org/alice> dc:publisher "Alice" .
# Graphe nommé : http://example.org/bob @prefix foaf: <http://xmlns.com/foaf/0.1/> . _:a foaf:name "Bob" . _:a foaf:mbox <mailto:bob@oldcorp.example.org> .
# Graphe nommé : http://example.org/alice @prefix foaf: <http://xmlns.com/foaf/0.1/> . _:a foaf:name "Alice" . _:a foaf:mbox <mailto:alice@work.example.org> .
Dans cet exemple, le graphe par défaut contient les noms des auteurs des deux graphes nommés. Ici les triplets dans les graphes nommés ne sont pas visibles dans le graphe par défaut.
Example 2 :
Les données RDF peuvent être combinées par la fusion RDF (RDF merge) des graphes [RDF-MT]. Un arrangement possible des graphes dans un ensemble de données RDF est de faire du graphe par défaut la fusion RDF de la totalité ou d'une partie des informations contenues dans les graphes nommés.
Dans l'exemple suivant, les graphes nommés contiennent les mêmes triplets qu'auparavant. L'ensemble de données RDF inclut une fusion RDF des graphes nommés dans le graphe par défaut, en rétiquetant les nœuds anonymes pour les garder distincts.
# Graphe par défaut @prefix foaf: <http://xmlns.com/foaf/0.1/> . _:x foaf:name "Bob" . _:x foaf:mbox <mailto:bob@oldcorp.example.org> . _:y foaf:name "Alice" . _:y foaf:mbox <mailto:alice@work.example.org> .
# Graphe nommé : http://example.org/bob @prefix foaf: <http://xmlns.com/foaf/0.1/> . _:a foaf:name "Bob" . _:a foaf:mbox <mailto:bob@oldcorp.example.org> .
# Graphe nommé : http://example.org/alice @prefix foaf: <http://xmlns.com/foaf/0.1/> . _:a foaf:name "Alice" . _:a foaf:mbox <mailto:alice@work.example> .
Dans une fusion RDF, les nœuds anonymes dans le graphe fusionné ne sont pas partagés avec les nœuds anonymes des graphes à fusionner.
Une interrogation SPARQL peut indiquer l'ensemble de données à utiliser au filtrage en utilisant les clauses
FROM et FROM NAMED pour décrire l'ensemble de données RDF. Si une interrogation comporte une
telle description d'un ensemble de données, alors cet ensemble de données est utilisé à la place de tout ensemble de données
que le service d'interrogation (query service) utiliserait si l'interrogation ne fournissait pas de description d'ensemble de données.
L'ensemble de données RDF peut également être défini dans une requête de protocole SPARQL,
auquel cas la description de protocole écrase (override) toute description dans l'interrogation même.
Un service d'interrogation peut refuser une requête d'interrogation si la description d'ensemble de données lui est inacceptable.
Les mots-clés FROM et FROM NAMED permettent à une interrogation d'indiquer un ensemble de données RDF
par référence ; ils indiquent que l'ensemble de données devrait inclure des graphes obtenus à partir de représentations des ressources
identifiées par les adresses IRI données (à savoir la forme absolue des références IRI fournies).
L'ensemble de données obtenu à partir d'un certain nombre de clauses FROM et FROM NAMED est :
FROM, et ;FROM NAMED.S'il n'y a pas de clause FROM mais une ou plusieurs clauses FROM NAMED, alors l'ensemble de données comprend
un graphe vide pour le graphe par défaut.
[9] |
DatasetClause |
::= | 'FROM' ( DefaultGraphClause | NamedGraphClause ) |
[10] |
DefaultGraphClause |
::= | SourceSelector |
[11] |
NamedGraphClause |
::= | 'NAMED' SourceSelector |
[12] |
SourceSelector |
::= | IRIref |
Chaque clause FROM contient une adresse IRI indiquant un graphe à utiliser pour former le graphe par défaut.
Cela n'installe pas le graphe comme graphe nommé.
Dans cet exemple, l'ensemble de données RDF contient un seul graphe par défaut et aucun graphe nommé :
# Graphe par défaut (stocké à http://example.org/foaf/aliceFoaf) @prefix foaf: <http://xmlns.com/foaf/0.1/> . _:a foaf:name "Alice" . _:a foaf:mbox <mailto:alice@work.example> .
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name
FROM <http://example.org/foaf/aliceFoaf>
WHERE { ?x foaf:name ?name }
| name |
|---|
| "Alice" |
Si une interrogation présente plusieurs clauses FROM, en fournissant plusieurs adresses IRI pour indiquer
le graphe par défaut, alors le graphe par défaut est fondé sur la fusion RDF
des graphes obtenus des représentations des ressources identifiées par les adresses IRI en question.
Une interrogation peut fournir les adresses IRI des graphes nommés dans l'ensemble de données RDF avec
la clause FROM NAMED. Chaque adresse IRI est utilisée pour fournir un seul graphe nommé dans
l'ensemble de données RDF. L'utilisation d'une même adresse IRI dans deux ou plus clauses FROM NAMED
se traduit par l'apparition d'un seul graphe nommé avec cette adresse IRI dans l'ensemble de données.
# Graphe : http://example.org/bob @prefix foaf: <http://xmlns.com/foaf/0.1/> . _:a foaf:name "Bob" . _:a foaf:mbox <mailto:bob@oldcorp.example.org> .
# Graphe : http://example.org/alice @prefix foaf: <http://xmlns.com/foaf/0.1/> . _:a foaf:name "Alice" . _:a foaf:mbox <mailto:alice@work.example> .
... FROM NAMED <http://example.org/alice> FROM NAMED <http://example.org/bob> ...
La syntaxe FROM NAMED suggère que l'adresse IRI identifie le graphe correspondant, mais la relation entre une
adresse IRI et un graphe dans un ensemble de données RDF est indirecte. L'adresse IRI identie
une ressource et la ressource est représentée par un graphe (ou, plus précisément, par un document qui sérialise un graphe).
Pour plus de détails, cf. [WEBARCH].
On peut utiliser la clause FROM et la clause FROM NAMED dans la même interrogation.
# Graphe par défaut (stocké à http://example.org/dft.ttl) @prefix dc: <http://purl.org/dc/elements/1.1/> . <http://example.org/bob> dc:publisher "Bob Hacker" . <http://example.org/alice> dc:publisher "Alice Hacker" .
# Graphe nommé : http://example.org/bob @prefix foaf: <http://xmlns.com/foaf/0.1/> . _:a foaf:name "Bob" . _:a foaf:mbox <mailto:bob@oldcorp.example.org> .
# Graphe nommé : http://example.org/alice @prefix foaf: <http://xmlns.com/foaf/0.1/> . _:a foaf:name "Alice" . _:a foaf:mbox <mailto:alice@work.example.org> .
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX dc: <http://purl.org/dc/elements/1.1/>
SELECT ?who ?g ?mbox
FROM <http://example.org/dft.ttl>
FROM NAMED <http://example.org/alice>
FROM NAMED <http://example.org/bob>
WHERE
{
?g dc:publisher ?who .
GRAPH ?g { ?x foaf:mbox ?mbox }
}
L'ensemble de données RDF de cette interrogation contient un graphe par défaut et deux graphes nommés.
Le mot-clé GRAPH est décrit ci-dessous.
Les actions nécessaires pour construire l'ensemble de données ne sont pas déterminées par la seule description de l'ensemble de données.
Si une adresse IRI apparaît deux fois dans une description d'ensemble de données, soit par deux clauses FROM,
soit par une clause FROM et une clause FROM NAMED, alors cela ne suppose pas que sont faites
une seule tentative exactement ou deux tentatives exactement pour obtenir un graphe RDF associé à l'adresse IRI.
Dès lors, on ne peut faire aucune supposition à propos de l'identité des nœuds anonymes dans les triplets obtenus à partir des deux apparitions
(occurrences) dans la description de l'ensemble de données. En général, on ne peut faire aucune supposition
concernant l'équivalence des graphes.
Lors de l'interrogation d'une collection de graphes, le mot-clé GRAPH est utilisé pour comparer des motifs à des
graphes nommés. GRAPH peut fournir une adresse IRI pour sélectionner un seul graphe ou utiliser une variable
qui s'étendra sur l'adresse IRI de tous les graphes nommés dans l'ensemble de données RDF de l'interrogation.
L'utilisation de GRAPH change le graphe actif pour le filtrage des motifs de graphe élémentaires dans une partie de
l'interrogation. En dehors de l'utilisation de GRAPH, le graphe par défaut est filtré par des motifs de graphe élémentaires.
Dans les exemples, nous utiliserons les deux graphes suivants :
# Graphe nommé : http://example.org/foaf/aliceFoaf
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
_:a foaf:name "Alice" .
_:a foaf:mbox <mailto:alice@work.example> .
_:a foaf:knows _:b .
_:b foaf:name "Bob" .
_:b foaf:mbox <mailto:bob@work.example> .
_:b foaf:nick "Bobby" .
_:b rdfs:seeAlso <http://example.org/foaf/bobFoaf> .
<http://example.org/foaf/bobFoaf>
rdf:type foaf:PersonalProfileDocument .
# Graphe nommé : http://example.org/foaf/bobFoaf
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
_:z foaf:mbox <mailto:bob@work.example> .
_:z rdfs:seeAlso <http://example.org/foaf/bobFoaf> .
_:z foaf:nick "Robert" .
<http://example.org/foaf/bobFoaf>
rdf:type foaf:PersonalProfileDocument .
[24] |
GraphGraphPattern |
::= | 'GRAPH' VarOrIRIref GroupGraphPattern |
L'interrogation suivante compare le motif de graphe à chacun des graphes nommés dans l'ensemble de données et forme des solutions
où la variable src est liée aux adresses IRI du graphe comparé. Le motif de graphe est comparé au
graphe actif, c'est-à-dire chacun des graphes nommés dans l'ensemble de données.
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?src ?bobNick
FROM NAMED <http://example.org/foaf/aliceFoaf>
FROM NAMED <http://example.org/foaf/bobFoaf>
WHERE
{
GRAPH ?src
{ ?x foaf:mbox <mailto:bob@work.example> .
?x foaf:nick ?bobNick
}
}
Le résultat d'interrogation donne le nom des graphes où l'information est trouvée et la valeur du surnom (nick) de Bob :
| src | bobNick |
|---|---|
| <http://example.org/foaf/aliceFoaf> | "Bobby" |
| <http://example.org/foaf/bobFoaf> | "Robert" |
L'interrogation peut restreindre le filtrage appliqué à un graphe spécifique en fournissant l'adresse IRI du graphe.
Cela établit le graphe nommé par l'addresse IRI comme graphe actif. Cette interrogation cherche le surnom de Bob tel
que donné dans le graphe http://example.org/foaf/bobFoaf.
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX data: <http://example.org/foaf/>
SELECT ?nick
FROM NAMED <http://example.org/foaf/aliceFoaf>
FROM NAMED <http://example.org/foaf/bobFoaf>
WHERE
{
GRAPH data:bobFoaf {
?x foaf:mbox <mailto:bob@work.example> .
?x foaf:nick ?nick }
}
ce qui produit une seule solution :
| nick |
|---|
| "Robert" |
Une variable utilisée dans la clause GRAPH peut aussi l'être dans une autre clause GRAPH ou dans un
motif de graphe comparé au graphe par défaut dans l'ensemble de données.
L'interrogation suivante utilise le graphe avec l'adresse IRI http://example.org/foaf/aliceFoaf
pour trouver le document de profil de Bob ; puis elle compare un autre motif à ce graphe. Le motif dans la deuxième
clause GRAPH trouve le nœud anonyme (variable w) de la personne avec la même boîte aux lettres (donnée
par la variable mbox) que celle trouvée dans la première clause GRAPH (variable whom),
parce que le nœud anonyme utilisé pour filtrer la variable whom du fichier FOAF
d'Alice n'est pas le même que le nœud anonyme du document de profil (puisqu'ils se trouvent dans des graphes différents).
PREFIX data: <http://example.org/foaf/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?mbox ?nick ?ppd
FROM NAMED <http://example.org/foaf/aliceFoaf>
FROM NAMED <http://example.org/foaf/bobFoaf>
WHERE
{
GRAPH data:aliceFoaf
{
?alice foaf:mbox <mailto:alice@work.example> ;
foaf:knows ?whom .
?whom foaf:mbox ?mbox ;
rdfs:seeAlso ?ppd .
?ppd a foaf:PersonalProfileDocument .
} .
GRAPH ?ppd
{
?w foaf:mbox ?mbox ;
foaf:nick ?nick
}
}
| mbox | nick | ppd |
|---|---|---|
| <mailto:bob@work.example> | "Robert" | <http://example.org/foaf/bobFoaf> |
Un triplet dans le fichier FOAF d'Alice donnant le surnom (nick) de Bob ne sera pas utilisé pour fournir
le surnom de Bob car le motif impliquant la variable nick est restreint par la variable ppd à un
document de profil personnel (Personal Profile Document) particulier.
Les motifs d'interrogation peuvent impliquer à la fois le graphe par défaut et les graphes nommés. Dans cet exemple, un agrégateur (aggregator) a lu une ressource web à deux occasions différentes. À chaque fois qu'un graphe est interprété dans l'agrégateur, il reçoit du système local une adresse IRI. Les graphes sont pratiquement les mêmes hormis l'adresse de courrier électronique de Bob qui a changé.
Ici le graphe par défaut est utilisé pour enregistrer les informations de provenance et les données RDF réellement lues sont conservées en deux graphes séparés, le système donnant à chacun une adresse IRI différente. L'ensemble de données RDF est constitué des deux graphes nommés et des informations à leur sujet.
RDF Dataset:
# Graphe par défaut @prefix dc: <http://purl.org/dc/elements/1.1/> . @prefix g: <tag:example.org,2005-06-06:> . @prefix xsd: <http://www.w3.org/2001/XMLSchema#> . g:graph1 dc:publisher "Bob" . g:graph1 dc:date "2004-12-06"^^xsd:date . g:graph2 dc:publisher "Bob" . g:graph2 dc:date "2005-01-10"^^xsd:date .
# Graphe avec adresse IRI allouée localement : tag:example.org,2005-06-06:graph1 @prefix foaf: <http://xmlns.com/foaf/0.1/> . _:a foaf:name "Alice" . _:a foaf:mbox <mailto:alice@work.example> . _:b foaf:name "Bob" . _:b foaf:mbox <mailto:bob@oldcorp.example.org> .
# Graphe avec adresse IRI allouée localement : tag:example.org,2005-06-06:graph2 @prefix foaf: <http://xmlns.com/foaf/0.1/> . _:a foaf:name "Alice" . _:a foaf:mbox <mailto:alice@work.example> . _:b foaf:name "Bob" . _:b foaf:mbox <mailto:bob@newcorp.example.org> .
Cette interrogation découvre des adresses électroniques, en détaillant le nom de la personne et la date de découverte de l'information.
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX dc: <http://purl.org/dc/elements/1.1/>
SELECT ?name ?mbox ?date
WHERE
{ ?g dc:publisher ?name ;
dc:date ?date .
GRAPH ?g
{ ?person foaf:name ?name ; foaf:mbox ?mbox }
}
Les résultats montrent que l'adresse électronique de "Bob" a changé.
| name | mbox | date |
|---|---|---|
| "Bob" | <mailto:bob@oldcorp.example.org> | "2004-12-06"^^xsd:date |
| "Bob" | <mailto:bob@newcorp.example.org> | "2005-01-10"^^xsd:date |
L'adresse IRI du type de donnée date est abrégée dans les résultats pour la lisibilité.
Les motifs d'interrogation génèrent une collection non ordonnée de solutions, chaque solution étant une fonction partielle de variables vers des termes RDF. Ces solutions sont ensuite traitées comme une séquence (une séquence de solutions), d'abord sans ordre spécifique ; les éventuels modificateurs de séquence s'appliquent alors pour créer une autre séquence. Enfin, cette dernière séquence est utilisée pour générer un des résultats d'une forme d'interrogation SPARQL.
Un modificateur de séquence de solutions (solution sequence modifier) est l'un des suivants :
Les modificateurs s'appliquent dans l'ordre de la liste ci-dessus.
[5] |
SelectQuery |
::= | 'SELECT' ( 'DISTINCT' |
'REDUCED' )? ( Var+ | '*' )
DatasetClause* WhereClause SolutionModifier |
[14] |
SolutionModifier |
::= | OrderClause? LimitOffsetClauses? |
[15] |
LimitOffsetClauses |
::= | ( LimitClause OffsetClause? |
OffsetClause LimitClause? ) |
[16] |
OrderClause |
::= | 'ORDER' 'BY'
OrderCondition+ |
La clause ORDER BY établit l'ordre d'une séquence de solutions.
À la suite de la clause ORDER BY on trouve une séquence de comparateurs de tri, composée d'une expression et d'un
modificateur de tri optionnel — ASC() ou DESC(). Chaque comparateur de tri est soit ascendant
— indiqué par le modificateur ASC() ou aucun modificateur —, soit descendant — indiqué par le modificateur DESC().
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name
WHERE { ?x foaf:name ?name }
ORDER BY ?name
PREFIX : <http://example.org/ns#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT ?name
WHERE { ?x foaf:name ?name ; :empId ?emp }
ORDER BY DESC(?emp)
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name
WHERE { ?x foaf:name ?name ; :empId ?emp }
ORDER BY ?name DESC(?emp)
L'opérateur "<" (cf. les sections 11.3 Conversion des opérateurs
et 11.3.1 Extensibilité des opérateurs) définit l'ordre relatif de deux types
numériques, littéraux simples, xsd:string, xsd:boolean
et xsd:dateTime. On ordonne deux adresses IRI en les comparant comme des littéraux simples.
SPARQL établit également un classement entre certains types de termes RDF qui ne seraient pas ordonnés sinon :
Un littéral ordinaire (plain literal) est inférieur à un littéral RDF
avec un type xsd:string de la même forme lexicale.
SPARQL ne définit pas le classement d'ensemble de tous les termes RDF possibles. Voici quelques exemples de couples de termes pour lesquels l'ordre relatif n'est pas défini :
Cette liste de liaisons de variables est en ordre ascendant :
| Terme RDF | Raison |
|---|---|
| Les résultats non liés sont triés comme étant en premier. | |
_:z | Les nœuds anonymes suivent les non liés. |
_:a | Il n'y a pas de classement relatif des nœuds anonymes. |
<http://script.example/Latin> | Les adresses IRI suivent les nœuds anonymes. |
<http://script.example/Кириллица> | Le caractère cyrillique "К" en vingt-troisième position a un point de code Unicode 0x41A, lequel est supérieur à 0x4C ("L"). |
<http://script.example/漢字> | Le caractère chinois "漢" en vingt-troisième position a un point de code Unicode 0x6F22, lequel est supérieur à 0x41A ("К"). |
"http://script.example/Latin" | Les littéraux simples suivent les adresses IRI. |
"http://script.example/Latin"^^xsd:string | Les types xsd:string suivent les littéraux simples. |
L'ordre ascendant de deux solutions en fonction d'un comparateur de tri est établi en substituant les liaisons de solution dans les expressions et en les comparant avec l'opérateur "<". L'ordre descendant est l'inverse de l'ordre ascendant.
L'ordre relatif de deux solutions est celui des deux solutions en fonction du premier comparateur de tri dans la séquence. Pour les solutions où les substitutions des liaisons de solution produisent le même terme RDF, l'ordre relatif est celui des deux solutions en fonction du comparateur de tri suivant. L'ordre relatif de deux solutions n'est pas défini si aucune expression de tri évaluée dans les deux solutions ne produit de termes RDF distincts.
Le tri d'une séquence de solutions produit toujours une séquence contenant le même nombre de solutions.
L'utilisation du modificateur ORDER BY sur la séquence de solutions d'une interrogation de type CONSTRUCT ou
DESCRIBE n'a aucun effet direct puisque seule une interrogation de type SELECT retourne une séquence de résultats.
Lorsqu'utilisé en combinaison avec les modificateurs LIMIT et OFFSET, le modificateur ORDER BY
peut servir à retourner des résultats générés à partir d'une tranche différente de la séquence de solutions.
Une interrogation ASK ne contient pas de modificateurs ORDER BY, LIMIT ou OFFSET.
[16] |
OrderClause |
::= | 'ORDER' 'BY' OrderCondition+ |
[17] |
OrderCondition |
::= | ( ( 'ASC' | 'DESC' ) BrackettedExpression ) |
[18] |
LimitClause |
::= | 'LIMIT' INTEGER |
[19] |
OffsetClause |
::= | 'OFFSET' INTEGER |
La séquence de solutions peut être transformée en une séquence n'impliquant qu'un sous-ensemble des variables. Pour chaque solution
dans la séquence, une nouvelle solution est formée avec une sélection définie des variables en utilisant la
forme d'interrogation SELECT.
Les exemples suivants montrent une interrogation pour n'extraire que les noms des personnes décrites dans un graphe RDF utilisant des propriétés FOAF :
@prefix foaf: <http://xmlns.com/foaf/0.1/> . _:a foaf:name "Alice" . _:a foaf:mbox <mailto:alice@work.example> . _:b foaf:name "Bob" . _:b foaf:mbox <mailto:bob@work.example> .
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name
WHERE
{ ?x foaf:name ?name }
| name |
|---|
| "Bob" |
| "Alice" |
Une séquence de solutions sans les modificateurs DISTINCT ou REDUCED gardera les solutions en double.
@prefix foaf: <http://xmlns.com/foaf/0.1/> . _:x foaf:name "Alice" . _:x foaf:mbox <mailto:alice@example.com> . _:y foaf:name "Alice" . _:y foaf:mbox <mailto:asmith@example.com> . _:z foaf:name "Alice" . _:z foaf:mbox <mailto:alice.smith@example.com> .
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name WHERE { ?x foaf:name ?name }
| name |
|---|
| "Alice" |
| "Alice" |
| "Alice" |
Les modificateurs DISTINCT et REDUCED contrôlent si les doubles sont inclus dans les résultats d'interrogation.
Le modificateur de solution DISTINCT élimine les solutions en double. Spécifiquement, chaque solution liant les
mêmes variables aux mêmes termes RDF est éliminée de la séquence de solutions.
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT DISTINCT ?name WHERE { ?x foaf:name ?name }
| name |
|---|
| "Alice" |
Notez que les doubles, selon l'ordre des modificateurs de séquences de solutions,
sont éliminés avant que les modificateurs LIMIT ou bien OFFSET ne s'appliquent.
Tandis que le modificateur DISTINCT assure l'élimination des solutions en double dans l'ensemble de solutions,
le modificateur REDUCED permet simplement de les éliminer. La cardinalité d'un ensemble de liaisons de variables dans un
ensemble de solutions REDUCED est d'au moins un et n'est pas supérieure à celle de l'ensemble de solutions sans les
modificateurs DISTINCT ou REDUCED. Par exemple, en utilisant les données précédentes, l'interrogation ci-dessous :
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT REDUCED ?name WHERE { ?x foaf:name ?name }
peut avoir une, deux (c'est le cas ici) ou trois solutions :
| name |
|---|
| "Alice" |
| "Alice" |
Le modificateur OFFSET fait commencer les solutions générées après le nombre de solutions indiqué. Une valeur
OFFSET de zéro n'a aucun effet.
L'emploi des modificateurs LIMIT et OFFSET pour sélectionner des sous-ensembles différents parmi les
solutions d'interrogation n'aura pas d'utilité à moins d'en rendre l'ordre prévisible en utilisant le modificateur ORDER BY.
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name
WHERE { ?x foaf:name ?name }
ORDER BY ?name
LIMIT 5
OFFSET 10
La clause LIMIT place une limite supérieure au nombre des solutions retournées. Si le nombre de solutions réel
est supérieur à la limite, alors le nombre limite de solutions, au plus, sera retourné.
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name
WHERE { ?x foaf:name ?name }
LIMIT 20
Aucun résultat n'est retourné pour une valeur LIMIT de 0. Une limite ne peut pas être négative.
SPARQL offre quatre formes d'interrogation (query forms). Ces formes d'interrogation utilisent les solutions du filtrage par motif (pattern matching) pour former des ensembles de résultats ou des graphes RDF. Les formes d'interrogation sont les suivantes :
- SELECT
- Retourne toutes les variables liées, ou un sous-ensemble de celles-ci, dans une comparaison de motifs d'interrogation (query pattern match).
- CONSTRUCT
- Retourne un graphe RDF construit en substituant des variables dans un ensemble de gabarits de triplet (triple templates).
- ASK
- Retourne un booléen indiquant si un motif d'interrogation correspond ou non.
- DESCRIBE
- Retourne un graphe RDF décrivant les ressources trouvées.
On peut utiliser le format XML des résultats de liaisons de variables SPARQL
pour sérialiser l'ensemble de résultats d'une interrogation SELECT ou le résultat booléen d'une interrogation ASK.
La forme SELECT des résultats retourne les variables et leurs liaisons directement. La syntaxe SELECT *
est une abréviation pour sélectionner toutes les variables dans une interrogation.
@prefix foaf: <http://xmlns.com/foaf/0.1/> . _:a foaf:name "Alice" . _:a foaf:knows _:b . _:a foaf:knows _:c . _:b foaf:name "Bob" . _:c foaf:name "Clare" . _:c foaf:nick "CT" .
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?nameX ?nameY ?nickY
WHERE
{ ?x foaf:knows ?y ;
foaf:name ?nameX .
?y foaf:name ?nameY .
OPTIONAL { ?y foaf:nick ?nickY }
}
| nameX | nameY | nickY |
|---|---|---|
| "Alice" | "Bob" | |
| "Alice" | "Clare" | "CT" |
Les ensembles de résultats peuvent être accédés par une interface de programmation (API) locale mais aussi être sérialisés en XML ou bien en un graphe RDF. Un format XML est décrit dans la spécification Format XML des résultats d'interrogation SPARQL, qui donne pour cet exemple :
<?xml version="1.0"?>
<sparql xmlns="http://www.w3.org/2005/sparql-results#">
<head>
<variable name="nameX"/>
<variable name="nameY"/>
<variable name="nickY"/>
</head>
<results>
<result>
<binding name="nameX">
<literal>Alice</literal>
</binding>
<binding name="nameY">
<literal>Bob</literal>
</binding>
</result>
<result>
<binding name="nameX">
<literal>Alice</literal>
</binding>
<binding name="nameY">
<literal>Clare</literal>
</binding>
<binding name="nickY">
<literal>CT</literal>
</binding>
</result>
</results>
</sparql>
[5] |
SelectQuery |
::= | 'SELECT' ( 'DISTINCT' | 'REDUCED' )? ( Var+ | '*' ) |
La forme d'interrogation CONSTRUCT retourne un seul graphe RDF défini par un gabarit de graphe
(graph template). Le résultat est un graphe RDF formé en prenant chaque solution d'interrogation
dans la séquence de solutions, en substituant les variables dans le gabarit de graphe et en combinant les triplets
en un seul graphe RDF par une union d'ensemble.
Si une telle instanciation produit un triplet contenant une variable non liée ou une structure RDF invalide, telle
qu'un littéral en position de sujet ou de prédicat, alors ce triplet n'est pas inclus dans le graphe RDF de sortie.
Le gabarit de graphe peut contenir des triplets sans variable — connu comme triplets de base (ground triples)
ou triplets explicites — qui apparaissent également dans le graphe RDF de sortie retourné par
la forme d'interrogation CONSTRUCT.
@prefix foaf: <http://xmlns.com/foaf/0.1/> . _:a foaf:name "Alice" . _:a foaf:mbox <mailto:alice@example.org> .
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 }
Cette interrogation crée des propriétés vcard à partir des informations FOAF :
@prefix vcard: <http://www.w3.org/2001/vcard-rdf/3.0#> . <http://example.org/person#Alice> vcard:FN "Alice" .
Un gabarit peut créer un graphe RDF contenant des nœuds anonymes (blank nodes). Les étiquettes de nœud anonyme sont confinées (scoped) au gabarit de chaque solution. Si la même étiquette apparaît deux fois dans un gabarit, il sera alors créé un nœud anonyme pour chaque solution d'interrogation mais il y aura des nœuds anonymes différents pour les triplets générés par les autres solutions d'interrogation.
@prefix foaf: <http://xmlns.com/foaf/0.1/> . _:a foaf:givenname "Alice" . _:a foaf:family_name "Hacker" . _:b foaf:firstname "Bob" . _:b foaf:surname "Hacker" .
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX vcard: <http://www.w3.org/2001/vcard-rdf/3.0#>
CONSTRUCT { ?x vcard:N _:v .
_:v vcard:givenName ?gname .
_:v vcard:familyName ?fname }
WHERE
{
{ ?x foaf:firstname ?gname } UNION { ?x foaf:givenname ?gname } .
{ ?x foaf:surname ?fname } UNION { ?x foaf:family_name ?fname } .
}
Cette interrogation crée des propriétés vcard correspondant aux informations FOAF :
@prefix vcard: <http://www.w3.org/2001/vcard-rdf/3.0#> . _:v1 vcard:N _:x . _:x vcard:givenName "Alice" . _:x vcard:familyName "Hacker" . _:v2 vcard:N _:z . _:z vcard:givenName "Bob" . _:z vcard:familyName "Hacker" .
L'utilisation de la variable x dans le gabarit, laquelle sera liée ici aux nœuds anonymes avec les étiquettes
_:a et _:b dans les données, crée des étiquettes de nœud anonyme différentes (_:v1 et _:v2)
dans le graphe RDF résultant.
Avec CONSTRUCT, il est possible d'extraire des parties ou la totalité des graphes de
l'ensemble de données RDF cible. Le premier exemple retourne le graphe (s'il existe dans l'ensemble de données) avec
l'étiquette IRI http://example.org/aGraph ; sinon il retourne un graphe vide.
CONSTRUCT { ?s ?p ?o } WHERE { GRAPH <http://example.org/aGraph> { ?s ?p ?o } . }
L'accès au graphe peut être conditionné à d'autres informations. Par exemple, si le graphe par défaut contient des métadonnées à propos des graphes nommés dans l'ensemble de données, alors une interrogation telle que la suivante peut extraire un graphe fondé sur l'information concernant le graphe nommé :
PREFIX dc: <http://purl.org/dc/elements/1.1/>
PREFIX app: <http://example.org/ns#>
CONSTRUCT { ?s ?p ?o } WHERE
{
GRAPH ?g { ?s ?p ?o } .
{ ?g dc:publisher <http://www.w3.org/> } .
{ ?g dc:date ?date } .
FILTER ( app:customDate(?date) > "2005-02-28T00:00:00Z"^^xsd:dateTime ) .
}
où app:customDate identifiait une fonction d'extension pour transformer le
format de données en un terme RDF xsd:dateTime.
[6] |
ConstructQuery |
::= | 'CONSTRUCT' ConstructTemplate |
Les modificateurs de solution d'une interrogation affectent les résultats d'une interrogation CONSTRUCT.
Dans cet exemple, le graphe de sortie du gabarit CONSTRUCT est formé à partir de juste deux des solutions du
filtrage par motif de graphe (graph pattern matching). L'interrogation produit un graphe avec les noms des
personnes des deux premiers sites, trié par visites. Les triplets dans le graphe RDF ne sont pas ordonnés.
@prefix foaf: <http://xmlns.com/foaf/0.1/> . @prefix site: <http://example.org/stats#> . _:a foaf:name "Alice" . _:a site:hits 2349 . _:b foaf:name "Bob" . _:b site:hits 105 . _:c foaf:name "Eve" . _:c site:hits 181 .
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX site: <http://example.org/stats#>
CONSTRUCT { [] foaf:name ?name }
WHERE
{ [] foaf:name ?name ;
site:hits ?hits .
}
ORDER BY desc(?hits)
LIMIT 2
@prefix foaf: <http://xmlns.com/foaf/0.1/> . _:x foaf:name "Alice" . _:y foaf:name "Eve" .
Les applications peuvent utiliser la forme ASK pour tester si un motif d'interrogation a une solution ou non.
Aucune information n'est retournée concernant les solutions d'interrogation possibles, juste qu'il existe ou non une solution.
@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> .
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
ASK { ?x foaf:name "Alice" }
yes
La forme de cet ensemble de résultats dans le format XML des résultats d'interrogation SPARQL donne :
<?xml version="1.0"?>
<sparql xmlns="http://www.w3.org/2005/sparql-results#">
<head></head>
<results>
<boolean>true</boolean>
</results>
</sparql>
Avec les mêmes données, l'interrogation suivante ne retourne aucune correspondance car la variable mbox d'Alice
n'est pas mentionnée.
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
ASK { ?x foaf:name "Alice" ;
foaf:mbox <mailto:alice@work.example> }
no
[8] |
AskQuery |
::= | 'ASK' DatasetClause* WhereClause |
La forme DESCRIBE retourne un seul graphe RDF de résultat contenant des données RDF à propos
de ressources. Ces données ne sont pas prescrites par une interrogation SPARQL, où le client interrogeant aurait à
connaître la structure du RDF dans la source des données, mais elles sont plutôt déterminées par le
processeur d'interrogation SPARQL. Le motif d'interrogation est utilisé pour créer un ensemble de résultat.
La forme DESCRIBE prend chaque ressource identifiée dans une solution, ainsi que toutes les ressources nommées directement
par des adresses IRI, et assemble un seul graphe RDF en prenant une « description » qui peut provenir
de toute information disponible y compris de l'ensemble de données RDF cible. La description est déterminée par le
service d'interrogation. La syntaxe DESCRIBE * est une abréviation pour décrire toutes les variables dans une interrogation.
La clause DESCRIBE elle-même peut prendre des adresses IRI pour identifier les ressources.
L'interrogation DESCRIBE la plus simple consiste juste en une adresse IRI dans la clause DESCRIBE :
DESCRIBE <http://example.org/>
Les ressources à décrire peuvent également être prises dans les liaisons juqu'à une variable d'interrogation dans un ensemble de résultats. Cela permet une description des ressources, qu'elles soient identifiées par des adresses IRI ou par un nœud anonyme dans l'ensemble de données :
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
DESCRIBE ?x
WHERE { ?x foaf:mbox <mailto:alice@org> }
La propriété foaf:mbox est définie comme étant une propriété de fonction symétrique
(inverse function property) dans le vocabulaire FOAF. Si elle était traitée comme telle,
cette interrogation retournerait des informations à propos d'une seule personne au plus. Par contre, si le motif d'interrogation
a plusieurs solutions, les données RDF de chacune sont constituées de l'union de toutes les descriptions de graphe RDF.
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
DESCRIBE ?x
WHERE { ?x foaf:name "Alice" }
Plus d'une adresse IRI ou variable peuvent être données :
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
DESCRIBE ?x ?y <http://example.org/>
WHERE {?x foaf:knows ?y}
Le RDF retourné est déterminé par l'éditeur de l'information. Il s'agit de l'information utile dont dispose le service à propos d'une ressource. Elle peut inclure des informations à propos d'autres ressources : ainsi les données RDF pour un livre peuvent aussi inclure des détails concernant l'auteur.
Une interrogation simple telle que :
PREFIX ent: <http://org.example.com/employees#>
DESCRIBE ?x WHERE { ?x ent:employeeId "1234" }
pourrait retourner une description de l'employé et d'autres détails potentiellement utiles :
@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#> . @prefixrdf: <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 .
comprenant la fermeture de nœud anonyme (blank node closure) de vcard:N du vocabulaire vcard. D'autres mécanismes sont possibles pour décider quelles informations il faut retourner, comme des descriptions liées concises (concise bounded descriptions) [CBD].
Pour un vocabulaire tel que FOAF, où les ressources sont typiquement des nœuds anonymes, retourner suffisamment d'information
pour identifier un nœud tel que le nœud foaf:mbox_sha1sum de type InverseFunctionalProperty ainsi que des informations
telles que le nom et d'autres détails enregistrés serait approprié. Dans l'exemple, la correspondance de la clause WHERE
a été retournée mais ce n'est pas obligatoire.
[7] |
DescribeQuery |
::= | 'DESCRIBE' ( VarOrIRIref+ | '*' ) |
Les clauses FILTER SPARQL restreignent les solutions d'une correspondance de motif de graphe selon
une expression donnée. Spécifiquement, les clauses FILTER éliminent toutes les solutions,
lorsqu'elles sont substituées dans l'expression, qui aboutissent à une valeur booléenne effective de false ou bien
produisent une erreur. Les valeurs booléennes effectives sont définies à la section
11.2.2 Valeurs booléennes effectives et les erreurs à la section
2.3.1 Types d'erreurs
dans la spécification XQuery 1.0 — Un langage d'interrogation XML [XQUERY].
Ces erreurs n'ont pas d'effets hors de l'évaluation de FILTER.
Les littéraux RDF peuvent avoir une adresse IRI de type de données :
@prefix a: <http://www.w3.org/2000/10/annotation-ns#> . @prefix dc: <http://purl.org/dc/elements/1.1/> . _:a a:annotates <http://www.w3.org/TR/rdf-sparql-query/> . _:a dc:date "2004-12-31T19:00:00-05:00" . _:b a:annotates <http://www.w3.org/TR/rdf-sparql-query/> . _:b dc:date "2004-12-31T19:01:00-05:00"^^<http://www.w3.org/2001/XMLSchema#dateTime> .
L'objet du premier triplet dc:date n'a pas d'information de type. Celui du deuxième a le type de données xsd:dateTime.
Les expressions SPARQL sont construites conformément à la grammaire et elles fournissent un accès aux fonctions (nommées par une adresse IRI) et aux fonctions d'opérateurs (invoquées par des mots-clés et des symboles dans la grammaire SPARQL). Les opérateurs SPARQL peuvent être utilisés pour comparer les valeurs de littéraux typés :
PREFIX a: <http://www.w3.org/2000/10/annotation-ns#>
PREFIX dc: <http://purl.org/dc/elements/1.1/>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT ?annot
WHERE { ?annot a:annotates <http://www.w3.org/TR/rdf-sparql-query/> .
?annot dc:date ?date .
FILTER ( ?date > "2005-01-01T00:00:00Z"^^xsd:dateTime ) }
Les opérateurs SPARQL sont listés à la section 11.3 et associés à leurs productions dans la grammaire.
En outre, SPARQL permet d'invoquer des fonctions arbitraires, y compris un sous-ensemble des fonctions de transtypage (casting functions) XPath, listées à la section 11.5. Ces fonctions sont invoquées par leur nom (une adresse IRI) dans une interrogation SPARQL. Par exemple :
... FILTER ( xsd:dateTime(?date) < xsd:dateTime("2005-01-01T00:00:00Z") ) ...
Dans cette section, nous utilisons les conventions d'écriture suivantes :
op:. Les opérateurs XPath n'ont pas
d'espace de noms ; op: est une convention de marquage ;Les fonctions et opérateurs SPARQL agissent sur les termes RDF et les variables SPARQL. Un sous-ensemble de ces fonctions et opérateurs provient des Fonctions et opérateurs XQuery 1.0 et XPath 2.0 [FUNCOP], lesquels ont des arguments et des types de retour à valeur typée XML Schema. Les littéraux typés RDF passés comme arguments à ces fonctions et opérateurs sont convertis (mapped to) en valeurs typées XML Schema avec la valeur de chaîne de la forme lexicale et un type de données atomique correspondant à l'adresse IRI de type de données. À l'inverse, les valeurs typées retournées sont converties en littéraux typés RDF de la même façon.
SPARQL a des opérateurs supplémentaires qui agissent sur des sous-ensembles de termes RDF spécifiques. Dans une référence de type, les termes suivants dénotent un littéral typé avec l'adresse IRI de type de données XML Schema correspondante [XSDT] :
Les termes suivants identifient les types supplémentaires utilisés dans les tests de valeurs SPARQL :
xsd:integer, xsd:decimal, xsd:float et xsd:double ;Les types suivants sont dérivés des types numériques et constituent des arguments valides pour les functions et opérateurs prenant des arguments numériques :
xsd:nonPositiveIntegerxsd:negativeIntegerxsd:longxsd:intxsd:shortxsd:bytexsd:nonNegativeIntegerxsd:unsignedLongxsd:unsignedIntxsd:unsignedShortxsd:unsignedBytexsd:positiveIntegerDes extensions du langage SPARQL peuvent traiter des types supplémentaires comme étant dérivés des types de données XML Schema.
SPARQL offre un sous-ensemble des fonctions et opérateurs définis par XQuery à la section Conversion des opérateurs. La section 2.2.3, Traitement des expressions, de la spécification XQuery 1.0 décrit l'invocation des fonctions XPath. Les règles suivantes soulignent les différences entre les modèles d'exécution et de données de XQuery et SPARQL :
xsd:boolean en utilisant les règles EBV de la section 11.2.2 ;||) ou logical-and
(&&) qui rencontre une erreur produira cette erreur ;true
si l'autre segment est true, et une erreur si l'autre segment est false ;true, et false si l'autre segment est false ;La table de vérité logical-and et logical-or pour vrai (T), faux (F) et en erreur (E) est la suivante :
| A | B | A || B | A && B |
|---|---|---|---|
| T | T | T | T |
| T | F | T | F |
| F | T | T | F |
| F | F | F | F |
| T | E | T | E |
| E | T | T | E |
| F | E | E | F |
| E | F | E | F |
| E | E | E | E |
SPARQL définit une syntaxe pour invoquer les fonctions et les opérateurs sur une liste d'arguments. Ceux-ci sont invoqués comme suit :
Si l'une de ces étapes échoue, l'invocation génère une erreur. Les effets des erreurs sont définis dans la section 11.2 Évaluation des filtres.
La valeur booléenne effective (effective boolean value), ou valeur EBV, est utilisée pour
calculer les arguments des fonctions logiques logical-and, logical-or et
fn:not, ainsi que pour évaluer le résultat d'une
expression FILTER.
Les règles de valeur booléenne effective XQuery reposent sur la
définition de la fonction fn:boolean XPath.
Les règles suivantes reflètent celles de fn:boolean appliquées aux types d'argument présents dans les
interrogations SPARQL :
xsd:boolean ou de type numérique
est false si la forme lexicale n'est pas valide pour ce type de données (par exemple, "abc"^^xsd:integer) ;xsd:boolean, la valeur EBV est celle de cet argument ;xsd:string, la valeur EBV est false
si la valeur d'opérande a une longueur nulle ; sinon la valeur EBV est true ;false
si la valeur d'opérande est "NaN" ou égale numériquement zéro ; sinon la valeur EBV est true ;Une valeur EBV de true est représentée par un littéral typé
avec un type de données de xsd:boolean et une valeur lexicale de "true" ; une valeur EBV de false
est représentée par un littéral typé avec un type de données de xsd:boolean
et une valeur lexicale de "false".
La grammaire SPARQL identifie un ensemble d'opérateurs (par exemple, &&,
*, isIRI) utilisés pour construire des contraintes. Le tableau suivant associe
chacune de ces productions grammaticales aux opérandes appropriés et une fonction opératrice définie soit dans la spécification
Fonctions et opérateurs XQuery 1.0 et XPath 2.0
[FUNCOP], soit dans les opérateurs SPARQL indiqués à la section 11.4.
À la sélection de la définition d'opérateur pour un ensemble de paramètres donné, c'est la définition avec les paramètres les plus
spécifiques qui s'applique. Ainsi, pour l'évaluation de xsd:integer = xsd:signedInt, la définition de l'opérateur =
avec deux paramètres numériques s'applique, plutôt que celle avec deux termes RDF.
Le tableau est organisé de manière à ce que le candidat supérieur le plus viable soit le plus spécifique. Les opérateurs invoqués
sans les opérandes appropriés produisent une erreur de type.
SPARQL suit le schéma de XPath pour les promotions de type numérique et la substitution de sous-type
pour les arguments des opérateurs numériques. Les règles de conversion des opérateurs XPath
pour les opérandes numériques (xsd:integer, xsd:decimal, xsd:float,
xsd:double et les types dérivés d'un type numérique) s'appliquent également
aux opérateurs SPARQL (cf. la spécification
Langage de chemin XML (XPath) 2.0
[XPATH20] pour les définitions des
promotions de type numérique et de la
substitution de sous-type).
Certains opérateurs sont associés à des expressions de fonction imbriquée, ainsi fn:not(op:numeric-equal(A, B)).
Notez que, selon les définitions XPath, fn:not et op:numeric-equal produisent une erreur
si leur argument est une erreur.
L'interclassement (collation) de la fonction fn:compare est
défini par XPath et identifié par
http://www.w3.org/2005/xpath-functions/collation/codepoint. Cet interclassement permet une comparaison de chaînes
fondée sur les valeurs de point de code (codepoint). L'équivalence de la chaîne de points de code
peut être testée par l'équivalence des termes RDF.
| Opérateur | Type(A) | Fonction | Type du résultat | |
|---|---|---|---|---|
| Opérateurs unaires XQuery | ||||
| ! A | xsd:boolean (EBV) | fn:not(A) | xsd:boolean | |
| + A | numérique | op:numeric-unary-plus(A) | numérique | |
| - A | numérique | op:numeric-unary-minus(A) | numérique | |
| Tests SPARQL, définis à la section 11.4 | ||||
| BOUND(A) | variable | bound(A) | xsd:boolean | |
| isIRI(A) isURI(A) |
terme RDF | isIRI(A) | xsd:boolean | |
| isBLANK(A) | terme RDF | isBlank(A) | xsd:boolean | |
| isLITERAL(A) | terme RDF | isLiteral(A) | xsd:boolean | |
| Accesseurs SPARQL, définis à la section 11.4 | ||||
| STR(A) | littéral | str(A) | littéral simple | |
| STR(A) | IRI | str(A) | littéral simple | |
| LANG(A) | littéral | lang(A) | littéral simple | |
| DATATYPE(A) | littéral typé | datatype(A) | IRI | |
| DATATYPE(A) | littéral simple | datatype(A) | IRI | |
| Opérateur | Type(A) | Type(B) | Fonction | Type du résultat |
|---|---|---|---|---|
| Connecteurs logiques, définis à la section 11.4 | ||||
| A || B | xsd:boolean (EBV) | xsd:boolean (EBV) | logical-or(A, B) | xsd:boolean |
| A && B | xsd:boolean (EBV) | xsd:boolean (EBV) | logical-and(A, B) | xsd:boolean |
| Tests XPath | ||||
| A = B | numérique | numérique | op:numeric-equal(A, B) | xsd:boolean |
| A = B | littéral simple | littéral simple | op:numeric-equal(fn:compare(A, B), 0) | xsd:boolean |
| A = B | xsd:string | xsd:string | op:numeric-equal(fn:compare(STR(A), STR(B)), 0) | xsd:boolean |
| A = B | xsd:boolean | xsd:boolean | op:boolean-equal(A, B) | xsd:boolean |
| A = B | xsd:dateTime | xsd:dateTime | op:dateTime-equal(A, B) | xsd:boolean |
| A != B | numérique | numérique | fn:not(op:numeric-equal(A, B)) | xsd:boolean |
| A != B | littéral simple | littéral simple | fn:not(op:numeric-equal(fn:compare(A, B), 0)) | xsd:boolean |
| A != B | xsd:string | xsd:string | fn:not(op:numeric-equal(fn:compare(STR(A), STR(B)), 0)) | xsd:boolean |
| A != B | xsd:boolean | xsd:boolean | fn:not(op:boolean-equal(A, B)) | xsd:boolean |
| A != B | xsd:dateTime | xsd:dateTime | fn:not(op:dateTime-equal(A, B)) | xsd:boolean |
| A < B | numérique | numérique | op:numeric-less-than(A, B) | xsd:boolean |
| A < B | littéral simple | littéral simple | op:numeric-equal(fn:compare(A, B), -1) | xsd:boolean |
| A < B | xsd:string | xsd:string | op:numeric-equal(fn:compare(STR(A), STR(B)), -1) | xsd:boolean |
| A < B | xsd:boolean | xsd:boolean | op:boolean-less-than(A, B) | xsd:boolean |
| A < B | xsd:dateTime | xsd:dateTime | op:dateTime-less-than(A, B) | xsd:boolean |
| A > B | numérique | numérique | op:numeric-greater-than(A, B) | xsd:boolean |
| A > B | littéral simple | littéral simple | op:numeric-equal(fn:compare(A, B), 1) | xsd:boolean |
| A > B | xsd:string | xsd:string | op:numeric-equal(fn:compare(STR(A), STR(B)), 1) | xsd:boolean |
| A > B | xsd:boolean | xsd:boolean | op:boolean-greater-than(A, B) | xsd:boolean |
| A > B | xsd:dateTime | xsd:dateTime | op:dateTime-greater-than(A, B) | xsd:boolean |
| A <= B | numérique | numérique | logical-or(op:numeric-less-than(A, B), op:numeric-equal(A, B)) | xsd:boolean |
| A <= B | littéral simple | littéral simple | fn:not(op:numeric-equal(fn:compare(A, B), 1)) | xsd:boolean |
| A <= B | xsd:string | xsd:string | fn:not(op:numeric-equal(fn:compare(STR(A), STR(B)), 1)) | xsd:boolean |
| A <= B | xsd:boolean | xsd:boolean | fn:not(op:boolean-greater-than(A, B)) | xsd:boolean |
| A <= B | xsd:dateTime | xsd:dateTime | fn:not(op:dateTime-greater-than(A, B)) | xsd:boolean |
| A >= B | numérique | numérique | logical-or(op:numeric-greater-than(A, B), op:numeric-equal(A, B)) | xsd:boolean |
| A >= B | littéral simple | littéral simple | fn:not(op:numeric-equal(fn:compare(A, B), -1)) | xsd:boolean |
| A >= B | xsd:string | xsd:string | fn:not(op:numeric-equal(fn:compare(STR(A), STR(B)), -1)) | xsd:boolean |
| A >= B | xsd:boolean | xsd:boolean | fn:not(op:boolean-less-than(A, B)) | xsd:boolean |
| A >= B | xsd:dateTime | xsd:dateTime | fn:not(op:dateTime-less-than(A, B)) | xsd:boolean |
| Arithmétique XPath | ||||
| A * B | numérique | numérique | op:numeric-multiply(A, B) | numérique |
| A / B | numérique | numérique | op:numeric-divide(A, B) | numérique; but xsd:decimal if both operands are xsd:integer |
| A + B | numérique | numérique | op:numeric-add(A, B) | numérique |
| A - B | numérique | numérique | op:numeric-subtract(A, B) | numérique |
| Tests SPARQL, définis à la section 11.4 | ||||
| A = B | terme RDF | terme RDF | RDFterm-equal(A, B) | xsd:boolean |
| A != B | terme RDF | terme RDF | fn:not(RDFterm-equal(A, B)) | xsd:boolean |
| sameTERM(A) | terme RDF | terme RDF | sameTerm(A, B) | xsd:boolean |
| langMATCHES(A, B) | littéral simple | littéral simple | langMatches(A, B) | xsd:boolean |
| REGEX(STRING, PATTERN) | littéral simple | littéral simple | fn:matches(STRING, PATTERN) | xsd:boolean |
| Opérateur | Type(A) | Type(B) | Type(C) | Fonction | Type du résultat |
|---|---|---|---|---|---|
| Tests SPARQL, définis à la section 11.4 | |||||
| REGEX(STRING, PATTERN, FLAGS) | littéral simple | littéral simple | littéral simple | fn:matches(STRING, PATTERN, FLAGS) | xsd:boolean |
Les arguments de fonction de type xsd:boolean signalés par "(EBV)" sont forcés à xsd:boolean en évaluant la valeur booléenne effective de l'argument.
Les extensions du langage SPARQL peuvent fournir des conversions supplémentaires entre les opérateurs et les fonctions opératrices ; cela revient à ajouter des rangées aux tableaux ci-dessus. Aucun opérateur supplémentaire ne peut produire un résultat qui remplace un résultat, hormis une erreur de type, dans la sémantique définie précédemment. La conséquence de cette règle est que les extensions SPARQL produiront au moins les mêmes solutions qu'une mise en œuvre non étendue et qu'elles pourront produire, pour certaines interrogations, plus de solutions.
Les conversions supplémentaires de l'opérateur "<" sont censées contrôler l'ordre relatif des opérandes, spécifiquement lorsqu'il est utilisé
dans une clause ORDER BY.
Cette section définit les opérateurs introduits par le langage d'interrogation SPARQL. Les exemples montrent l'action des opérateurs tels qu'invoqués par les structures grammaticales appropriées.
xsd:booleanbound(variablevar)
Retourne true si le paramètre var est lié à une valeur ; retourne false sinon.
Les variables ayant les valeurs NaN ou INF sont considérées comme liées.
Données :
@prefix foaf: <http://xmlns.com/foaf/0.1/> . @prefix dc: <http://purl.org/dc/elements/1.1/> . @prefix xsd: <http://www.w3.org/2001/XMLSchema#> . _:a foaf:givenName "Alice". _:b foaf:givenName "Bob" . _:b dc:date "2005-04-04T04:04:04Z"^^xsd:dateTime .
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX dc: <http://purl.org/dc/elements/1.1/>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT ?name
WHERE { ?x foaf:givenName ?givenName .
OPTIONAL { ?x dc:date ?date } .
FILTER ( bound(?date) ) }
Résultat d'interrogation :
| givenName |
|---|
| "Bob" |
On peut tester qu'un motif de graphe n'est pas exprimé en définissant un motif de graphe OPTIONAL
qui introduit une variable et en vérifiant que la variable n'est pas liée (not bound).
C'est ce qu'on appelle « négation par l'échec » (negation as failure) en programmation logique.
Cette interrogation filtre les personnes avec un nom (name) mais sans date exprimée :
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX dc: <http://purl.org/dc/elements/1.1/>
SELECT ?name
WHERE { ?x foaf:givenName ?name .
OPTIONAL { ?x dc:date ?date } .
FILTER (!bound(?date)) }
Résultat d'interrogation :
| name |
|---|
| "Alice" |
Puisque la date (dc:date) de Bob était connue, "Bob" ne constituait pas une solution de l'interrogation.
xsd:booleanisIRI(terme RDFterm)xsd:booleanisURI(terme RDFterm)
Retourne true si le paramètre term est de type IRI ; retourne false sinon.
isURI est une orthographe alternative pour l'opérateur isIRI.
@prefix foaf: <http://xmlns.com/foaf/0.1/> . _:a foaf:name "Alice". _:a foaf:mbox <mailto:alice@work.example> . _:b foaf:name "Bob" . _:b foaf:mbox "bob@work.example" .
Cette interrogation filtre les personnes avec un nom (name) et une boîte aux lettres (mbox) qui est une adresse IRI :
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name ?mbox
WHERE { ?x foaf:name ?name ;
foaf:mbox ?mbox .
FILTER isIRI(?mbox) }
Résultat d'interrogation :
| name | mbox |
|---|---|
| "Alice" | <mailto:alice@work.example> |
xsd:booleanisBlank(terme RDFterm)
Retourne true si le paramètre term est un nœud anonyme ; retourne false sinon.
@prefix a: <http://www.w3.org/2000/10/annotation-ns#> . @prefix dc: <http://purl.org/dc/elements/1.1/> . @prefix foaf: <http://xmlns.com/foaf/0.1/> . _:a a:annotates <http://www.w3.org/TR/rdf-sparql-query/> . _:a dc:creator "Alice B. Toeclips" . _:b a:annotates <http://www.w3.org/TR/rdf-sparql-query/> . _:b dc:creator _:c . _:c foaf:given "Bob". _:c foaf:family "Smith".
Cette interrogation filtre les personnes avec une date (dc:creator) qui utilisent des prédicats du vocabulaire FOAF
pour exprimer leur nom.
PREFIX a: <http://www.w3.org/2000/10/annotation-ns#>
PREFIX dc: <http://purl.org/dc/elements/1.1/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?given ?family
WHERE { ?annot a:annotates <http://www.w3.org/TR/rdf-sparql-query/> .
?annot dc:creator ?c .
OPTIONAL { ?c foaf:given ?given ; foaf:family ?family } .
FILTER isBlank(?c)
}
Résultat d'interrogation :
| given | family |
|---|---|
| "Bob" | "Smith" |
Dans cet exemple, il y avait deux objets de prédicats foaf:knows mais un seul (_:c) était un nœud anonyme.
xsd:booleanisLiteral(terme RDFterm)
Retourne true si le paramètre term est un littéral ; retourne false sinon.
@prefix foaf: <http://xmlns.com/foaf/0.1/> . _:a foaf:name "Alice". _:a foaf:mbox <mailto:alice@work.example> . _:b foaf:name "Bob" . _:b foaf:mbox "bob@work.example" .
Cette interrogation est similaire à celle de la section 11.4.2 sauf qu'elle filtre les personnes avec un nom
(name) et une boîte aux lettres (mbox) qui est un littéral. Elle pourrait servir à repérer des données erronées
(foaf:mbox devrait seulement avoir une adresse IRI comme objet).
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name ?mbox
WHERE { ?x foaf:name ?name ;
foaf:mbox ?mbox .
FILTER isLiteral(?mbox) }
Résultat d'interrogation :
| name | mbox |
|---|---|
| "Bob" | "bob@work.example" |
littéral simplestr(littéralltrl)littéral simplestr(IRIrsrc)
Retourne la forme lexicale du paramètre ltrl (un littéral) ;
retourne la représentation en points de code du paramètre rsrc (une adresse IRI).
C'est utile pour examiner les parties d'une adresse IRI, par exemple le nom d'hôte.
@prefix foaf: <http://xmlns.com/foaf/0.1/> . _:a foaf:name "Alice". _:a foaf:mbox <mailto:alice@work.example> . _:b foaf:name "Bob" . _:b foaf:mbox <mailto:bob@home.example> .
Cette interrogation sélectionne l'ensemble des personnes utilisant une adresse en work.example dans leur profil FOAF :
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name ?mbox
WHERE { ?x foaf:name ?name ;
foaf:mbox ?mbox .
FILTER regex(str(?mbox), "@work.example") }
Résultat d'interrogation :
| name | mbox |
|---|---|
| "Alice" | <mailto:alice@work.example> |
littéral simplelang(littéralltrl)
Retourne l'étiquette de langue du paramètre ltrl, le cas échéant ; retourne ""
si ltrl n'a pas d'étiquette de langue. Notez que le modèle de données RDF
n'inclut pas de littéraux avec étiquette de langue vide.
@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> .
Cette interrogation trouve le nom (foaf:name) espagnol et la boîte aux lettres (foaf:mbox) :
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name ?mbox
WHERE { ?x foaf:name ?name ;
foaf:mbox ?mbox .
FILTER ( lang(?name) = "ES" ) }
Résultat d'interrogation :
| name | mbox |
|---|---|
| "Roberto"@ES | <mailto:bob@work.example> |
IRIdatatype(littéral typétypedLit)IRIdatatype(littéral simplesimpleLit)
Retourne l'adresse IRI de type de données du paramètre typedLit ;
retourne un type xsd:string si le paramètre est un littéral simple.
@prefix foaf: <http://xmlns.com/foaf/0.1/> . @prefix eg: <http://biometrics.example/ns#> . @prefix xsd: <http://www.w3.org/2001/XMLSchema#> . _:a foaf:name "Alice". _:a eg:shoeSize "9.5"^^xsd:float . _:b foaf:name "Bob". _:b eg:shoeSize "42"^^xsd:integer .
Cette interrogation trouve le nom (foaf:name) et la taille de chaussure (foaf:shoeSize) des personnes,
la taille étant un entier :
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX eg: <http://biometrics.example/ns#>
SELECT ?name ?shoeSize
WHERE { ?x foaf:name ?name ; eg:shoeSize ?shoeSize .
FILTER ( datatype(?shoeSize) = xsd:integer ) }
Résultat d'interrogation :
| name | shoeSize |
|---|---|
| "Bob" | 42 |
xsd:booleanxsd:booleanleft||xsd:booleanright
Retourne un OU logique des paramètres left et right. Notez que la fonction logical-or
agit sur la valeur booléenne effective de ses arguments.
Remarque : cf. la section 11.2 Évaluation des filtres pour le traitement des erreurs de
l'opérateur ||.
xsd:booleanxsd:booleanleft&&xsd:booleanright
Retourne un ET logique des paramètres left et right. Notez que la fonction logical-and
agit sur la valeur booléenne effective de ses arguments.
Remarque : cf. la section 11.2 Évaluation des filtres pour le traitement des erreurs de
l'opérateur &&.
xsd:booleanterme RDFterm1=terme RDFterm2
Retourne true si les paramètres term1 et term2 sont le même terme RDF
selon la définition de la spécification
Cadre de description des ressources (RDF) — Concepts et syntaxe abstraite
[CONCEPTS] ; produit une erreur de type si les deux arguments sont des littéraux mais pas le même
terme RDF 1 ;
retourne false sinon. Les paramètres term1 et term2 sont les mêmes si l'une des propositions suivantes
est vraie :
term1 et term2 sont des
adresses IRI équivalentes comme définies à la section
6.4 Références URI RDF de
[CONCEPTS] ;term1 et term2 sont des
littéraux équivalents comme définis à la section
6.5.1 Égalité des littéraux de
[CONCEPTS] ;term1 et term2 sont le même
nœud anonyme comme décrit à la section
6.6 Nœuds anonymes de
[CONCEPTS].@prefix foaf: <http://xmlns.com/foaf/0.1/> . _:a foaf:name "Alice". _:a foaf:mbox <mailto:alice@work.example> . _:b foaf:name "Ms A.". _:b foaf:mbox <mailto:alice@work.example> .
Cette interrogation trouve les personnes qui ont plusieurs triplets foaf:name :
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name1 ?name2
WHERE { ?x foaf:name ?name1 ;
foaf:mbox ?mbox1 .
?y foaf:name ?name2 ;
foaf:mbox ?mbox2 .
FILTER (?mbox1 = ?mbox2 && ?name1 != ?name2)
}
Résultat d'interrogation :
| name1 | name2 |
|---|---|
| "Alice" | "Ms A." |
| "Ms A." | "Alice" |
Dans l'interrogation suivante pour des documents annotés le jour de l'an (2004 ou 2005), les termes RDF ne sont pas les mêmes mais ont des valeurs équivalentes :
@prefix a: <http://www.w3.org/2000/10/annotation-ns#> . @prefix dc: <http://purl.org/dc/elements/1.1/> . _:b a:annotates <http://www.w3.org/TR/rdf-sparql-query/> . _:b dc:date "2004-12-31T19:00:00-05:00"^^<http://www.w3.org/2001/XMLSchema#dateTime> .
PREFIX a: <http://www.w3.org/2000/10/annotation-ns#>
PREFIX dc: <http://purl.org/dc/elements/1.1/>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT ?annotates
WHERE { ?annot a:annotates ?annotates .
?annot dc:date ?date .
FILTER ( ?date = xsd:dateTime("2005-01-01T00:00:00Z") ) }
| annotates |
|---|
| <http://www.w3.org/TR/rdf-sparql-query/> |
[1] L'invocation de la fonction RDFterm-equal sur deux littéraux typés teste l'équivalence des valeurs. Une mise en œuvre étendue peut gérer des types de données supplémentaires. Une mise en œuvre traitant une interrogation qui teste l'équivalence des valeurs sur des types de données non gérés (et des formes lexicales et des adresses IRI de type de données non identiques) retourne une erreur, indiquant par-là qu'elle est incapable de déterminer si les valeurs sont équivalentes ou non. Ainsi, une mise en œuvre non étendue produira une erreur en testant
"iiii"^^my:romanNumeral = "iv"^^my:romanNumeral, ou bien"iiii"^^my:romanNumeral != "iv"^^my:romanNumeral.
xsd:booleansameTerm(terme RDFterm1,terme RDFterm2)
Retourne true si les paramètres term1 et term2 sont le même terme RDF
comme défini dans la spécification
Cadre de description des ressources (RDF) — Concepts et syntaxe abstraite
[CONCEPTS] ; retourne false sinon.
@prefix foaf: <http://xmlns.com/foaf/0.1/> . _:a foaf:name "Alice". _:a foaf:mbox <mailto:alice@work.example> . _:b foaf:name "Ms A.". _:b foaf:mbox <mailto:alice@work.example> .
Cette interrogation trouve les personnes qui ont plusieurs triplets foaf:name :
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name1 ?name2
WHERE { ?x foaf:name ?name1 ;
foaf:mbox ?mbox1 .
?y foaf:name ?name2 ;
foaf:mbox ?mbox2 .
FILTER (sameTerm(?mbox1, ?mbox2) && !sameTerm(?name1, ?name2))
}
Résultat d'interrogation :
| name1 | name2 |
|---|---|
| "Alice" | "Ms A." |
| "Ms A." | "Alice" |
À la différence de RDFterm-equal, la fonction sameTerm
peut être utilisée pour tester la non-équivalence de littéraux typés
ayant des types de données non gérés :
@prefix : <http://example.org/WMterms#> . @prefix t: <http://example.org/types#> . _:c1 :label "Container 1" . _:c1 :weight "100"^^t:kilos . _:c1 :displacement "100"^^t:liters . _:c2 :label "Container 2" . _:c2 :weight "100"^^t:kilos . _:c2 :displacement "85"^^t:liters . _:c3 :label "Container 3" . _:c3 :weight "85"^^t:kilos . _:c3 :displacement "85"^^t:liters .
PREFIX : <http://example.org/WMterms#>
PREFIX t: <http://example.org/types#>
SELECT ?aLabel1 ?bLabel
WHERE { ?a :label ?aLabel .
?a :weight ?aWeight .
?a :displacement ?aDisp .
?b :label ?bLabel .
?b :weight ?bWeight .
?b :displacement ?bDisp .
FILTER ( sameTerm(?aWeight, ?bWeight) && !sameTerm(?aDisp, ?bDisp) }
| aLabel | bLabel |
|---|---|
| "Container 1" | "Container 2" |
| "Container 2" | "Container 1" |
Le test des boîtes avec le même poids peut aussi être réalisé avec l'opérateur "="
(cf. RDFterm-equal) puisque le test "100"^^t:kilos = "85"^^t:kilos
aboutira à une erreur, éliminant ainsi cette solution potentielle.
xsd:booleanlangMatches(littéral simplelanguage-tag,littéral simplelanguage-range)
Retourne true si le premier argument language-tag correspond au deuxième argument language-range
selon le schéma de filtrage de base défini dans [RFC4647], section 3.3.1. L'argument language-range
est une étendue de langue de base selon le RFC Correspondance des étiquettes de langue
[RFC4647], section 2.1. Un argument language-range de "*" filtre toute chaîne language-tag non vide.
@prefix dc: <http://purl.org/dc/elements/1.1/> . _:a dc:title "That Seventies Show"@en . _:a dc:title "Cette série des années soixante-dix"@fr . _:a dc:title "Cette série des années septante"@fr-BE . _:b dc:title "Il Buono, il Bruto, il Cattivo" .
Cette interrogation utilise les fonctions langMatches et lang (décrites à la section 11.2.3.8)
pour trouver les titres en français de la série anglaise intitulée « That Seventies Show » :
PREFIX dc: <http://purl.org/dc/elements/1.1/>
SELECT ?title
WHERE { ?x dc:title "That Seventies Show"@en ;
dc:title ?title .
FILTER langMatches( lang(?title), "FR" ) }
Résultat d'interrogation :
| title |
|---|
| "Cette série des années soixante-dix"@fr |
| "Cette série des années septante"@fr-BE |
L'idiome langMatches( lang( ?v ), "*" ) ne filtrera pas les littéraux sans étiquette de langue puisque lang( ?v )
retournera une chaîne vide, donc :
PREFIX dc: <http://purl.org/dc/elements/1.1/>
SELECT ?title
WHERE { ?x dc:title ?title .
FILTER langMatches( lang(?title), "*" ) }
signalera tous les titres avec une étiquette de langue :
| title |
|---|
| "That Seventies Show"@en |
| "Cette série des années soixante-dix"@fr |
| "Cette série des années septante"@fr-BE |
xsd:booleanregex(littéral simpletext,littéral simplepattern)xsd:booleanregex(littéral simpletext,littéral simplepattern,littéral simpleflags)
Invoque la fonction XPath fn:matches pour filtrer
l'argument text par rapport à un motif d'expression rationnelle (argument pattern). Le langage d'expression rationnelle
est défini dans les Fonctions et opérateurs XQuery 1.0 et XPath 2.0, à la section
7.6.1 Syntaxe des expressions rationnelles
[FUNCOP].
@prefix foaf: <http://xmlns.com/foaf/0.1/> . _:a foaf:name "Alice". _:b foaf:name "Bob" .
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name
WHERE { ?x foaf:name ?name
FILTER regex(?name, "^ali", "i") }
Résultat d'interrogation :
| name |
|---|
| "Alice" |
SPARQL importe un sous-ensemble des fonctions constructrices (constructor functions) XPath définies dans les Fonctions et opérateurs XQuery 1.0 et XPath 2.0 [FUNCOP], section 17.1 Forçage de types primitifs à types primitifs. Les constructeurs SPARQL comprennent tous les constructeurs XPath pour les types de données d'opérandes SPARQL plus les types de données supplémentaires imposés par le modèle de données RDF. Dans SPARQL, le transtypage (casting) s'effectue en appelant une fonction constructrice pour le type cible sur un opérande du type source.
XPath définit seulement le forçage d'un seul type de données XML Schema à un autre. Les forçages restants sont définis comme suit :
xsd:string produit un littéral typé
avec une valeur lexicale constituée des points de code composant l'adresse IRI et un type de données de xsd:string ;xsd:string avec la valeur de chaîne égale
à la valeur lexicale du littéral du type de données cible.Le tableau ci-dessous récapitule les opérations de transtypage toujours permises (Y),
jamais permises (N) et dépendantes de la valeur lexicale (M). Par exemple,
une opération de transtypage d'un type xsd:string (première rangée) vers un type xsd:float (deuxième colonne)
dépend de la valeur lexicale (M).
bool = xsd:boolean
dbl = xsd:double
flt = xsd:float
dec = xsd:decimal
int = xsd:integer
dT = xsd:dateTime
str = xsd:string
IRI = IRI
ltrl = littéral simple
| De \ À | str | flt | dbl | dec | int | dT | bool |
|---|---|---|---|---|---|---|---|
| str | Y | M | M | M | M | M | M |
| flt | Y | Y | Y | M | M | N | Y |
| dbl | Y | Y | Y | M | M | N | Y |
| dec | Y | Y | Y | Y | Y | N | Y |
| int | Y | Y | Y | Y | Y | N | Y |
| dT | Y | N | N | N | N | Y | N |
| bool | Y | Y | Y | Y | Y | N | Y |
| IRI | Y | N | N | N | N | N | N |
| ltrl | Y | M | M | M | M | M | M |
Une règle de grammaire PrimaryExpression peut consister en un appel à une fonction d'extension nommée par une adresse IRI. Une fonction d'extension reçoit un certain nombre de termes RDF en arguments et retourne un terme RDF. La sémantique de ces fonctions est définie par l'adresse IRI qui identifie la fonction.
L'interopérabilité des interrogations SPARQL utilisant des fonctions d'extension sera vraisemblablement limitée.
Comme exemple, prenons une fonction appelée func:even :
xsd:booleanfunc:even(numériquevalue)
Cette fonction serait invoquée dans un filtre (FILTER) ainsi :
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX func: <http://example.org/functions#>
SELECT ?name ?id
WHERE { ?x foaf:name ?name ;
func:empId ?id .
FILTER (func:even(?id)) }Comme deuxième exemple, prenons une fonction aGeo:distance qui calcule la distance entre deux points, utilisée ici pour trouver
des lieux près de Grenoble :
xsd:doubleaGeo:distance(numériquex1,numériquey1,numériquex2,numériquey2)
PREFIX aGeo: <http://example.org/geo#>
SELECT ?neighbor
WHERE { ?a aGeo:placeName "Grenoble" .
?a aGeo:location ?axLoc .
?a aGeo:location ?ayLoc .
?b aGeo:placeName ?neighbor .
?b aGeo:location ?bxLoc .
?b aGeo:location ?byLoc .
FILTER ( aGeo:distance(?axLoc, ?ayLoc, ?bxLoc, ?byLoc) < 10 ) .
}
On pourrait utiliser une fonction d'extension pour tester un type de données d'application non géré par la spécification SPARQL
de base ; ce pourrait être une transformation entre des formats de types de données, par exemple, vers un terme RDF dateTime
XSD depuis un autre format de date.
Cette section définit le comportement correct pour l'évaluation de motifs de graphe et de modificateurs de solution, en fonction d'une chaîne d'interrogation et d'un ensemble de données RDF. Cela n'implique pas qu'une mise en œuvre SPARQL doive utiliser le processus défini ici.
L'exécution d'une interrogation SPARQL est définie par une série d'étapes, commençant à l'interrogation SPARQL en tant que chaîne, en transformant cette chaîne en une forme de syntaxe abstraite, puis en transformant la syntaxe abstraite en une interrogation abstraite SPARQL comprenant des opérateurs de l'algèbre SPARQL. Cette interrogation abstraite est alors évaluée sur un ensemble de données RDF.
SPARQL est défini en fonction d'adresses IRI [RFC3987]. Les adresses IRI constituent un sous-ensemble des références URI RDF qui omet les espaces.
Soit I l'ensemble de toutes les adresses IRI ;
soit RDF-L l'ensemble de tous les littéraux RDF ;
soit RDF-B l'ensemble de tous les nœuds anonymes
dans les graphes RDF.
L'ensemble des termes RDF, RDF-T, est : I union RDF-L union RDF-B.
Cette définition d'un terme RDF rassemble plusieurs notions de base du modèle de données RDF, toutefois mises à jour pour indiquer des adresses IRI au lieu de références URI RDF.
Un ensemble de données RDF est un ensemble tel que :
{ G, (<u1>, G1), (<u2>, G2), ..., (<un>, Gn) }
où G et chaque Gi sont des graphes, et chaque <ui> est une adresse IRI. Chaque <ui>
est distinct.
G est dit le graphe par défaut. (<ui>, Gi) sont dits des graphes nommés.
Le graphe actif est le graphe de l'ensemble de données utilisé pour le filtrage des motifs de graphe élémentaires.
Une variable d'interrogation est un membre de l'ensemble V, où V est infini et disjoint de l'ensemble RDF-T.
Un motif de triplet est membre de l'ensemble :
(RDF-T union V) x (I union V) x (RDF-T union V)
Cette définition du motif de triplet inclut les sujets littéraux. Voici ce que fait remarquer le groupe de travail RDF-core.
« [Le groupe de travail RDF core] remarquait ne voir aucune objection à ce que les littéraux soient des sujets et un prochain groupe de travail avec une charte moins restrictive pourrait étendre les syntaxes pour admettre les littéraux comme sujets de déclarations. »
Du fait que les graphes RDF ne peuvent pas contenir de sujets littéraux, tout motif de triplet SPARQL avec un littéral pour sujet échouera à correspondre à un graphe RDF.
Un motif de graphe élémentaire est un ensemble de motifs de triplet.
Le motif de graphe vide est un motif de graphe élémentaire qui est l'ensemble vide.
Une application de solution est une application d'un ensemble de variables vers un ensemble de termes RDF. Nous employons le terme « solution » là où cela est clair.
Une application de solution, μ, est une fonction partielle μ : V → T.
Le domaine de définition (domain) de μ, dom(μ), est le sous-ensemble de V où μ est définie.
Une séquence de solutions est une liste de solutions éventuellement non ordonnées.
Un modificateur de séquence de solutions est l'un des modificateurs suivants :
Cette section définit le processus de conversion des motifs de graphe et des modificateurs de solution dans une chaîne d'interrogation SPARQL en une expression algébrique SPARQL.
Après l'analyse d'une chaîne d'interrogation SPARQL et l'application des abréviations pour les adresses IRI et les motifs de triplet indiquée à la section 4, on obtient un arbre de syntaxe abstrait composé de :
| Motifs | Modificateurs | Formes d'interrogation |
|---|---|---|
| termes RDF | DISTINCT | SELECT |
| motifs de triplet | REDUCED | CONSTRUCT |
| Motifs de graphe élémentaires | PROJECT | DESCRIBE |
| Groupes | ORDER BY | ASK |
| OPTIONAL | LIMIT | |
| UNION | OFFSET | |
| GRAPH | ||
| FILTER |
Le résultat de la conversion de cet arbre de syntaxe abstrait est une interrogation SPARQL qui utilise les symboles algébriques SPARQL suivants :
| Motif de graphe | Modificateurs de solution |
|---|---|
| BGP | ToList |
| Join | OrderBy |
| LeftJoin | Project |
| Filter | Distinct |
| Union | Reduced |
| Graph | Slice |
Slice est la combinaison des modificateurs OFFSET et LIMIT ; mod représente l'un
des modificateurs de solution.
ToList est utilisé là où se produit la conversion des résultats du filtrage des motifs de graphe en séquences.
Une interrogation abstraite SPARQL est un uplet (tuple) (E, DS, R) où :
Cette section décrit le processus de traduction d'un motif de graphe SPARQL en une expression algébrique SPARQL. Après la traduction des abréviations syntaxiques pour les adresses IRI et les motifs de triplet, il transforme récursivement les formes syntaxiques en expressions algébriques :
OPTIONAL { { ... FILTER ( ... ?x ... ) } }.
Cela est illustré par deux cas d'utilisation non normatifs :
D'abord, développer les abréviations pour les adresses IRI et les motifs de triplet données à la section 4.
La clause WhereClause est constituée
d'un motif GroupGraphPattern comprenant les formes suivantes :
Chacune est traduite selon la procédure suivante :
Transform(forme syntaxique)
S'il s'agit de la forme
TriplesBlock
Le résultat est BGP(liste de motifs de triplet)
S'il s'agit de la forme
GroupOrUnionGraphPattern
Soit A := non défini
Pour chaque élément G dans le GroupOrUnionGraphPattern
Si A n'est pas défini
A := Transform(G)
Sinon
A := Union(A, Transform(G))
Le résultat est A
S'il s'agit de la forme
GraphGraphPattern
Si la forme est GRAPH IRI GroupGraphPattern
Le résultat est Graph(IRI, Transform(GroupGraphPattern))
Si la forme est GRAPH Var GroupGraphPattern
Le résultat est Graph(Var, Transform(GroupGraphPattern))
S'il s'agit de la forme
GroupGraphPatternNous introduisons les symboles suivants :
- Join(Pattern, Pattern)
- LeftJoin(Pattern, Pattern, expression)
- Filter(expression, Pattern)
Soit FS := l'ensemble vide
Soit G := le motif vide, Z, un motif de graphe élémentaire qui est l'ensemble vide.
Pour chaque élément E dans le motif GroupGraphPattern
Si E est de la forme FILTER(expr)
FS := FS set-union {expr}
Si E est de la forme OPTIONAL{P}
Alors
Soit A := Transform(P)
Si A est de la forme Filter(F, A2)
G := LeftJoin(G, A2, F)
sinon
G := LeftJoin(G, A, true)
Si E est d'une autre forme :
Soit A := Transform(E)
G := Join(G, A)
Si FS n'est pas vide :
Soit X := Conjonction des expressions dans FS
G := Filter(X, G)
Le résultat est G.
Étape de simplification :
Les groupes d'un seul motif de graphe (pas un filtre) deviennent Join(Z, A) et peuvent être remplacés par A. Le motif de graphe vide Z est l'identité pour Join :
Remplacer Join(Z, A) par A Remplacer Join(A, Z) par A
La deuxième forme d'un exemple de récriture équivaut à la première, car l'étape de simplification supprime les jointures (joins) de groupe vide.
Exemple de groupe avec un motif de graphe élémentaire consistant en un seul motif de triplet :
Exemple de groupe avec un motif de graphe élémentaire consistant en deux motifs de triplet :
Exemple de groupe consistant en l'union de deux motifs de graphe élémentaires :
Exemple de groupe consistant en l'union d'une union et d'un motif de graphe élémentaire :
Exemple de groupe consistant en un motif de graphe élémentaire et un motif de graphe optionnel :
Exemple de groupe consistant en un motif de graphe élémentaire et deux motifs de graphe optionnels :
Exemple de groupe consistant en un motif de graphe élémentaire et un motif de graphe optionnel avec un filtre :
Exemple de groupe consistant en l'union d'un motif de graphe élémentaire et d'un motif de graphe optionnel :
Exemple de groupe consistant en un motif de graphe élémentaire, un filtre et un motif de graphe optionnel :
Étape 1 : ToList
ToList transforme un multiensemble (multiset) en une séquence avec les mêmes éléments et la même cardinalité. Il n'y a aucun tri implicite de la séquence ; les doubles n'ont pas besoin d'être adjacents.
Soit M := ToList(Pattern)
Étape 2 : ORDER BY
Si la chaîne d'interrogation a une clause ORDER BY
M := OrderBy(M, liste de comparateurs de tri)
Étape 3 : Projection
M := Project(M, vars)
où vars est l'ensemble des variables mentionnées dans la clause SELECT, ou de toutes les variables nommées dans l'interrogation si SELECT * est utilisé.
Étape 4 : DISTINCT
Si l'interrogation contient DISTINCT,
M := Distinct(M)
Étape 5 : REDUCED
Si l'interrogation contient REDUCED,
M := Reduced(M)
Étape 6 : OFFSET et LIMIT
Si l'interrogation contient "OFFSET start" ou "LIMIT length"
M := Slice(M, start, length)
par défaut, start vaut 0
par défaut, length vaut (size(M)-start).
L'interrogation abstraite globale est M.
Lors de la comparaison de motifs de graphe, les solutions possibles forment un multiensemble [Multiset], appelé aussi sac (bag). Un multiensemble est une collection non ordonnée d'éléments dans lequel chaque élément peut apparaître plus d'une fois. Il est décrit par un ensemble d'éléments et une fonction de cardinalité donnant le nombre d'apparitions (ou multiplicité) de chaque élément de l'ensemble dans le multiensemble.
Notons μ les applications de solution et
Notons μ0 l'application telle que dom(μ0) est l'ensemble vide.
Notons Ω0 le multiensemble constitué exactement de l'application vide μ0, avec une multiplicité de 1. C'est l'identité de jointure.
Notons μ(?x→t) la solution associant la variable x au terme RDF t : { (x, t) }
Notons Ω(?x→t) le multiensemble constitué exactement de μ(?x→t), c'est-à-dire { { (x, t) } } avec une multiplicité de 1.
Deux applications de solution μ1 et μ2 sont compatibles si, pour toute variable v dans dom(μ1) et dans dom(μ2), μ1(v) = μ2(v).
Si μ1 et μ2 sont compatibles, alors μ1 set-union μ2 est aussi une application. Notons merge(μ1, μ2) pour μ1 set-union μ2
Notons card[Ω](μ) la multiplicité de l'application de solution μ dans un multiensemble d'applications Ω.
Les motifs de graphe élémentaires forment la base du filtrage par motif de SPARQL. Un motif de graphe élémentaire est comparé au graphe actif de cette partie de l'interrogation. Les motifs de graphe élémentaires peuvent être instanciés en remplaçant les variables et les nœuds anonymes par des termes, en donnant deux notions de l'instance. Les nœuds anonymes sont remplacés en utilisant une application d'instance RDF, σ, des nœuds anonymes aux termes RDF ; les variables sont remplacées par une application de solution, des variables d'interrogation aux termes RDF.
Une application d'instance de motif, P, est la combinaison d'une application d'instance RDF, σ, et d'une application de solution, μ, telle que P(x) = μ(σ(x))
Toute application d'instance de motif définit une application de solution unique et une application d'instance RDF unique, obtenue en la restreignant respectivement aux variables d'interrogation et aux nœuds anonymes.
Soit BGP un motif de graphe élémentaire et G un graphe RDF.
μ est une solution pour BGP de G lorsqu'il existe une application d'instance de motif P telle que P(BGP) soit un sous-graphe de G et μ soit la restriction de P aux variables d'interrogation dans BGP.
card[Ω](μ) = card[Ω](nombre d'applications d'instance RDF, σ, tel que P = μ(σ) soit une application d'instance de motif et P(BGP) soit un sous-graphe de G).
Si un motif de graphe élémentaire est l'ensemble vide, alors la solution est Ω0.
Cette définition permet à l'application de solution de relier une variable dans un motif de graphe élémentaire, BGP, à un nœud anonyme dans G. Puisque SPARQL traite les identificateurs de nœud anonyme dans un document au format XML des résultats d'interrogation SPARQL comme étant confinés (scoped) au document, on ne peut pas les prendre comme nœuds identifiants dans le graphe actif de l'ensemble de données. Si nous notons DS l'ensemble de données d'une interrogation, les solutions des graphes sont donc comprises comme n'appartenant pas au graphe actif de DS même mais à un graphe RDF appelé le « graphe de visibilité » (scoping graph), qui est le graphe équivalent du graphe actif de DS mais ne partage pas de nœuds anonymes avec DS ou avec BGP. Le même graphe de visibilité est utilisé pour toutes les solutions d'une seule interrogation. Le graphe de visibilité est une construction purement théorique ; en pratique, l'effet est obtenu simplement par les conventions de visibilité de document des identificateurs de nœud anonyme.
Comme les nœuds anonymes RDF admettent une infinité de solutions redondantes pour plusieurs motifs, il peut y avoir une infinité de solutions de motif (obtenues en remplaçant les nœuds anonymes par des nœuds anonymes différents). Il est donc nécessaire de délimiter en quelque sorte les solutions d'un motif de graphe élémentaire. SPARQL utilise le critère de concordance de sous-graphe (subgraph match criterion) pour déterminer les solutions d'un motif de graphe élémentaire. Il y a une seule solution pour chaque application d'instance de motif distincte, du motif de graphe élémentaire à un sous-ensemble du graphe actif.
On l'optimise pour faciliter le calcul plutôt que pour éliminer la redondance. Cela autorise les résultats d'interrogation à contenir des redondances, même si le graphe actif de l'ensemble de données est mince (lean), et des ensembles de données logiquement équivalents à produire des résultats d'interrogation différents.
Pour chaque symbole d'une interrogation abstraite SPARQL, nous définissons un opérateur d'évaluation. Nous utilisons les opérateurs algébriques SPARQL de même nom pour évaluer les nœuds des interrogations abstraites SPARQL comme cela est décrit à la section 12.5 Sémantique d'évaluation SPARQL.
Définition : Filter
Soit Ω un multiensemble d'applications de solution et expr une expression. Nous définissons :
Filter(expr, Ω) = { μ | μ dans Ω et expr(μ) est une expression qui a une valeur booléenne effective de true }
card[Filter(expr, Ω)](μ) = card[Ω](μ)
Définition : Join
Soit Ω1 et Ω2 des multiensembles d'applications de solution. Nous définissons :
Join(Ω1, Ω2) = { merge(μ1, μ2) | μ1 dans Ω1 et μ2 dans Ω2, et μ1 et μ2 étant compatibles }
card[Join(Ω1, Ω2)](μ) =
pour chaque merge(μ1, μ2), μ1
dans Ω1 et μ2 dans Ω2 tel que μ = merge(μ1, μ2),
somme de (μ1, μ2), card[Ω1](μ1)*card[Ω2](μ2)
Il est possible qu'une application de solution μ dans une jointure (Join) puisse apparaître dans des applications de solution différentes, μ1 et μ2 dans les multiensembles étant joints. La multiplicité (cardinality) de μ est la somme des multiplicités de toutes les possibilités.
Définition : Diff
Soit Ω1 et Ω2 des multiensembles d'applications de solution. Nous définissons :
Diff(Ω1, Ω2, expr) =
{ μ | μ dans Ω1 tel que pour tous les μ′ dans Ω2,
soit μ et μ′ ne sont pas compatibles, soit μ et μ'
sont compatibles et expr(merge(μ, μ')) a une valeur booléenne effective
de false }
card[Diff(Ω1, Ω2, expr)](μ) = card[Ω1](μ)
Diff est utilisé en interne pour la définition de LeftJoin.
Définition : LeftJoin
Soit Ω1 et Ω2 des multiensembles d'applications de solution et expr une expression. Nous définissons :
LeftJoin(Ω1, Ω2, expr) = Filter(expr, Join(Ω1, Ω2)) set-union Diff(Ω1, Ω2, expr)
card[LeftJoin(Ω1, Ω2, expr)](μ) = card[Filter(expr, Join(Ω1, Ω2))](μ) + card[Diff(Ω1, Ω2, expr)](μ)
Qui s'écrit en entier :
LeftJoin(Ω1, Ω2, expr) =
{ merge(μ1, μ2) | μ1 dans Ω1 et μ2 dans
Ω2, et μ1 et μ2 sont compatibles et expr(merge(μ1,
μ2)) est true }
set-union
{ μ1 | μ1 dans Ω1 et μ2 dans Ω2, et
μ1 et μ2 ne sont pas compatibles }
set-union
{ μ1 | μ1 dans Ω1 et μ2 dans Ω2, et
μ1 et μ2 sont compatibles et expr(merge(μ1, μ2)) est false
}
Comme ceux-ci sont distincts, la multiplicité de LeftJoin est la multiplicité de ces composants individuels de la définition.
Définition : Union
Soit Ω1 et Ω2 des multiensembles d'applications de solution. Nous définissons :
Union(Ω1, Ω2) = { μ | μ dans Ω1 ou μ dans Ω2 }
card[Union(Ω1, Ω2)](μ) = card[Ω1](μ) + card[Ω2](μ)
Notons [x | C] une suite d'éléments où C(x) est true.
Notons card[L](x) comme étant la multiplicité de x dans L.
Définition : ToList
Soit Ω un multiensemble d'applications de solution. Nous définissons :
ToList(Ω) = une suite d'applications μ dans Ω dans un ordre quelconque, avec card[Ω](μ) apparitions de μ
card[ToList(Ω)](μ) = card[Ω](μ)
Définition : OrderBy
Soit Ψ une suite d'applications de solution. Nous définissons :
OrderBy(Ψ, condition) = [ μ | μ dans Ψ et la suite satisfait à la condition de tri]
card[OrderBy(Ψ, condition)](μ) = card[Ψ](μ)
Définition : Project
Soit Ψ une suite d'applications de solution et PV un ensemble de variables.
Pour l'application μ, notons Proj(μ, PV) la restriction de μ aux variables dans PV.
Project(Ψ, PV) = [ Proj(Ψ[μ], PV) | μ dans Ψ ]
card[Project(Ψ, PV)](μ) = card[Ψ](μ)
L'ordre de Project(Ψ, PV) doit conserver un tri donné par OrderBy.
Définition : Distinct
Soit Ψ une suite d'applications de solutions. Nous définissons :
Distinct(Ψ) = [ μ | μ dans Ψ ]
card[Distinct(Ψ)](μ) = 1
L'ordre de Distinct(Ψ) doit conserver un tri donné par OrderBy.
Définition : Reduced
Soit Ψ une suite d'applications de solution. Nous définissons :
Reduced(Ψ) = [ μ | μ dans Ψ ]
card[Reduced(Ψ)](μ) est entre 1 et card[Ψ](μ)
L'ordre de Reduced(Ψ) doit conserver un tri donné par OrderBy.
Le modificateur de séquence de solution Reduced ne garantit pas de multiplicité définie.
Définition : Slice
Soit Ψ une suite d'applications de solution. Nous définissons :
Slice(Ψ, start, length)[i] = Ψ[start+i] pour i = 0 jusqu'à (length-1)
Nous définissons eval(D(G), motif de graphe) comme étant l'évaluation d'un motif de graphe par rapport à un ensemble de données D ayant un graphe actif G. Le graphe actif est initialement le graphe par défaut.
D : un ensemble de données D(G) : D un ensemble de données avec un graphe actif G (celui auquel les motifs sont comparés) D[i] : le graphe d'adresse IRI i dans l'ensemble de données D D[DFT] : le graphe par défaut de D P, P1, P2 : des motifs de graphe L : une séquence de solutions
eval(D(G), Filter(F, P)) = Filter(F, eval(D(G),P))
eval(D(G), Join(P1, P2)) = Join(eval(D(G), P1), eval(D(G), P2))
eval(D(G), LeftJoin(P1, P2, F)) = LeftJoin(eval(D(G), P1), eval(D(G), P2), F)
eval(D(G), BGP) = multiensemble d'applications de solution
Cf. la section 12.3 Motifs de graphe élémentaires
eval(D(G), Union(P1,P2)) = Union(eval(D(G), P1), eval(D(G), P2))
si IRI est un nom de graphe dans D eval(D(G), Graph(IRI,P)) = eval(D(D[IRI]), P)
si IRI n'est pas un nom de graphe dans D eval(D(G), Graph(IRI,P)) = le multiensemble vide
eval(D(G), Graph(var,P)) =
Soit R le multiensemble vide
foreach IRI i in D
R := Union(R, Join( eval(D(D[i]), P) , Ω(?var→i) )
le résultat est R
L'évaluation d'un graphe utilise l'opérateur d'union de l'algèbre SPARQL. La multiplicité d'une application de solution est la somme des multiplicités de cette application de solution dans chaque opération de jointure (join).
eval(D, ToList(P)) = ToList(eval(D(D[DFT]), P))
eval(D, Distict(L)) = Distinct(eval(D, L))
eval(D, Reduced(L)) = Reduced(eval(D, L))
eval(D, Project(L, vars)) = Project(eval(D, L), vars)
eval(D, OrderBy(L, condition)) = OrderBy(eval(D, L), condition)
eval(D, Slice(L, start, length)) = Slice(eval(D, L), start, length)
On peut utiliser la conception SPARQL globale pour des interrogations supposant une forme plus élaborée d'inférence (entailment) que l'inférence simple, en récrivant les conditions de concordance des motifs de graphe élémentaires. Puisqu'énoncer de telles conditions dans une seule forme générale, qui s'applique à toutes les formes d'inférence et élimine de façon optimale la redondance inutile ou inappropriée, est un problème de recherche ouvert, ce document donne seulement les conditions nécessaires auxquelles une telle solution devrait satisfaire. Celles-ci devront être développées en définitions complètes pour chaque cas particulier.
Les motifs de graphe élémentaires se tiennent dans une même relation vis-à-vis des motifs de triplet que les motifs RDF vis-à-vis des triplets RDF, et une bonne partie de la même terminologie peut s'y appliquer. En particulier, deux motifs de graphe élémentaires sont dits équivalents s'il existe une bijection M entre les termes des motifs de triplet qui relie les nœuds anonymes aux nœuds anonymes et relie les variables, les littéraux et les adresses IRI à eux-mêmes, de telle sorte qu'un triplet ( s, p, o ) se trouve dans le premier motif si et seulement si le triplet ( M(s), M(p), M(o) ) se trouve dans le deuxième. Cette définition étend celle de l'équivalence des graphes RDF aux motifs de graphe élémentaires en préservant les noms des variables à travers les motifs équivalents.
Un régime d'inférence (entailment regime) définit :
Les exemples de régimes d'inférence comprennent l'inférence simple [RDF-MT], l'inférence RDF [RDF-MT], l'inférence RDFS [RDF-MT], la D-inférence (D-entailment) [RDF-MT] et l'inférence OWL-DL [OWL-Semantics]. Parmi celles-ci, seule l'inférence OWL-DL restreint l'ensemble des graphes bien formés. Si E est un régime d'inférence, alors nous nous référerons à une E-inférence, une E-cohérence, etc. en suivant cette convention d'écriture.
Certains régimes d'inférence peuvent catégoriser des graphes RDF comme étant incohérents. Par exemple, le graphe RDF suivant :
_:x rdf:type xsd:string . _:x rdf:type xsd:decimal .
est D-incohérent lorsque D contient les types de données XSD. L'effet d'une interrogation sur un graphe incohérent n'est pas couvert par cette spécification, mais l'extension SPARQL particulière doit le définir.
Une extension SPARQL d'une E-inférence doit satisfaire aux conditions suivantes :
Le graphe de visibilité SG correspondant à un graphe actif cohérent AG est défini exclusivement et est E-équivalent à AG ;
Pour tout motif de graphe élémentaire BGP et toute application de solution de graphe P, P(BGP) est bien formée pour E ;
Pour tout graphe de visibilité SG et tout ensemble de réponses {P1 ... Pn} pour un motif de graphe élémentaire BGP, où {BGP1 .... BGPn} est un ensemble de motifs de graphe élémentaires, tous équivalents à BGP, aucun d'eux ne partagent de nœuds anonymes avec un autre ou avec SG ;
SG E-infère (SG union P1(BGP1) union ... union Pn(BGPn))
Ces conditions ne déterminent pas complètement l'ensemble des réponses possibles, puisque RDF autorise une quantité illimitée de redondance. De ce fait, la condition suivante doit en outre être vérifiée ;
Chaque extension SPARQL doit fournir des conditions sur les ensembles de réponses garantissant que tous les BGP et AG ont un ensemble fini de réponses qui est unique jusque dans l'équivalence des graphes RDF.
(a) SG sera souvent équivalent (graphe) à AG, mais le restreindre à une E-équivalence permet d'appliquer certaines formes de normalisation, par exemple l'élimination des redondances sémantiques, aux documents sources avant l'interrogation.
(b) La construction dans la condition 3 assure que tous les nœuds anonymes introduits par l'application de solution sont utilisés en interne d'une façon cohérente à celle dont les nœuds anonymes apparaissent dans SG. On s'assure que les identificateurs de nœuds anonymes apparaissent dans plus d'une réponse dans un ensemble de réponses seulement lorsque les nœuds anonymes identifiés ainsi sont en effet identiques dans SG. Si l'extension ne permet pas les liaisons de réponses aux nœuds anonymes, alors on peut simplifier cette condition en la suivante :
SG E-infère P(BGP) pour chaque solution de motif P.
(c) Ces conditions n'imposent pas l'obligation SPARQL selon laquelle SG ne doit pas partager de nœuds anonymes avec AG ou BGP. En particulier, cela permet à SG d'être en fait AG. Cela autorise des protocoles d'interrogation dans lesquels les identificateurs de nœuds anonymes gardent leur signification entre l'interrogation et le document source, ou à travers plusieurs interrogations. De tels protocoles ne sont toutefois pas gérés par la spécification de protocole SPARQL courante.
(d) Puisque les conditions 1 à 3 ne sont nécessaires que sur les réponses, la condition 4 autorise des cas où l'ensemble des réponses légales peut être restreint de diverses façons. Par exemple, l'état de l'art actuel en matière d'interrogation OWL-DL se concentre sur le cas où les liaisons de réponses aux nœuds anonymes sont prohibées. Nous notons que ces conditions permettent même le cas pathologique « muet » où chaque interrogation a un ensemble de réponses vide.
(e) Aucune de ces conditions ne mentionne explicitement les applications d'instance sur les nœuds anonymes dans BGP. Pour certains régimes d'inférence, l'interprétation existentielle des nœuds anonymes ne peut pas être entièrement capturée par l'existence d'une seule application d'instance. Ces conditions permettent à de tels régimes de donner aux nœuds anonymes dans les motifs d'interrogation une lecture « entièrement existentielle ».
On montre aisément que SPARQL satisfait à ces conditions dans le cas où E est une inférence simple, étant donné que la condition SPARQL sur SG est qu'il équivaut (graphe) à AG mais ne partage pas de nœuds anonymes avec AG ou BGP (ce qui satisfait à la première condition). Seule la condition 3 n'est pas évidente.
Chaque réponse Pi est la restriction d'application de solution d'une instance SPARQL Mi, telle que Mi(BGPi) est un sous-graphe de SG. Puisque BGPi et SG n'ont aucun nœud anonyme commun, le domaine d'arrivée (range) de Mi ne contient aucun nœud anonyme de BGPi ; ainsi, les composantes d'application de solution Pi et d'application d'instance RDF Ii de Mi se substituent, et Mi(BGPi) = Ii(Pi(BGPi)). Donc :
M1(BGP1) union ... union Mn(BGPn)
= I1(P1(BGP1)) union ... union In(Pn(BGPn))
= [ I1 + ... + In]( P1(BGP1) union
... union Pn(BGPn) )
puisque les domaines de définition (domains) des applications d'instance Ii sont tous mutuellement exclusifs. Comme ils sont également exclusif par rapport à SG,
SG union [ I1 + ... + In]( P1(BGP1)
union ... union Pn(BGPn) )
= [ I1 + ... + In](SG union P1(BGP1)
union ... union Pn(BGPn) )
c'est-à-dire que
SG union P1(BGP1) union ... union Pn(BGPn)
a une instance laquelle est un sous-graphe de SG, et est donc inférée simplement par SG selon le lemme d'interpolation RDF [RDF-MT].
Une chaîne d'interrogation SPARQL
(SPARQL query string) est une chaîne de caractères Unicode (cf. la section 6.1 Concepts de chaînes
de [CHARMOD]) dans le langage défini par la grammaire suivante, commençant par la production
Query. Pour la compatibilité avec des versions futures d'Unicode, les caractères dans cette chaîne peuvent
inclure des points de code Unicode non affectés à la date de cette publication (cf. la section 4 Pattern Syntax
dans Identifier and Pattern Syntax
[UNIID]). Pour les productions excluant des classes de caractères (par exemple [^<>'{}|^`]),
les caractères sont exclus de l'intervalle #x0 - #x10FFFF.
Les séquences d'échappement de points de code d'une chaîne d'interrogation SPARQL sont traitées avant l'analyse selon la grammaire de la définition EBNF ci-dessous. Les séquences d'échappement de points de code d'une chaîne d'interrogation SPARQL sont les suivantes :
| Échappement | Point de code Unicode |
|---|---|
| '\u' HEX HEX HEX HEX | Un point de code Unicode dans l'intervalle U+0 à U+FFFF inclus correspondant à la valeur hexadécimale codée. |
| '\U' HEX HEX HEX HEX HEX HEX HEX HEX | Un point de code Unicode dans l'intervalle U+0 à U+10FFFF inclus correspondant à la valeur hexadécimale codée. |
où HEX est un caractère hexadécimal.
HEX ::= [0-9] | [A-F] | [a-f]
Exemples :
<ab\u00E9xy> # le point de code 0x00E9 est la LETTRE MINUSCULE LATINE E ACCENT AIGU é \u03B1:a # le point de code 0x03B1 est la LETTRE MINUSCULE GRECQUE ALPHA α a\u003Ab # a:b -- le point de code 0x003A est le DEUX-POINTS
Les séquences d'échappement de points de code peuvent apparaître n'importe où dans la chaîne d'interrogation. Elles sont traitées
avant l'analyse fondée sur les règles de grammaire et peuvent donc être remplacées par des points de code ayant une signification dans
la grammaire, ainsi ":" qui marque un nom préfixé.
Ces séquences d'échappement ne sont pas incluses dans la grammaire ci-dessous. Seules les séquences d'échappement de caractères
qui seraient légales à ce point dans la grammaire peuvent être données. Par exemple, la variable "?x\u0020y" n'est pas légale
(\u0020 est un caractère ESPACE non admis dans un nom de variable).
Les caractères blancs (white space) — production WS —
servent à séparer deux terminaux qui seraient sinon (mal) interprétés comme un seul. Les noms de règle en majuscules ci-dessous indiquent
où les caractères blancs sont signficatifs ; ceux-ci forment un choix de terminaux possible pour construire un analyseur SPARQL.
Les caractères blancs sont significatifs dans les chaînes.
Par exemple :
?a<?b&&?c>?d
est la variable de séquence d'atome '?a', une adresse IRI '<?b&&?c>' et une
variable '?d', et non une expression impliquant l'opérateur '&&' connectant deux expressions
avec '<' (inférieur à) et '>' (supérieur à).
Les commentaires dans les interrogations SPARQL prennent la forme d'un caractère "#", hors d'une
adresse IRI ou d'une chaîne, et continuent jusqu'à la fin de la ligne (marquée par un caractère 0x0D ou
0x0A) ou à la fin du fichier s'il n'y a pas de caractère de fin de ligne après le marqueur de commentaire. Les commentaires
sont traités comme des caractères blancs.
Le texte filtré par la production IRI_REF et la production
PrefixedName (après expansion du préfixe), après le traitement des échappements,
doit être conforme à la syntaxe générique des références IRI à la section
2.2 Définition ABNF des références IRI et des adresses IRI du RFC 3987
[RFC3987]. Par exemple, la référence IRI_REF
<abc#def> peut apparaître dans une chaîne d'interrogation SPARQL, mais la référence
IRI_REF <abc##def> ne le doit pas.
Les adresses IRI de base déclarées avec le mot-clé BASE doivent être des adresses IRI absolues. Un préfixe déclaré avec le mot-clé PREFIX ne peut pas être redéclaré dans la même interrogation. Cf. la section 2.1.1 Syntaxe des termes IRI pour une description de BASE et de PREFIX.
La même étiquette de nœud anonyme ne peut pas être utilisée dans deux motifs de graphes élémentaires distincts avec la même interrogation.
En plus des séquences d'échappement de points de code, il y a les séquences d'échappement suivantes
dans toute production string (par exemple
STRING_LITERAL1, STRING_LITERAL2,
STRING_LITERAL_LONG1, STRING_LITERAL_LONG2) :
| Échappement | Point de code Unicode |
|---|---|
| '\t' | U+0009 (TABULATION HORIZONTALE) |
| '\n' | U+000A (CHANGEMENT DE LIGNE) |
| '\r' | U+000D (RETOUR DE CHARIOT) |
| '\b' | U+0008 (ESPACE ARRIÈRE) |
| '\f' | U+000C (SAUT DE PAGE) |
| '\"' | U+0022 (GUILLEMET ANGLAIS) |
| "\'" | U+0027 (APOSTROPHE) |
| '\\' | U+005C (BARRE OBLIQUE INVERSÉE) |
Exemples :
"abc\n" "xy\rz" 'xy\tz'
La notation EBNF utilisée dans la grammaire est défini à la section 6 Notation de la spécification Langage de balisage extensible (XML) 1.1 [XML11].
Les mots-clés sont comparés d'une manière indépendante de la casse à l'exception du mot-clé 'a' qui est utilisé,
en accord avec Turtle et N3, en place de l'adresse IRI de rdf:type
(en entier, http://www.w3.org/1999/02/22-rdf-syntax-ns#type).
Mots-clés :
| BASE | SELECT | ORDER BY | FROM | GRAPH | STR | isURI |
| PREFIX | CONSTRUCT | LIMIT | FROM NAMED | OPTIONAL | LANG | isIRI |
| DESCRIBE | OFFSET | WHERE | UNION | LANGMATCHES | isLITERAL | |
| ASK | DISTINCT | FILTER | DATATYPE | REGEX | ||
| REDUCED | a | BOUND | true | |||
| sameTERM | false |
Les séquences d'échappement sont dépendantes de la casse.
Lors du choix d'une règle à appliquer, la correspondance la plus longue est choisie.
Productions des terminaux :
[70] |
IRI_REF |
::= | '<' ([^<>"{}|^`\]-[#x00-#x20])* '>' |
[71] |
PNAME_NS |
::= | PN_PREFIX? ':' |
[72] |
PNAME_LN |
::= | PNAME_NS PN_LOCAL |
[73] |
BLANK_NODE_LABEL |
::= | '_:' PN_LOCAL |
[74] |
VAR1 |
::= | '?' VARNAME |
[75] |
VAR2 |
::= | '$' VARNAME |
[76] |
LANGTAG |
::= | '@' [a-zA-Z]+ ('-' [a-zA-Z0-9]+)* |
[77] |
INTEGER |
::= | [0-9]+ |
[78] |
DECIMAL |
::= | [0-9]+ '.' [0-9]* | '.' [0-9]+ |
[79] |
DOUBLE |
::= | [0-9]+ '.' [0-9]* EXPONENT | '.' ([0-9])+ EXPONENT | ([0-9])+ EXPONENT |
[80] |
INTEGER_POSITIVE |
::= | '+' INTEGER |
[81] |
DECIMAL_POSITIVE |
::= | '+' DECIMAL |
[82] |
DOUBLE_POSITIVE |
::= | '+' DOUBLE |
[83] |
INTEGER_NEGATIVE |
::= | '-' INTEGER |
[84] |
DECIMAL_NEGATIVE |
::= | '-' DECIMAL |
[85] |
DOUBLE_NEGATIVE |
::= | '-' DOUBLE |
[86] |
EXPONENT |
::= | [eE] [+-]? [0-9]+ |
[87] |
STRING_LITERAL1 |
::= | "'" ( ([^#x27#x5C#xA#xD]) | ECHAR )* "'" |
[88] |
STRING_LITERAL2 |
::= | '"' ( ([^#x22#x5C#xA#xD]) | ECHAR )* '"' |
[89] |
STRING_LITERAL_LONG1 |
::= | "'''" ( ( "'" | "''" )? ( [^'\] | ECHAR ) )* "'''" |
[90] |
STRING_LITERAL_LONG2 |
::= | '"""' ( ( '"' | '""' )? ( [^"\] | ECHAR ) )* '"""' |
[91] |
ECHAR |
::= | '\' [tbnrf\"'] |
[92] |
NIL |
::= | '(' WS* ')' |
[93] |
WS |
::= | #x20 | #x9 | #xD | #xA |
[94] |
ANON |
::= | '[' WS* ']' |
[95] |
PN_CHARS_BASE |
::= | [A-Z] | [a-z] | [#x00C0-#x00D6] | [#x00D8-#x00F6] | [#x00F8-#x02FF] | [#x0370-#x037D] | [#x037F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF] |
[96] |
PN_CHARS_U |
::= | PN_CHARS_BASE | '_' |
[97] |
VARNAME |
::= | ( PN_CHARS_U | [0-9] ) ( PN_CHARS_U | [0-9] | #x00B7 | [#x0300-#x036F] | [#x203F-#x2040] )* |
[98] |
PN_CHARS |
::= | PN_CHARS_U | '-' | [0-9] | #x00B7 | [#x0300-#x036F] | [#x203F-#x2040] |
[99] |
PN_PREFIX |
::= | PN_CHARS_BASE ((PN_CHARS|'.')* PN_CHARS)? |
[100] |
PN_LOCAL |
::= | ( PN_CHARS_U | [0-9] ) ((PN_CHARS|'.')* PN_CHARS)?Notez que les noms locaux SPARQL admettent des chiffres en tête, contrairement aux noms locaux XML. |
Remarques :
AdditiveExpression l'autorise en couvrant les deux cas d'une expression
suivie d'un nombre à signe. Cela produit une addition ou une substraction du nombre sans signe selon le cas.Les fichiers de grammaire de quelques outils courants sont disponibles ici.
Cf. l'annexe A Grammaire SPARQL à propos de la conformité des chaînes d'interrogation SPARQL, et la section 10 Formes d'interrogation pour la conformité des résultats d'interrogation. Cf. l'annexe E. Type de média Internet pour la conformité au type de média application/sparql-query.
Cette spécification est prévue pour être utilisée en conjonction avec le protocole SPARQL [SPROT] et le format XML des résultats d'interrogation SPARQL [RESULTS]. Cf. les critères de conformité de ces spécifications.
Notez que le protocole SPARQL décrit une interface abstraite ainsi qu'un protocole de réseau, et que l'interface abstraite peut aussi bien s'appliquer à des interfaces de programmation (API) qu'à des interfaces de réseau.
Les interrogations SPARQL utilisant des clauses FROM, FROM NAMED ou GRAPH peuvent provoquer la résolution
de l'adresse URI indiquée. Cela peut entraîner une utilisation supplémentaire des ressources de réseau, de stockage ou
de traitement (CPU) en même temps que des problèmes secondaires associés tels qu'une attaque par saturation
(denial of service). Les problèmes de sécurité décrits à la section 7 de
Identificateur de ressource uniforme (URI) — Syntaxe générique
[RFC3986] devraient être pris en compte. En outre, le contenu des adresses URI de type file:
peut dans certains cas être accédé, traité et retourné comme résultats, offrant un accès inattendu aux ressources locales.
Le langage SPARQL autorise les extensions, lesquelles auront leurs propres implications pour la sécurité.
Plusieurs adresses IRI peuvent avoir le même aspect. Des caractères d'écritures différentes peuvent sembler les mêmes (un caractère cyrillique "о" peut apparaître semblable à un caractère latin "o"). Un caractère suivi par des caractères combinatoires (combining characters) peut avoir la même représentation visuelle qu'un autre (un caractère LETTRE MINUSCULE LATINE E suivi d'un caractère LETTRE MODIFICATIVE ACCENT AIGU ont la même représentation visuelle qu'un caractère LETTRE MINUSCULE LATINE E ACCENT AIGU). Les utilisateurs de SPARQL doivent faire attention de construire des interrogations avec des adresses IRI qui correspondent aux adresses IRI dans les données. On peut trouver plus de renseignements à propos de la comparaison de caractères similaires dans Unicode Security Considerations [UNISEC] et Identificateurs de ressource internationalisés (IRI) [RFC3987], section 8.
Le type de média Internet, ou type MIME, du langage d'interrogation SPARQL est "application/sparql-query".
Il est recommandé que les fichiers d'interrogation SPARQL aient l'extension ".rq" (tout en minuscules) sur toutes les plateformes.
Il est recommandé que les fichiers d'interrogation SPARQL stockés sur le système de fichiers HFS Macintosh reçoivent le type de fichier "TEXT".
Le langage d'interrogation RDF SPARQL est un produit de l'ensemble du groupe de travail RDF Data Access du W3C, et nos remerciements pour les débats, commentaires et revues vont à tous les membres présents et passés.
Nous avons en outre débattu et discuté avec de nombreuses personnes au travers de la liste aux commentaires du groupe de travail. Tous les commentaires ont participé à améliorer le document. Andy voudrait également remercier en particulier Jorge Peérez, Geoff Chappell, Bob MacGregor, Yosi Scharf et Richard Newman pour avoir exploré les problèmes spécifiques en rapport avec SPARQL. Eric voudrait signaler l'aide incalculable de Björn Höhrmann.
Voici un récapitulatif au niveau supérieur des changements apportés à ce document depuis la publication de la recommandation candidate du 14 juin 2007 :
application/sparql-query a été approuvé et le texte à propos du statut de cette requête a donc été supprimé.