RDF Introduction
RDF Introduction
Michel Gagnon
2 Syntaxe de RDF 4
2.1 Syntaxe abstraite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.2 Syntaxe N-Triples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.3 Syntaxe Turtle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.4 Syntaxe RDF/XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.4.1 Représentation des noeuds vides . . . . . . . . . . . . . . . . . . . . . . . 9
2.4.2 Littéraux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.4.3 Identification de l’URI de base . . . . . . . . . . . . . . . . . . . . . . . . 11
2.5 Identification des types de ressources . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.6 Conteneurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.7 Collections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.8 Réification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.9 Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3 RDF Schema 22
3.1 Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3.2 Propriétés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
1 Introduction
RDF (Resource Description Framework) n’est pas à proprement parler un langage. Il s’agit
plutôt d’un modèle de données pour décrire des ressources sur le web. On entend par ressource
toute entité que l’on veut décrire sur le web mais qui n’est pas nécessairement accessible sur
le web. Par exemple, on pourrait fournir des informations sur l’auteur de ce document, malgré
que la personne décrite n’est pas accessible par le web. On trouve plutôt des ressources, comme
sa page personnelle, ou une photo, qui peuvent être obtenues à partir de leur URL (Universal
Resource Locator). Ces ressources sont reliées à cette personne, mais ne sont pas cette personne.
1
Pour désigner cette personne, on utilisera une URI (Universal Resource Identifier), un nom unique
qui ressemble syntaxiquement à une URL, mais à la différence près qu’il n’est pas nécessaire que
celle-ci soit accessible sur le web. D’une certaine manière l’ensemble des URL est inclus dans
l’ensemble des URI (voir figure 1).
URL
La raison d’être de RDF est de permettre que les informations sur les ressources soient mani-
pulées par des applications, plutôt que d’être simplement affichées aux utilisateurs du web. C’est
entre autres pour cette raison qu’une syntaxe XML a été proposée pour véhiculer des informations
modélisées en RDF. Il existe aussi une autre notation plus facile à lire pour un humain : Turtle.
Parmi les caractéristiques importantes de RDF, on retrouve sa flexibilité et son extensibilité.
N’importe qui peut ajouter des informations sur une ressource, en autant que l’on connaisse son
URI. Ainsi, deux documents distincts situés à des endroits différents peuvent fournir des descrip-
tions d’une même ressource. Rien n’empêche une application d’extraire les descriptions fournies
par ces documents et de le fusionner. Aussi, rien n’oblige qu’une ressource décrite existe réelle-
ment. En fait, RDF impose peu de contraintes sur les descriptions possibles.
Supposons par exemple que nous voulions décrire une personne qui s’appelle Michel Gagnon,
qui travaille au département de génie informatique de l’École polytechnique de Montréal et dont
la page personnelle se trouve à l’URL suivante :
http://www.professeurs.polymtl.ca/michel.gagnon.
Pour ce faire, il faut d’abord reconnaître qu’il y a quatre entités référées par la description :
la personne en question, son nom, l’endroit où elle travaille et sa page personnelle. Pour chacune,
sauf le nom, il faut donc une URI pour la représenter. Le nom est un cas spécial, puisqu’il s’agit
en fait d’une chaîne de caractères. Nous pourrrons dans ce cas utiliser la chaîne directement, sans
passer par l’intermédiaire d’une URI pour la désigner.
Supposons donc que les quatre entités de notre description sont désignées de la manière sui-
vante :
2
la personne décrite http://www.polymtl.ca/Profs#MichelGagnon
le nom de la personne "Michel Gagnon"
le lieu de travail http://www.polymtl.ca/Vocabulary#dgi
la page personnelle http://www.professeurs.polymtl.ca/michel.gagnon
Veuillez notez que même si les URI désignant la personne et son lieu de travail ont la forme
http://www..., cela ne signifie pas nécessairement qu’il s’agisse d’une URL correspondant à un docu-
ment auquel on peut accéder sur le web. Il s’agit tout simplement d’une convention utilisée pour uniformiser
les URI. L’intérêt de cette convention est qu’elle laisse la possibilité de traiter cette URI comme une URL et
de mettre sur le web un document correspondant à cette URL. Un document, par exemple, qui expliquerait
de manière informelle l’entité représentée par l’URI en question. Mais rappelons encore une fois qu’il n’est
pas nécessaire qu’il y ait un document sur le web pour chaque URI.
Il nous faut maintenant représenter les relations entre ces entités. RDF prévoit l’existence de propriétés.
Il s’agit d’entités dont le rôle est d’établir un lien entre deux autres entités. Dans notre exemple, il faudra
utiliser trois propriétés pour relier la personne avec son nom, son lieu de travail, et sa page personnelle. Les
propriétés sont elles aussi désignées par des URI. La figure 2 illustre notre description en RDF, en utilisant
les propriétés suivantes, respectivement :
http://www.polymtl.ca/Vocabulary#hasName
http://www.polymtl.ca/Vocabulary#worksAt
http://www.polymtl.ca/Vocabulary#hasHomePage
On voit bien, avec cet exemple, qu’un modèle RDF est en fait un graphe, avec deux types de noeuds.
Certains noeuds, représentés par une ellipse, désignent une entité référée par une URI. D’autres noeuds, re-
présentés par un rectangle, représentent un littéral, c’est-à-dire une entité exprimée directement, une chaîne
de caractères par exemple. Nous verrons plus loin qu’un littéral peut aussi être d’un autre type, comme un
entier, une valeur booléenne, une date, etc.
3
On remarquera aussi, dans notre exemple, que plusieurs URI ont le même préfixe :
http://www.polymtl.ca/Vocabulary#.
Il est possible d’alléger la représentation en utilisant un alias pour ce préfixe. Ainsi, si on utilise les alias
local: et prof: pour les préfixes http://www.polymtl.ca/Vocabulary# et
http://www.polymtl.ca/Profs#, respectivement, notre description sera telle qu’illustrée à la fi-
gure 3.
2 Syntaxe de RDF
RDF étant un modèle de données sous forme de graphe, il n’a pas à proprement parler de syntaxe. En
fait, il y a plusieurs syntaxes possibles pour représenter une description RDF. La plus connue est la syntaxe
RDF/XML qui, utilisant le méta-langage XML, permet de créer des descriptions facilement manipulables
par la machine. Comme il faut bien pouvoir spécifier les contraintes de toute syntaxe utilisée pour représenter
un graphe RDF, une syntaxe abstraite a donc été définie, que nous allons maintenant décrire brièvement. Par
la suite, nous verrons comment un graphe RDF peut être représenté dans les trois syntaxes suivantes :
RDF/XML, N-Triples et Turtle.
4
prédicat, qui représente une propriété, est toujours une URI. Finalement, l’objet, qui représente la valeur de
la propriété lorsqu’appliquée au sujet, peut être une URI, un noeud vide ou un littéral.
Notons qu’il y a plusieurs avantages à utiliser des URI pour désigner les ressources décrites par une
graphe RDF. Premièrement, elles permettent de désambiguïser les désignations utilisées et de permettre à
plusieurs applications de partager le même vocabulaire tout en évitant les conflits de noms. De plus, le fait
que les propriétés sont elles-mêmes désignées par des URI permet que celles-ci soient aussi utilisées comme
des ressources. On peut donc ajouter des triplets RDF qui fournissent des informations sur ces propriétés.
Nous verrons plusieurs situations de ce genre dans la suite de ce document.
Un noeud vide est tout noeud qui n’est ni une URI, ni un littéral. Il s’agit d’un noeud unique qui peut ap-
paraître dans plusieurs triplets, et qui n’a pas de nom intrinsèque. En quelque sorte, un noeud vide représente
une ressource anonyme.
Un graphe peut contenir deux types de littéral. Un littéral simple est constitué d’une chaîne de caractères,
appelée forme lexicale, et facultativement d’un attribut indiquant la langue. Un littéral typé est formé d’une
chaîne de caractères (qui constitue la forme lexicale) et d’une URI indiquant un type qui sera utilisé pour
décoder cette chaîne. Par exemple, la chaîne typée "10"^^xsd:integer indique que la chaîne "10"
doit être interprétée comme un entier, selon le type xsd:integer défini dans la norme de XML Schema.
À remarquer que RDF n’a pas de types pré-définis. Il faudra donc toujours utiliser une ressource externe à
RDF pour interpréter un littéral typé. Rien n’empêche une application de définir ses propres types.
Supposons par exemple, que nous voulions indiquer que la dernière date de mise à jour de la page
personnelle de Michel Gagnon est le 20 mai 2005. On pourrait toujours le faire en ajoutant une propriété
local:derniereMaJ et dont la valeur serait 2005-05-20. Mais, comme il s’agit tout simplement
d’une chaîne de caractère, il serait difficile d’effectuer une comparaison avec une autre date.
Il est donc préférable de fournir un type à ce littéral. La manière la plus simple de le faire serait d’utiliser
le type xml:date prévu par la norme XML. En ajoutant ce type, on indique que le littéral ne doit pas être
interprété comme tel, mais plutôt qu’on doit utiliser le type spécifié pour identifier la valeur correspondant
à la chaîne fournie.
Plus formellement, un type de données en RDF est toujours identifié par une URI et suppose l’existence
d’un espace lexical L, d’un espace de valeurs V et d’une fonction m : L → 7 V. L’espace lexical L est
l’ensemble de toutes les chaînes de caractères possibles pour ce type, alors que V est l’ensemble de toutes
les valeurs possibles. L’application m doit être définie telle que :
— chaque membre de L est associé à exactement un membre de V ;
— pour chaque valeur de V, il peut y avoir zéro ou plusieurs membres de L qui lui sont associés.
À part ces caractéristiques que tout littéral typé doit respecter en RDF, aucune autre contrainte n’est
spécifiée et, surtout, aucune spécification sur la manière d’interpréter un littéral typé. Cette interprétation
repose entièrement sur l’application qui manipule le document RDF.
Si le sujet, le prédicat ou l’objet est une URI, on le représente en mettant entre crochets <> la forme non
abrégée de cet URI. Ainsi, on ne peut pas utiliser de préfixe dans la notation N-Triples.
5
Dans le cas où le sujet ou l’objet est un noeud vide, on utilise la forme _:nom, où nom est tout simple-
ment un identificateur unique pour ce noeud vide. La seule raison d’être de ce nom est de pouvoir référer au
même noeud vide dans deux triplets différents lorsque le noeud vide est impliqué dans plus d’une relation.
Finalement, un littéral est représenté directement sans modification. En utilisant la notation N-Triples,
nous obtenons la représentation suivante pour le graphe RDF de la figure 2 :
<http
://www.polymtl.ca/Profs#MichelGagnon> <http
://www.polymtl.ca/Vocabulary#worksAt>
<http
://www.polymtl.ca/Vocabulary#dgi> .
<http
://www.polymtl.ca/Profs#MichelGagnon> <http
://www.polymtl.ca/Vocabulary#hasName> "Michel Gagnon"
.
<http
://www.polymtl.ca/Profs#MichelGagnon> <http
://www.polymtl.ca/Vocabulary#hasHomePage>
<http
://www.professeurs.polymtl.ca/michel.gagnon> .
_
:p234 <http
://www.polymtl.ca/Vocabulary#worksAt> <http
://www.polymtl.ca/Vocabulary#dgi> .
_
:p234 <http
://www.polymtl.ca/Vocabulary#hasName> "Michel Gagnon" .
_
:p234 <http
://www.polymtl.ca/Vocabulary#hasHomePage> <http
://www.professeurs.polymtl.ca/michel.gagnon>
.
On voit bien que cette notation est fastidieuse, étant donné l’impossibilité d’abbréger les URI. Dans la
suite de ce document, nous utiliserons une manière abrégée. Au lieu d’écrire l’URI au complet entre cro-
chets, nous utiliserons la forme prefixe:URI. À noter qu’il s’agit d’un simple ajustement pour faciliter
la lecture, que les triplets écrits de cette manière ne sont pas valides dans la notation N-triples. Ainsi, chaque
fois qu’on verra la forme prefixe:URI dans un triplets, il faudra imaginer qu’elle ne fait que remplacer
la forme correcte <URI>, où URI correspond à l’URI écrite au long sans préfixe. Supposons maintenant
que les préfixes local: et prof: correspondent aux URI suivantes, respectivement :
http://www.polymtl.ca/Vocabulary#
http://www.polymtl.ca/Profs#
prof
:MichelGagnon local
:worksAt local:dgi .
prof
:MichelGagnon local
:hasName "Michel Gagnon" .
prof
:MichelGagnon local
:hasHomePage <http
://www.professeurs.polymtl.ca/michel.gagnon> .
Pour représenter un littéral simple, on l’écrit tout simplement en le mettant entre guillemets, comme
dans l’exemple précédent, où "Michel Gagnon" est un littéral. Si le littéral a une étiquette de langue,
6
on l’ajoute après le littéral, séparée par le symbole @. Ainsi le littéral "chien" en français serait représentée
par l’expression suivante : "chien"@fr. Finalement, pour un littéral typé, on fait suivre le littéral par les
symboles ^^ suivi du type. Nous avons déjà vu auparavant l’exemple du nombre 10, qui peut être représenté
par le littéral "10"^^xsd:integer.
prof:MichelGagnon local:hasHomePage
<http://www.professeurs.polymtl.ca/michel.gagnon> .
prof:MichelGagnon local:hasName "Michel Gagnon" .
prof:MichelGagnon local:worksAt local:dgi .
Comme il s’agit ici de trois descriptions d’une même ressource, il serait intéressant des les combiner en
une seule description. Avec la notation N3, cela est possible. Il suffit de spécifier la ressource décrite, suivie
de paires <predicat> <objet> séparées par des points-virgule. Notre exemple se retrouve alors avec
la forme suivante :
prof:MichelGagnon
local:hasHomePage <http://www.professeurs.polymtl.ca/michel.gagnon> ;
local:hasName "Michel Gagnon" ;
local:worksAt <http://www.polymtl.ca/Vocabulary#dgi> .
Un noeud vide est représenté par les crochets []. Ainsi, si dans notre exemple l’URI de la personne
n’était pas connue, nous aurions la représentation suivante :
[ ] local:hasHomePage <http://www.professeurs.polymtl.ca/michel.gagnon> ;
local:hasName "Michel Gagnon" ;
local:worksAt <http://www.polymtl.ca/Vocabulary#dgi> .
Remarquez qu’il est possible de mettre toutes les déclarations de propriété d’un noeud vide à l’intérieur
des crochets :
7
@prefix local: <http://www.polymtl.ca/Vocabulary#> .
[ local:hasHomePage <http://www.professeurs.polymtl.ca/michel.gagnon> ;
local:hasName "Michel Gagnon" ;
local:worksAt <http://www.polymtl.ca/Vocabulary#dgi> ] .
L’avantage de cette dernière approche est qu’elle facilite l’écriture lorsque nous avons un noeud vide
comme objet d’un triplet. Ainsi, si nous avions la relation connait et que nous voulions indiquer que le
professeur Jean St-Jean connaît la personne décrite dans l’exemple précédent, nous aurions la représentation
suivante :
prof:JeanStJean local:connait
[ local:hasHomePage <http://www.professeurs.polymtl.ca/michel.gagnon> ;
local:hasName "Michel Gagnon" ;
local:worksAt <http://www.polymtl.ca/Vocabulary#dgi> ] .
<?xml version="1.0"?>
<rdf:RDF
xmlns:local="http://www.polymtl.ca/Vocabulary#"
xmlns:prof="http://www.polymtl.ca/Profs#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
<rdf:Description rdf:about="http://www.polymtl.ca/Profs#MichelGagnon">
<local:worksAt rdf:resource="http://www.polymtl.ca/Vocabulary#dgi"/>
</rdf:Description>
<rdf:Description rdf:about="http://www.polymtl.ca/Profs#MichelGagnon">
<local:hasName>Michel Gagnon</local:hasName>
</rdf:Description>
<rdf:Description rdf:about="http://www.polymtl.ca/Profs#MichelGagnon">
<local:hasHomePage
rdf:resource="http://www.professeurs.polymtl.ca/michel.gagnon"/>
</rdf:Description>
</rdf:RDF>
On remarque que tout le graphe RDF est décrit à l’intérieur des balises rdf:RDF. Plusieurs espaces
de nommage y sont d’abord spécifiés, en particulier celui qui correspond à notre préfixe local. Viennent
ensuite trois descriptions de la ressource MichelGagnon (pour simplifier l’écriture, j’utiliserai parfois un
8
nom abbrégé pour désigner une URI). Remarquons qu’une description d’une ressource est spécifiée par la
balise rdf:Description, avec l’URI de la ressource indiquée par l’attribut rdf:about. On remarque
aussi, pour les deux descriptions dont l’objet est une URI, que cette URI est elle aussi indiquée par un
attribut, cette fois-ci dans une balise correspondant au prédicat. Dans le cas du littéral, la valeur est mise
tout simplement entre les balises qui correspondent au prédicat. Finalement, notons que dans les attributs,
les URI doivent être indiquées au long, tel que requis par la norme XML.
Normalement, lorsque plusieurs descriptions se réfèrent à une même ressource, on utilise une forme
abbrégée qui les réunit toutes en une seule description :
<?xml version="1.0"?>
<!DOCTYPE rdf:RDF [<!ENTITY local "http://www.polymtl.ca/Vocabulary#">
<!ENTITY prof "http://www.polymtl.ca/Profs#">]>
<rdf:RDF
xmlns:local="http://www.polymtl.ca/Vocabulary#"
xmlns:prof="http://www.polymtl.ca/Profs#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
<rdf:Description rdf:about="&prof;MichelGagnon">
<local:worksAt rdf:resource="&local;dgi"/>
<local:hasName>Michel Gagnon</local:hasName>
<local:hasHomePage
rdf:resource="http://www.professeurs.polymtl.ca/michel.gagnon"/>
</rdf:Description>
</rdf:RDF>
Dans l’exemple précédent, nous remarquons que des entités &prof; et &local; ont été définies pour
simplifier l’écriture des attributs.
<?xml version="1.0"?>
<rdf:RDF
xmlns:local="http://www.polymtl.ca/Vocabulary#"
xmlns:prof="http://www.polymtl.ca/Profs#"
9
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
<rdf:Description>
<local:worksAt rdf:resource="http://www.polymtl.ca/Vocabulary#dgi"/>
<local:hasName>Michel Gagnon</local:hasName>
<local:hasHomePage
rdf:resource="http://www.professeurs.polymtl.ca/michel.gagnon"/>
</rdf:Description>
</rdf:RDF>
Supposons maintenant que la propriété hasHomePage est fournie dans une description séparée. Il fau-
drait alors utiliser un identificateur pour le noeud vide :
<?xml version="1.0"?>
<rdf:RDF
xmlns:local="http://www.polymtl.ca/Vocabulary#"
xmlns:prof="http://www.polymtl.ca/Profs#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
<rdf:Description rdf:nodeID="p304">
<local:worksAt rdf:resource="http://www.polymtl.ca/Vocabulary#dgi"/>
<local:hasName>Michel Gagnon</local:hasName>
</rdf:Description>
<rdf:Description rdf:nodeID="p304">
<local:hasHomePage
rdf:resource="http://www.professeurs.polymtl.ca/michel.gagnon"/>
</rdf:Description>
</rdf:RDF>
Un noeud vide ne peut être que le sujet ou l’objet d’un triplet. En aucun cas on ne pourra utiliser une
propriété anonyme, ce qui signifie que le prédicat sera toujours désigné par une URI.
Un noeud vide n’est pas seulement utile pour décrire des ressources sans les nommer. Il permet aussi
de contourner le fait qu’en RDF on ne peut exprimer que des relations binaires. Pour exprimer une relation
R qui implique n arguments, où n > 2, il suffit de choisir un de ces arguments comme étant le sujet de la
relation R (typiquement le premier argument) et de définir l’objet comme un noeud vide. Chaque argument
qui reste est alors représenté comme étant l’objet d’une relation le liant à ce noeud vide.
2.4.2 Littéraux
Comme nous l’avons vu dans l’exemple précédent, qui contient le littéral "Michel Gagnon", un
littéral simple est représenté en l’insérant tout simplement entre les balises qui désignent le prédicat ayant
ce littéral comme valeur. S’il y a en plus la spécification de la langue utilisée, il suffit de mettre l’attribut
xml:lang dans la balise du prédicat et de spécifier la langue en question.
10
En ce qui concerne les littéraux typés, il sont représentés en RDF/XML par l’attribut rdf:datatype,
dont la valeur indique le type utilisé pour interpréter le littéral. Si on ajoutait à notre exemple la date de
dernière mise à jour de la page personnelle, on obtiendrait un représentation comme celle-ci :
<?xml version="1.0"?>
<rdf:RDF
xmlns:prof="http://www.polymtl.ca/Profs#"
xmlns:local="http://www.polymtl.ca/Vocabulary#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
<rdf:Description rdf:about="http://www.polymtl.ca/Profs#MichelGagnon">
<local:hasHomePage>
<rdf:Description rdf:about="http://www.professeurs.polymtl.ca/michel.gagnon">
<local:lastUpdate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">
2005-05-20
</local:lastUpdate>
</rdf:Description>
</local:hasHomePage>
<local:worksAt rdf:resource="http://www.polymtl.ca/Vocabulary#dgi"/>
<local:hasName>Michel Gagnon</local:hasName>
</rdf:Description>
</rdf:RDF>
11
dans un document ayant cette URI et de compléter les descriptions dans des documents séparés. Mais ceci
n’est pas nécessairement la meilleure approche en terme de gestion.
Une autre approche, peut-être plus intéressante, est d’utiliser un mécanisme qui permet de spécifier
explicitement la base qui sera utilisée pour former l’URI, en utilisant l’attribut xml:base dans la balise
RDF du document. Chaque fois qu’on aura un attribut rdf:ID dans ce document, l’URI sera formée en
prenant non pas l’URI du document, mais plutôt celle spécifiée par cet attribut. C’est ainsi qu’on pourra
avoir la même base dans des documents différents.
http://www.w3.org/1999/02/22-rdf-syntax-ns#type
<?xml version="1.0"?>
<rdf:RDF
12
xmlns:local="http://www.polymtl.ca/Vocabulary#"
xmlns:prof="http://www.polymtl.ca/Profs#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
<rdf:Description rdf:about="http://www.polymtl.ca/Profs#MichelGagnon">
<rdf:type
rdf:resource="http://www.polymtl.ca/Vocabulary#AssistantProfessor"/>
<local:worksAt>
<rdf:Description rdf:about="http://www.polymtl.ca/Vocabulary#dgi">
<rdf:type
rdf:resource="http://www.polymtl.ca/Vocabulary#AcademicDepartment"/>
</rdf:Description>
</local:worksAt>
<local:hasName>Michel Gagnon</local:hasName>
<local:hasHomePage>
<rdf:Description
rdf:about="http://www.professeurs.polymtl.ca/michel.gagnon">
<rdf:type rdf:resource="http://www.polymtl.ca/Vocabulary#HomePage"/>
</rdf:Description>
</local:hasHomePage>
</rdf:Description>
</rdf:RDF>
Comme le type d’une ressource est une propriété importante et très utilisée, la syntaxe RDF/XML per-
met une abbréviation, qui consiste tout simplement à remplacer la balise Description par le type de la
ressource et retirer la relation rdf:type associée à la ressource :
<?xml version="1.0"?>
<rdf:RDF
xmlns:local="http://www.polymtl.ca/Vocabulary#"
xmlns:prof="http://www.polymtl.ca/Profs#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
<local:AssistantProfessor
rdf:about="http://www.polymtl.ca/Profs#MichelGagnon">
<local:worksAt>
<local:AcademicDepartment
rdf:about="http://www.polymtl.ca/Vocabulary#dgi"/>
</local:worksAt>
<local:hasName>Michel Gagnon</local:hasName>
<local:hasHomePage>
<local:HomePage
rdf:about="http://www.professeurs.polymtl.ca/michel.gagnon"/>
</local:hasHomePage>
</local:AssistantProfessor>
</rdf:RDF>
13
<?xml version="1.0"?>
<rdf:RDF
xmlns:prof="http://www.polymtl.ca/Profs#"
xmlns:local="http://www.polymtl.ca/Vocabulary#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#w">
<local:AcademicDepartment rdf:about="http://www.polymtl.ca/Vocabulary#dgi"/>
<local:HomePage rdf:about="http://www.professeurs.polymtl.ca/michel.gagnon"/>
<local:AssistantProfessor rdf:about="http://www.polymtl.ca/Profs#MichelGagnon">
<local:hasHomePage
rdf:resource="http://www.professeurs.polymtl.ca/michel.gagnon"/>
<local:worksAt rdf:resource="http://www.polymtl.ca/Vocabulary#dgi"/>
<local:hasName>Michel Gagnon</local:hasName>
</local:AssistantProfessor>
</rdf:RDF>
Dans la notation N3, il existe aussi une abbrévation pour l’identification du type d’une ressource. Il
s’agit tout simplement d’utiliser la propriété a :
local:dgi a local:AcademicDepartment .
<http://www.professeurs.polymtl.ca/michel.gagnon> a local:HomePage .
prof:MichelGagnon
a local:AssistantProfessor ;
local:hasHomePage <http://www.professeurs.polymtl.ca/michel.gagnon> ;
local:hasName "Michel Gagnon" ;
local:worksAt local:dgi .
À noter que RDF n’interdit pas qu’une ressource ait plus d’un type. Mais un seul de ses types pourra
faire l’objet de l’abbréviation de RDF/XML qui permet de remplacer la balise rdf:Description par le
type. Tous les autres types devront être définis explicitement.
2.6 Conteneurs
Il n’est pas rare de vouloir représenter une ressource qui est en fait un conteneur, c’est-à-dire une res-
source qui contient d’autres ressources. On n’a qu’à penser par exemple à un groupe de personnes. On
aimerait donc pouvoir spécifier qu’une ressource est un conteneur et indiquer clairement les relations entre
cette ressource et les entités qu’elle contient. RDF propose trois classes de conteneur : rdf:Bag, rdf:Seq
et rdf:Alt. Le premier désigne un conteneur dont les membres n’ont aucun ordre entre eux, contrairement
au second qui lui suppose l’existence d’un ordre. Le conteneur rdf:Alt désigne un conteneur présentant
des alternatives parmi lesquelles on s’attend à ce qu’une seule soit sélectionnée.
Le conteneur est relié à chacun des ses membres par une relation rdf:_n, où n est un entier. Il va de soi
que dans le cas d’un conteneur de type rdf:Seq, on s’attend à ce que n représente l’ordre du membre en
question. À noter qu’il n’y pas vraiment de contraintes sur la manière de décrire les conteneurs. Par exemple,
RDF n’interdit pas d’avoir deux membres avec la même valeur n, même avec le conteneur rdf:Seq. Il
14
n’interdit pas non plus qu’il y ait des sauts dans la numérotation. Par exemple, on peut très bien décrire un
conteneur de trois membres avec les relations rdf:_1, rdf:_2 et rdf:_4.
Supposons maintenant que notre professeur soit membre d’un département qui contient trois profes-
seurs. La manière la plus naturelle de représenter cela est en utilisant un conteneur rdf:Bag, tel qu’illustré
à la figure 5.
Pour simplifier l’écriture, RDF/XML fournit une abbréviation, en utilisant la relation rdf:li pour
chaque membre, au lieu de la relation spécifique rdf:_n. Un telle notation suppose que les relations
rdf:_1, rdf:_2, et ainsi de suite, sont générées automatiquement. Ainsi, les deux formes suivantes sont
équivalentes :
<?xml version="1.0"?>
<rdf:RDF
xmlns:prof="http://www.polymtl.ca/Profs#"
xmlns:local="http://www.polymtl.ca/Vocabulary#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
<rdf:Description rdf:about="http://www.professeurs.polymtl.ca/michel.gagnon">
<local:lastUpdate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">
2005-05-20
</local:lastUpdate>
</rdf:Description>
<rdf:Description rdf:about="http://www.polymtl.ca/Profs#MichelGagnon">
<local:hasHomePage
15
rdf:resource="http://www.professeurs.polymtl.ca/michel.gagnon"/>
<local:worksAt rdf:resource="http://www.polymtl.ca/Vocabulary#dgi"/>
<local:hasName>Michel Gagnon</local:hasName>
</rdf:Description>
<rdf:Bag rdf:about="http://www.polymtl.ca/Vocabulary#ProfsDepartement">
<rdf:li rdf:resource="http://www.polymtl.ca/Profs#MarieSteMarie"/>
<rdf:li rdf:resource="http://www.polymtl.ca/Profs#JeanStJean"/>
<rdf:li rdf:resource="http://www.polymtl.ca/Profs#MichelGagnon"/>
</rdf:Bag>
</rdf:RDF>
<?xml version="1.0"?>
<rdf:RDF
xmlns:prof="http://www.polymtl.ca/Profs#"
xmlns:local="http://www.polymtl.ca/Vocabulary#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
<rdf:Description rdf:about="http://www.professeurs.polymtl.ca/michel.gagnon">
<local:lastUpdate rdf:datatype="http://www.w3.org/2001/XMLSchema#date"
>2005-05-20</local:lastUpdate>
</rdf:Description>
<rdf:Description rdf:about="http://www.polymtl.ca/Profs#MichelGagnon">
<local:hasHomePage
rdf:resource="http://www.professeurs.polymtl.ca/michel.gagnon"/>
<local:worksAt rdf:resource="http://www.polymtl.ca/Vocabulary#dgi"/>
<local:hasName>Michel Gagnon</local:hasName>
</rdf:Description>
<rdf:Bag rdf:about="http://www.polymtl.ca/Vocabulary#ProfsDepartement">
<rdf:_1 rdf:resource="http://www.polymtl.ca/Profs#MarieSteMarie"/>
<rdf:_2 rdf:resource="http://www.polymtl.ca/Profs#JeanStJean"/>
<rdf:_3 rdf:resource="http://www.polymtl.ca/Profs#MichelGagnon"/>
</rdf:Bag>
</rdf:RDF>
2.7 Collections
Un des désavantages avec les conteneurs est qu’il n’est pas possible de les considérer comme des en-
sembles fermés. Ainsi, si dans une description on spécifie l’existence de trois éléments dans un conteneur,
on n’a jamais de garantie qu’il ne contient que ces trois éléments. Rien n’empêche de spécifier d’autres
éléments de ce conteneur dans une autre description. Pour pallier cette lacune, RDF permet de définir des
collections, qui sont en quelque sorte des listes. La liste vide est représentée par une ressource spéciale
pré-définie dont l’URI est rdf:nil. On construit une liste de manière récursive en utilisant le prédicat
rdf:first pour indiquer le premier élément de la liste, et le prédicat rdf:rest pour indiquer le reste
de la liste, qui est lui-même une liste.
Si, par exemple, on sait que les trois professeurs cités dans le modèle de la figure 5 sont les seuls du
département (un petit département !), on peut utiliser une liste au lieu d’un conteneur :
<?xml version="1.0"?>
<rdf:RDF
16
xmlns:prof="http://www.polymtl.ca/Profs#"
xmlns:local="http://www.polymtl.ca/Vocabulary#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
<rdf:Description rdf:about="http://www.professeurs.polymtl.ca/michel.gagnon">
<local:lastUpdate rdf:datatype="http://www.w3.org/2001/XMLSchema#date"
>2005-05-20</local:lastUpdate>
</rdf:Description>
<rdf:Description rdf:about="http://www.polymtl.ca/Profs#MichelGagnon">
<local:hasHomePage
rdf:resource="http://www.professeurs.polymtl.ca/michel.gagnon"/>
<local:worksAt rdf:resource="http://www.polymtl.ca/Vocabulary#dgi"/>
<local:hasName>Michel Gagnon</local:hasName>
</rdf:Description>
<rdf:List rdf:about="http://www.polymtl.ca/Vocabulary#ProfsDepartement">
<rdf:first rdf:resource="http://www.polymtl.ca/Profs#MarieSteMarie"/>
<rdf:rest>
<rdf:List>
<rdf:first rdf:resource="http://www.polymtl.ca/Profs#JeanStJean"/>
<rdf:rest>
<rdf:List>
<rdf:first rdf:resource="http://www.polymtl.ca/Profs#MichelGagnon"/>
<rdf:rest
rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#nil"/>
</rdf:List>
</rdf:rest>
</rdf:List>
</rdf:rest>
</rdf:List>
</rdf:RDF>
Comme cette syntaxe est très lourde, il existe donc une abbréviation, mais qui ne pourra être utilisée
que si la liste est l’objet d’un triplet, ce qui n’est pas le cas dans notre exemple. Supposons donc qu’il existe
une ressource local:Departement liée à notre liste par la relation local:staff. Nous pourrions
alors utiliser une l’attribut rdf:parseType="Collection" dans la balise qui représente la propriété,
et fournir la liste des éléments. Ainsi, notre exemple aurait alors la forme suivante :
<?xml version="1.0"?>
<rdf:RDF
xmlns:prof="http://www.polymtl.ca/Profs#"
xmlns:local="http://www.polymtl.ca/Vocabulary#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
<rdf:Description rdf:about="http://www.professeurs.polymtl.ca/michel.gagnon">
<local:lastUpdate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">
2005-05-20
</local:lastUpdate>
</rdf:Description>
<rdf:Description rdf:about="http://www.polymtl.ca/Profs#MichelGagnon">
17
<local:hasHomePage
rdf:resource="http://www.professeurs.polymtl.ca/michel.gagnon"/>
<local:worksAt rdf:resource="http://www.polymtl.ca/Vocabulary#dgi"/>
<local:hasName>Michel Gagnon</local:hasName>
</rdf:Description>
<local:Departement>
<local:staff rdf:parseType="Collection">
<rdf:Description rdf:about="http://www.polymtl.ca/Profs#MarieSteMarie"/>
<rdf:Description rdf:about="http://www.polymtl.ca/Profs#JeanStJean"/>
<rdf:Description rdf:about="http://www.polymtl.ca/Profs#MichelGagnon"/>
</local:staff>
</local:Departement>
</rdf:RDF>
Il est important de remarquer que si on utilise la forme non abbrégée pour décrire une liste, il n’y a
pas réellement de contraintes sur l’utilisation des prédicats rdf:first et rdf:rest. Rien n’empêche
d’utiliser plus d’une occurrence de ces relations pour un même noeud. Par exemple, on pourrait les utiliser
pour décrire un arbre au lieu d’une simple liste.
2.8 Réification
Supposons qu’un triplet est ajouté dans un modèle et que nous voulions spécifier l’auteur de ce triplet
ou la date de cet ajout. Avec ce que nous connaissons jusqu’à maintenant, il ne serait pas possible de le faire,
puisqu’on ne peut pas désigner un triplet au complet. Pour y arriver, il faut utiliser une technique appelée
réification.
L’idée consiste à ajouter une ressource de type rdf:Statement. Une telle ressource représente un tri-
plet. Pour spécifier les informations contenues dans ce triplet, on peut utiliser les propriétés rdf:subject,
rdf:predicate et rdf:objet.
La figure 6 illustre un exemple de réification, où on précise que Michel Gagnon a lui-même fourni
l’information sur son lieu de travail. Voici une représentation de ce modèle avec la syntaxe RDF/XML :
<?xml version="1.0"?>
<rdf:RDF
xmlns:prof="http://www.polymtl.ca/Profs#"
xmlns:local="http://www.polymtl.ca/Vocabulary#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<rdf:Description rdf:about="http://www.polymtl.ca/Profs#MichelGagnon">
<local:worksAt rdf:resource="http://www.polymtl.ca/Vocabulary#dgi"/>
</rdf:Description>
<rdf:Statement>
<rdf:predicate rdf:resource="http://www.polymtl.ca/Vocabulary#worksAt"/>
<dc:creator rdf:resource="http://www.polymtl.ca/Profs#MichelGagnon"/>
<rdf:object rdf:resource="http://www.polymtl.ca/Vocabulary#dgi"/>
<rdf:subject rdf:resource="http://www.polymtl.ca/Profs#MichelGagnon"/>
18
</rdf:Statement>
</rdf:RDF>
Un problème demeure, par contre. On peut identifier une ressource qui correspond à un triplet et indi-
quer quels sont le sujet, le prédicat et l’objet de ce triplet. Mais il n’est pas possible de dire que ce triplet
correspond à un triplet spécifique dans un modèle RDF. Bien sûr, on peut rechercher un triplet qui possède le
même sujet, le même prédicat et le même objet, mais ceci n’est pas une garantie qu’il s’agisse bien du même
triplet. Après tout, rien n’empêche d’avoir deux triplets identiques dans un même modèle. Cela pourrait se
produire par exemple, si deux personnes décrivent une même ressource dans deux documents différents. Il
se pourra alors que certains triplets identiques se retrouvent dans les deux descriptions.
Dans la syntaxe RDF/XML, il existe un abbréviation qui permet de créer automatiquement la réification
d’un triplet. Il s’agit tout simplement d’ajouter l’attribut rdf:ID à la propriété. Ceci aura pour effet de
créer automatiquement une ressource de type rdf:Statement décrivant le triplet en question, et dont
l’URI d’identification sera celle fournie à l’attribut rdf:ID de la propriété. Ceci permet donc de créer un
lien indirect entre le triplet et la description réifiée de ce triplet. Mais il est important de noter que même
si l’URI de la réification est la même que celle du prédicat du triplet, cela ne représente toujours pas une
manière formelle d’indiquer l’identité entre ces deux entités. Pour y arriver, il faudrait vraiment que nous
puissions identifier tous le triplet comme une ressource, ce qui, nous l’avons déjà vu, n’est pas possible en
RDF. Voici donc comment notre exemple pourrait être représentée avec cet abbréviation :
<?xml version="1.0"?>
<rdf:RDF
xmlns:prof="http://www.polymtl.ca/Profs#"
xmlns:local="http://www.polymtl.ca/Vocabulary#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
19
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<rdf:Description rdf:about="http://www.polymtl.ca/Profs#MichelGagnon">
<local:worksAt
rdf:ID="enonce1" rdf:resource="http://www.polymtl.ca/Vocabulary#dgi"/>
</rdf:Description>
<rdf:Statement rdf:about="#enonce1">
<dc:creator rdf:resource="http://www.polymtl.ca/Profs#MichelGagnon"/>
</rdf:Statement>
</rdf:RDF>
2.9 Exercices
■ Exercice 2.1
Dessinez un graphe RDF représentant la situation suivante : une rencontre entre le président des États-Unis
et le premier ministre du Canada, qui a eu lieu à Toronto, le 24 avril 2005.
■ Exercice 2.2
Soit le graphe RDF suivant représenté en utilisant le langage Turtle :
ex:MichelGagnon
rdf:type ex:Professeur, ex:Personne;
ex:enseigne
[rdf:first ex:inf6410 ;
rdf:rest [rdf:first ex:inf1010 ;
rdf:rest rdf:nil]] ;
ex:travaille ex:Poly .
[] ex:connait ex:MichelGagnon ;
ex:travaille [rdf:type ex:Universite] .
a) Dessinez ce graphe.
b) Traduisez en représentation RDF/XML la plus abbrégée possible.
■ Exercice 2.3
Soit la situation suivante :
Marie a eu deux enfants avec Robert : une fille, qui s’appelle Anne et un garçon, qui s’ap-
pelle André. Elle habite maintenant avec Luc, avec qui elle a eu une autre fille, qui s’appelle
Mélanie. Robert habite à Montréal, avec André. Marie et Luc habitent à Québec avec Anne,
Mélanie et Paul. Paul est le fils que Luc a eu avec Claudine dans son premier mariage.
20
a) Dessinez un graphe RDF qui représente le mieux cette situation. Assurez-vous qu’un minimum de chan-
gements soit requis dans le graphe si un membre de cette famille décide de déménager, et si Marie déménage
dans une autre ville avec tous ceux qui habitent avec elle.
■ Exercice 2.4
<?xml version="1.0"?>
<!DOCTYPE rdf:RDF [
<!ENTITY xsd "http://www.w3.org/2001/XMLSchema#" >
<!ENTITY rdfs "http://www.w3.org/2000/01/rdf-schema#" >
<!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#" >
]>
<rdf:RDF
xmlns="http://www.polymtl.ca#"
xml:base="http://www.polymtl.ca#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#">
<A rdf:ID="x1">
<p rdf:parseType="Collection">
<rdf:Description rdf:ID="x2"/>
<rdf:Description>
<q rdf:resource="x3"/>
</rdf:Description>
</p>
</A>
</rdf:RDF>
■ Exercice 2.5
Soit la description suivante fournie en RDF/XML :
<?xml version="1.0"?>
<rdf:RDF
xmlns:local="http://www.polymtl.ca/Vocabulaire#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:rdfs="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<local:B rdf:about="http://www.polymtl.ca/Vocabulaire#b1">
<local:r2>
<rdf:Description rdf:about="http://www.polymtl.ca/Vocabulaire#a1">
<rdf:type>
<rdf:Description rdf:about="http://www.polymtl.ca/Vocabulaire#A">
<local:diff rdf:resource="http://www.polymtl.ca/Vocabulaire#B"/>
</rdf:Description>
</rdf:type>
<local:r1>
<local:A />
</local:r1>
</rdf:Description>
</local:r2>
21
</local:B>
<rdf:Alt rdf:about="http://www.polymtl.ca/Vocabulaire#c">
<rdf:_1 rdf:resource="http://www.polymtl.ca/Vocabulaire#x1" />
<rdf:_2 rdf:resource="http://www.polymtl.ca/Vocabulaire#x2" />
</rdf:Alt>
</rdf:RDF>
b) Représentez ce graphe RDF dans le format Turtle. Assurez-vous que votre représentation soit la plus
abrégée possible.
3 RDF Schema
Nous avons vu, dans la section 2.5, que l’on peut utiliser la propriété rdf:type pour distinguer le type
de chacune des ressources décrites. Mais que représente réellement la relation rdf:type ? En d’autres
mots, lorsqu’on applique la propriété rdf:type à une ressource, quel est le type de la ressource obtenue ?
Ou encore, dans la terminologie de RDF, quel est le type de l’objet dans un triplet dont le prédicat est
rdf:type ?
Il s’agit en fait d’un type de ressource spécial, puisqu’il ne s’agit pas d’une entité simple mais en fait
d’une classe d’entités. Quand on dit qu’une ressource R et du type T , on se trouve à définir implicitement
l’ensemble de toutes les ressources qui ont en commun d’avoir le type T . Pour exprimer ce genre de concepts
et d’autres qui y sont reliés, un vocabulaire précis a été proposé. Pour des raisons historiques, ce vocabulaire
a été dénommé RDF Schema, abbrégé RDFS. Comme cela porte à confusion avec XML Schema, qui n’a
absolument rien à voir avec RDF Schema, on parle maintenant plutôt de RDF Vocabulary Language, même
si le nom original est resté.
Le prefixe pour tous les éléments du vocabulaire RDFS est le suivant (dans la suite du texte, nous utiliserons
l’alias rdfs: pour ce préfixe) :
http://www.w3.org/2000/01/rdf-schema#
3.1 Classes
Le premier élément important de ce vocalulaire est rdfs:Class qui représente justement le type de la
ressource obtenue comme valeur lorsque la propriété rdf:type est appliquée à une ressource. Ainsi, les
ressources local:AcademicDepartment, local:HomePage et local:AssistantProfessor
ont toutes la valeur rdfs:Class pour la propriété rdf:type, comme illustré à la figure 7.
Comme on l’a déjà vu plus tôt, une ressource peut appartenir à plus d’une classe. Par exemple, rien ne
nous empêche d’ajouter un triplet indiquant que Michel Gagnon est aussi de type local:Humain (à noter
que seul un des types peut être utilisé comme abdréviation à la place de la balise rdf:Description) :
<?xml version="1.0"?>
<rdf:RDF
22
F IGURE 7 – Classes
xmlns:prof="http://www.polymtl.ca/Profs#"
xmlns:local="http://www.polymtl.ca/Vocabulary#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
<rdfs:Class rdf:about="http://www.polymtl.ca/Vocabulary#HomePage"/>
<rdfs:Class rdf:about="http://www.polymtl.ca/Vocabulary#AssistantProfessor"/>
<rdfs:Class rdf:about="http://www.polymtl.ca/Vocabulary#AcademicDepartment"/>
<local:AcademicDepartment rdf:about="http://www.polymtl.ca/Vocabulary#dgi"/>
<local:HomePage rdf:about="http://www.professeurs.polymtl.ca/michel.gagnon"/>
<local:AssistantProfessor rdf:about="http://www.polymtl.ca/Profs#MichelGagnon">
<rdf:type rdf:resource="http://www.polymtl.ca/Vocabulary#Humain"/>
<local:hasHomePage
rdf:resource="http://www.professeurs.polymtl.ca/michel.gagnon"/>
<local:worksAt rdf:resource="http://www.polymtl.ca/Vocabulary#dgi"/>
<local:hasName>Michel Gagnon</local:hasName>
</local:AssistantProfessor>
</rdf:RDF>
RDFS permet de définir des hiérarchies de classes, en indiquant qu’une classe est sous-classe d’une
autre classe, par le biais de la propriété rdfs:subClassOf. Si une classe C est sous-classe de C′ , cela
implique que si une ressource est décrite comme étant de type C, on peut déduire automatiquement qu’elle
est aussi de type C′ . À noter que la relation rdfs:subClassOf est transitive. La figure 8 illustre une
extension de notre exemple comprenant une hiérarchie des classes de professeurs. On spécifie aussi qu’un
département est un lieu de travail.
23
F IGURE 8 – Hiérachie de classes
3.2 Propriétés
Il est naturel de supposer que toutes les ressources ont un type. Ceci vaut aussi pour les propriétés qui,
rappelons-le, sont elles aussi considérées comme des ressources. En RDF, toutes les propriétés ont pour type
la classe rdf:Property. Ceci signifie donc que notre exemple implique l’existence des triplets suivants :
Il va de soi que le triplet suivant est implicite pour tous les graphes RDF :
Il est intéressant de noter que la classe rdf:Property ne fait pas partie du vocabulaire de RDFS,
mais plutôt du vocabulaire de base de RDF. On comprend facilement ce choix en considérant le fait que la
propriété rdf:type fait partie du vocabulaire de RDF et que toute ressource doit avoir un type. Il est alors
naturel que la classe rdf:Property fasse partie du vocabulaire RDF.
De la même manière que l’on peut établir des hiérarchies de classes, on peut définir des hiérarchies de
propriétés, en utilisant la relation rdfs:subPropertyOf. Mais le plus intéressant en RDFS est proba-
blement la possibilité de spécidier le domaine ou l’image d’une propriété. On le fait en ajoutant un triplet
qui indique un type de ressource qu’on peut retrouver comme sujet ou objet d’une propriété, en utilisant
les relations rdfs:domain ou rdfs:range, respectivement. Ainsi, en revenant à notre exemple, on
peut spécifier que c’est un membre de personnel (StaffMember) qui travaille (worksAt) à un lieu de travail
24
F IGURE 9 – Hiérarchie de propriétés
25
(WorkPlace). On peut aussi spécifier que la propriété "travailler" est une sous-propriété de la propriété "avoir
activité". Tout ceci est illustré à la figure 9.
Une conséquence du fait qu’une propriété P soit sous-propriété d’une propriété P′ est que tout domaine
(ou image) défini pour P′ est automatiquement défini pour la propriété P.
Une propriété peut avoir plus d’un domaine, mais il faut bien comprendre ce que cela signifie : toute res-
source à laquelle s’applique cette propriété appartient nécessairement à toutes les classes spécifiées comme
faisant partie du domaine de la propriété. De même pour l’image. Supposons par exemple la propriété
local:hasMother a pour domaine les classes local:Woman et local:Person. Supposons main-
tenant qu’on applique cette propriété à la ressource prof:MarieSteMarie. Automatiquement, on doit
pouvoir déduire que cette personne est à la fois une personne et une femme.
Il est très important de comprendre que les spécifications de domaine ou d’image en RDF ne sont pas
des contraintes. Quand on spécifie qu’une certaine classe est dans le domaine d’une propriété, on n’exige
pas que toute ressource à laquelle la propriété est appliquée soit préalablement définie comme appartenant
à cette classe. On peut le voir comme une source d’information supplémentaire, c’est-à-dire que dès qu’on
aura une ressource à laquelle la propriété est appliquée, on pourra déduire que cette ressource appartient à
la classe en question, même si cela n’est spécifié nulle part de manière explicite.
On remarquera aussi que les propriétés en RDFS sont globales. On ne peut pas, par exemple, spécifier
qu’une propriété est locale à une classe, comme on le ferait normalement dans un langage de programmation
orienté objet. Ceci a pour effet qu’on pourra toujours spécifier d’autres domaines ou d’autres images d’une
propriétés, à partir du moment où on connaît son URI. Cette caractéristique est très importante et démontre
bien un biais dans le design de RDF, où on a voulu insister plus sur les relations entre les ressources que les
ressources elles-mêmes.
26