← Suite du cours #3

Du Graphe aux Motifs

Turtle ne se limite pas aux simples triplets.
Raccourcis, chemins, listes, nœuds anonymes —
le langage qui donne des ailes à RDF.

LIEN AVEC LE COURS #3

Du triplet simple au langage d'ingénieur

Dans le cours #2, on a découvert Turtle : sujet prédicat objet. Dans le cours #3, on a utilisé RDF pour représenter des ontologies OWL. Mais Turtle, c'est bien plus qu'une syntaxe à triplet unique.

Ce quatrième cours explore la face cachée de Turtle : les raccourcis qui transforment un listing verbeux en un graphe compact, les nœuds anonymes qui évitent de nommer l'innommable, les listes qui encodent des séquences, et les chemins de propriétés qui parcourent le graphe comme on suivrait une piste dans une forêt profonde.

ex:Socrate ──rdf:type──▶ ex:Humain
├──ex:nom──▶ "Socrate"@el
├──ex:maitreDe──▶ ex:Platon ──ex:maitreDe──▶ ex:Aristote
└──ex:eleve──▶ [ _:b1 ] (anonyme)
« Un langage de représentation de connaissances sans raccourcis syntaxiques, c'est comme un couteau suisse sans ouvre-boîte : ça marche, mais c'est frustrant. » — Un ingénieur du W3C qui a passé trop de temps à écrire des triplets à la main

Ce cours suppose que vous maîtrisez les bases de Turtle (cours #2, chapitre 6). On va maintenant ouvrir le capot et voir tout ce que le standard peut faire pour vous.

CHAPITRE 1 CŒUR

Arrêtez d'écrire le même sujet 40 fois

Le problème existentiel de tout rédacteur Turtle : on a un seul sujet et plein de triplets à écrire. Socrate a 15 propriétés. Vous allez recopier ex:Socrate 15 fois ? Non. Vous allez utiliser le point-virgule et la virgule.

Le point-virgule ; : même sujet, prédicats différents

Quand plusieurs triplets partagent le même sujet, on peut chaîner les prédicats avec ; :

Turtle
# Version longue (11 lignes, on pleure)
ex:Socrate  rdf:type          ex:Humain .
ex:Socrate  ex:estLeMaitreDe  ex:Platon .
ex:Socrate  ex:estLeMaitreDe  ex:Aristote .
ex:Socrate  ex:age            "70"^^xsd:integer .
ex:Socrate  ex:nom            "Socrate"@grc .
ex:Socrate  ex:nom            "Σωκράτης"@grc .

# Version courte (point-virgule, plus de larmes)
ex:Socrate  rdf:type          ex:Humain ;
            ex:estLeMaitreDe  ex:Platon ,
                              ex:Aristote ;
            ex:age            "70"^^xsd:integer ;
            ex:nom            "Socrate"@grc ,
                              "Σωκράτης"@grc .

La virgule , : même sujet ET même prédicat

Quand en plus le prédicat est identique, la virgule permet de lister les objets sans répéter le prédicat. C'est magique.

Turtle
# Avant : répétition du prédicat
ex:Socrate  ex:estLeMaitreDe  ex:Platon .
ex:Socrate  ex:estLeMaitreDe  ex:Aristote .
ex:Socrate  ex:estLeMaitreDe  ex:Xenophon .

# Après : point-virgule + virgule
ex:Socrate  ex:estLeMaitreDe  ex:Platon ,
                              ex:Aristote ,
                              ex:Xenophon .

# Mélange des deux :
ex:Socrate  rdf:type          ex:Humain ;
            ex:estLeMaitreDe  ex:Platon ,
                              ex:Aristote ,
                              ex:Xenophon ;
            ex:age            "70"^^xsd:integer .
🧠 Anatomie d'une ligne Turtle :
sujet prédicat1 objet1 , objet2 ; prédicat2 objet3 .
La virgule dit : « même sujet, même prédicat, objet suivant ».
Le point-virgule dit : « même sujet, prédicat suivant ».
Le point dit : « j'ai fini, j'arrête, promis ».
C'est comme une phrase bien ponctuée. Mais en moins poétique.

La notation a : sucre pour rdf:type

Le prédicat rdf:type (qui signifie « est un ») est tellement courant qu'il a sa propre notation abrégée : a.

Turtle
# Version classique
ex:Socrate  rdf:type  ex:Humain .

# Version sucrée (les deux sont strictement identiques)
ex:Socrate  a  ex:Humain .

# Avec les raccourcis :
ex:Socrate  a       ex:Humain ;
            ex:nom  "Socrate"@grc .

# On peut enchaîner les types :
ex:Socrate  a  ex:Humain , ex:Philosophe , ex:Athénien .
📜 Origine : Le a vient de la syntaxe N3 (Notation 3), une extension de Turtle inventée par Tim Berners-Lee lui-même. L'idée : puisque « est un » est le prédicat le plus utilisé dans tous les graphes RDF, autant lui donner la lettre la plus courte de l'alphabet. Logique. En N3, a signifie littéralement « is a ». L'anglais au service de la brièveté.

📝 Exercice mental

Réécrivez ces triplets en deux lignes avec ;, ,, a : :Platon rdf:type :Humain . :Platon ex:age 80 . :Platon ex:nom "Platon" . :Platon ex:nom "Πλάτων" .

⚠️ Piège

Le a ne peut être utilisé que comme prédicat. Vous ne pouvez pas écrire ex:Humain a ex:Socrate pour dire « Humain a pour instance Socrate ». Ça ne marche pas. La vie est injuste.

CHAPITRE 2 PRATIQUE

Nœuds anonymes : nommer l'innommable

Parfois, un nœud existe, mais on ne veut pas (ou on ne peut pas) lui donner d'URI. C'est une ressource sans nom. En RDF, on appelle ça un nœud blanc (blank node).

« Dans le web sémantique, il est tout à fait acceptable d'exister sans identifiant. Certains diraient que c'est une forme de nirvana numérique. » — Un bouddhiste RDF (oui, ça existe)

Syntaxe [] avec contenu

Un nœud anonyme se note avec des crochets []. On peut y mettre des propriétés à l'intérieur :

Turtle
# Un Humain sans nom (littéralement)
ex:Socrate  ex:aPourEleve  [
    a  ex:Humain ;
    ex:nom  "Inconnu"@fr
] .

# Ceci crée deux triplets avec un blank node intermédiaire :
ex:Socrate  ex:aPourEleve  _:b1 .
_:b1  rdf:type  ex:Humain .
_:b1  ex:nom     "Inconnu"@fr .

Les crochets ouvrent un scope : tout ce qui est à l'intérieur décrit un nœud anonyme qui est l'objet du triplet parent.

Syntaxe [] vide : nœud anonyme sans propriété

Parfois on veut juste dire « il existe une relation » sans décrire la cible :

Turtle
# Socrate a un maître (qu'on ne connaît pas / qu'on ne décrit pas)
ex:Socrate  ex:aPourMaitre  [] .

# Strictement équivalent à :
ex:Socrate  ex:aPourMaitre  _:b1 .

Nœuds anonymes comme sujets

On peut aussi décrire un nœud anonyme en le réutilisant avec [] comme sujet. Turtle permet d'utiliser des crochets des deux côtés :

Turtle
# Un événement anonyme (sans URI)
[
    a  ex:Evenement ;
    ex:type  "naissance"@fr ;
    ex:lieu  ex:Athenes ;
    ex:date  "-470"^^xsd:gYear
]  ex:aPourActeur  ex:Socrate .

# Noter le sujet entre crochets, suivi du prédicat-objet
⚠️ Attention : Les blank nodes sont pratiques, mais impossibles à référencer depuis l'extérieur. Vous ne pouvez pas créer un lien HTTP vers un blank node. C'est comme une personne sans numéro de téléphone : elle existe, mais personne ne peut l'appeler. C'est triste, mais c'est RDF.

En SPARQL, les blank nodes sont représentés par _:b1, _:b2, etc. Mais ces identifiants sont locaux à chaque fichier : un _:b1 dans un fichier n'est pas le même que _:b1 dans un autre. La solitude du blank node.

Quand utiliser les nœuds anonymes ?

SituationBlank node ?Pourquoi
Une personne a une adresse complète qu'on ne cite jamais ailleurs✅ OuiL'adresse n'a pas d'identité propre
Un livre a un auteur qu'on retrouve dans d'autres livres❌ NonIl a besoin d'une URI pour être référencé
Un triplet dont l'objet est juste « il existe »✅ OuiPas besoin de décrire plus
Un événement historique unique qu'on décrit en détail⚠️ DébatSi vous voulez le lier depuis d'autres données, donnez-lui une URI

🧪 Variation : imbrication

Les [] peuvent s'imbriquer : :Socrate :maitreDe [ :nom "Platon" ; :age 80 ] . Un blank node dans un blank node. C'est des tortues jusqu'en bas.

🔄 Variation : listes anonymes

Combinaison avec les listes : :Socrate :eleves ( [ :nom "Platon" ] [ :nom "Aristote" ] ) .

CHAPITRE 3 STRUCTURE

Listes : quand l'ordre compte

RDF est un graphe, pas un arbre. En théorie, il n'y a pas d'ordre entre les triplets. Mais parfois, l'ordre est important : les ingrédients d'une pizza, les enfants dans l'ordre de naissance, les étapes d'une recette. Pour ça, RDF a inventé les listes.

Le pattern rdf:first / rdf:rest

Une liste RDF est une liste chaînée à la Lisp. Chaque élément pointe vers le suivant :

Turtle
# Une liste de deux ingrédients (en interne RDF)
ex:Margherita  ex:ingredients  _:l1 .
_:l1  rdf:first  ex:Mozzarella .
_:l1  rdf:rest    _:l2 .
_:l2  rdf:first  ex:Tomate .
_:l2  rdf:rest    rdf:nil .
ex:Margherita ──▶ex:ingredients──▶ _:l1
_:l1 ──rdf:first──▶ ex:Mozzarella
└──rdf:rest───────▶ _:l2
_:l2 ──rdf:first──▶ ex:Tomate
└──rdf:rest───────▶ rdf:nil

La syntaxe raccourcie (...)

Fort heureusement, personne n'écrit les listes RDF à la main. Turtle propose une syntaxe parenthésée :

Turtle
# La même liste, en 10 fois moins de lignes
ex:Margherita  ex:ingredients  ( ex:Mozzarella ex:Tomate ) .

# Liste vide
ex:Platon  ex:enfants  () .

# Liste avec des littéraux
ex:Socrate  ex:oeuvres  ( "Apologie" "Criton" "Phédon" "République" ) .

# Liste avec des nœuds anonymes
ex:Socrate  ex:eleves  ( [ ex:nom "Platon" ] [ ex:nom "Aristote" ] ) .

Attention : liste ≠ ensemble de triplets

Il y a une différence fondamentale entre une liste et une série de triplets avec le même prédicat :

Turtle
# ENSEMBLE (pas d'ordre, pas de notion de totalité)
ex:Socrate  ex:eleve  ex:Platon , ex:Aristote .

# LISTE (ordre préservé, notion de « ces éléments et pas d'autres »)
ex:Socrate  ex:eleves  ( ex:Platon ex:Aristote ) .

# Sémantique différente :
# La 1ʳᵉ version dit : Socrate a des élèves (parmi d'autres peut-être)
# La 2ᵉ version dit : la liste des élèves de Socrate EST [Platon, Aristote]
🏛️ Point culture : La structure rdf:first/rdf:rest est directement inspirée des cons et cdr du langage Lisp (1958). Le W3C a littéralement recyclé une structure de données de 40 ans pour le web sémantique. Quand on a une bonne idée, on la garde. Et rdf:nil, c'est la version RDF de nil en Lisp. Le web sémantique doit beaucoup à John McCarthy (inventeur de Lisp), même s'il ne l'a jamais su.

📏 Mesure de taille

Une liste de n éléments génère 2n+1 triplets RDF en interne (n × first + n × rest + rdf:nil). Le confort syntaxique a un coût.

🔁 Listes imbriquées

On peut avoir des listes dans des listes : ex:menu ( (ex:entrée ex:plat) (ex:dessert ex:café) ) . Les parenthèses s'emboîtent.

🧮 Découpage

En SPARQL, on peut déconstruire les listes avec ?l rdf:first ?e ou utiliser des extensions comme SPARQL 1.2 pour déstructurer directement.

CHAPITRE 4 NUANCES

Littéraux : quand les mots ont des types

Les littéraux sont les valeurs concrètes : chaînes, nombres, dates, booléens. En Turtle, ils peuvent être enrichis d'étiquettes de langue et de types de données.

Étiquettes de langue avec @

Un même nom dans différentes langues, c'est le quotidien du web multilingue :

Turtle
ex:Socrate  ex:nom  "Socrate"@fr ,
                     "Socrates"@en ,
                     "Σωκράτης"@grc ,
                     "سقراط"@ar .

# Les étiquettes suivent le standard BCP47
# @fr = français, @en = anglais, @grc = grec ancien, @ar = arabe
# On peut préciser la région : @en-US, @fr-CA, @zh-Hans

Typage avec ^^

Pour préciser qu'une valeur est un entier, une date, un booléen :

Turtle
# Littéraux typés
ex:Socrate  ex:age          "70"^^xsd:integer .
ex:Platon   ex:anneeNaiss  "-428"^^xsd:gYear .
ex:Aristote ex:estVivant   "false"^^xsd:boolean .
ex:Socrate  ex:taille      "1.70"^^xsd:decimal .

# Les types XSD les plus courants :
# xsd:string, xsd:integer, xsd:decimal, xsd:boolean
# xsd:date, xsd:dateTime, xsd:gYear, xsd:gYearMonth
# xsd:float, xsd:double, xsd:hexBinary, xsd:base64Binary

Sucre : les raccourcis de types

Turtle offre des raccourcis syntaxiques pour les types courants :

Turtle
# Entiers (xsd:integer implicite)
ex:Socrate  ex:age  70 .

# Décimaux (xsd:decimal implicite)
ex:Socrate  ex:taille  1.70 .

# Booléens (xsd:boolean implicite)
ex:Socrate  ex:mortel  true .    # ou false

# Chaîne simple (xsd:string implicite)
ex:Socrate  ex:nom  "Socrate" .

# Identiques en interne :
ex:Socrate  ex:age  "70"^^xsd:integer .
# et
ex:Socrate  ex:age  70 .
# produisent exactement le même triplet

Chaînes multilignes et échappement

Pour les textes longs, Turtle propose des triples guillemets :

Turtle
# Chaîne longue (peut contenir des retours à la ligne)
ex:Socrate  ex:citation  """
    Je ne sais qu'une chose :
    c'est que je ne sais rien.
    — Socrate
"""@fr .

# Échappement dans les chaînes
ex:Socrate  ex:citation  "Il disait : \"Connais-toi toi-même\""@fr .
🔢 Point technique : En Turtle, 1 (sans guillemets) est un entier. "1" (avec guillemets) est une chaîne. "1"^^xsd:integer est un entier au format chaîne. "1"^^xsd:string est une chaîne explicitement typée. Ces trois valeurs sont différentes en RDF. Oui, le web sémantique fait la différence entre le nombre 1 et le caractère « 1 ». C'est taquin, mais précis.

🌍 Langues rares

BCP47 permet des langues comme @grc (grec ancien), @la (latin), @cu (vieux slave), @non (vieux norrois). Parfait pour décrire les sagas islandaises en RDF.

🧮 Précision décimale

xsd:decimal est exact (base 10). xsd:float est approché (base 2). 1.70 en Turtle est un xsd:decimal exact. Pas d'arrondi. Votre banquier approuve.

CHAPITRE 5 MOTEUR

Property Paths : naviguer dans le graphe

Les chemins de propriétés (property paths) sont l'un des ajouts les plus puissants de SPARQL 1.1 (et Turtle les supporte pour la définition de graphes). Ils permettent de parcourir le graphe sans connaître sa structure exacte.

« Un chemin de propriété, c'est comme un explorateur qui suivrait des flèches dans une grotte sans savoir où elles mènent. Parfois il arrive au trésor. Parfois il tourne en rond. Mais il apprend des choses en chemin. » — Indiana Jones, professeur de web sémantique à l'université perdue

Les opérateurs de base

OpérateurSyntaxeSensExemple SPARQL
Séquence/ p1 puis p2 (composition) ex:maitreDe / ex:maitreDe
Union| p1 ou p2 (alternative) ex:maitreDe | ex:eleve
Un ou plus+ p1, p1/p1, p1/p1/p1… ex:ancetreDe+
Zéro ou plus* p1, p1/p1… ou juste soi-même ex:influence*
Optionnel? p1 ou rien (zéro ou un) ex:surnom?
Inverse^ Parcourir dans le sens inverse ^ex:maitreDe
Négation! Tout sauf p1 !ex:maitreDe

Exemples SPARQL avec property paths

SPARQL
# 1. Qui est le maître du maître de X ? (grand-maître)
# Séquence : ex:maitreDe / ex:maitreDe
SELECT ?grandMaitre ?eleve WHERE {
  ?grandMaitre  ex:maitreDe / ex:maitreDe  ?eleve .
}
# → (Socrate → Platon → Aristote) ⇒ Socrate est grand-maître d'Aristote

# 2. Tous les ancêtres académiques (chaîne de maîtres)
# Un ou plus : ex:maitreDe+
SELECT ?ancetre ?descendant WHERE {
  ?ancetre  ex:maitreDe+  ?descendant .
}
# → remonte toute la chaîne : maître, maître du maître, etc.

# 3. Toute la famille académique (maîtres + élèves)
# Union : ex:maitreDe | ^ex:maitreDe
SELECT ?x ?y WHERE {
  ?x  ( ex:maitreDe | ^ex:maitreDe )  ?y .
}
# → toutes les paires maître-élève, dans les deux sens

# 4. Qui est influencé par Socrate (directement ou indirectement) ?
# Zéro ou plus : ex:influence*
SELECT ?influence WHERE {
  ex:Socrate  ex:influence*  ?influence .
}
# → Socrate lui-même, ses élèves directs, ses élèves d'élèves, ...

# 5. Les Humains qui ont un surnom (optionnel)
SELECT ?h ?surnom WHERE {
  ?h  a  ex:Humain .
  ?h  ex:surnom?  ?surnom .
}
# → tous les Humains, avec surnom si présent (None sinon)

# 6. L'inverse : qui est élève de qui ?
SELECT ?eleve ?maitre WHERE {
  ?eleve  ^ex:maitreDe  ?maitre .
}
# Strictement équivalent à : ?maitre ex:maitreDe ?eleve
🧠 Puissance expressive : Les property paths permettent d'exprimer en une ligne ce qui nécessiterait des pages entières de code Python. Un chemin comme ^ex:employeDe / ex:dirige / ex:sousTraitant+ peut révéler des chaînes de responsabilité dans une organisation que vous n'auriez jamais trouvées à la main.

⚠️ Mais attention : Les property paths avec * et + peuvent être très lents sur des grands graphes. Un ex:connait+ sur un graphe social de 10⁶ nœuds, c'est potentiellement un chemin de 10⁶ de long. À utiliser avec précaution. Comme une tronçonneuse.

Property paths en Turtle (SHACL)

Les chemins de propriétés ne sont pas réservés à SPARQL. En Turtle, on peut les utiliser dans les définitions de SHACL (Shapes Constraint Language) ou de OWL 2 pour décrire des propriétés complexes :

Turtle
# SHACL : une shape qui utilise un property path
ex:AncetreShape  a  sh:NodeShape ;
    sh:targetClass  ex:Humain ;
    sh:property  [
        sh:path  ( ex:maitreDe [ sh:zeroOrMorePath ex:maitreDe ] ) ;
        sh:minCount  1
    ] .

# OWL 2 : propriété transitive (chemin de longueur ≥ 1)
ex:ancetre  a  owl:TransitiveProperty .

# OWL 2 : propriété composée (chemin séquence)
ex:grandMaitre  a  owl:ObjectProperty ;
    owl:propertyChainAxiom  ( ex:maitreDe ex:maitreDe ) .

🔗 Chemins vs. Prolog

Les property paths de SPARQL sont l'équivalent des prédicats récursifs en Prolog. ex:ancetre+ correspond à la règle ancetre(X,Y) :- parent(X,Y). ancetre(X,Y) :- parent(X,Z), ancetre(Z,Y). Même puissance, syntaxe différente.

⌛ Zéro ou plus

* inclut le nœud lui-même. Utile pour les requêtes qui veulent « tout le monde, y compris soi-même ». Exemple : ex:connait* → tout le réseau social accessible, y compris la personne initiale.

🚫 Négation

!ex:maitreDe signifie « toute propriété sauf maitreDe ». Attention : ça matche n'importe quelle autre propriété. C'est rarement ce qu'on veut. À utiliser avec des FILTER ou dans des contextes SHACL.

CHAPITRE 6 RDF AVANCÉ

Collections, conteneurs et RDF

Au chapitre 3, on a vu les listes RDF (rdf:first/rdf:rest). Mais RDF propose d'autres structures pour grouper des ressources : les conteneurs et les collections.

rdf:Bag, rdf:Seq, rdf:Alt

Avant les listes, RDF avait des conteneurs (un peu l'ancêtre un peu poussiéreux). Ils existent toujours dans le standard :

TypeSignificationOrdreDoublons
rdf:BagEnsemble non ordonné❌ Non✅ Oui
rdf:SeqSéquence ordonnée✅ Oui✅ Oui
rdf:AltAlternatives (choix)✅ Oui (priorité)❌ Non
Turtle
# rdf:Seq — une séquence (avec indices rdf:_1, rdf:_2, …)
ex:Socrate  ex:oeuvres  [
    a  rdf:Seq ;
    rdf:_1  "Apologie" ;
    rdf:_2  "Criton" ;
    rdf:_3  "Phédon"
] .

# rdf:Bag — un sac (pas d'ordre, avec rdf:_1, rdf:_2, …)
ex:Socrate  ex:eleves  [
    a  rdf:Bag ;
    rdf:_1  ex:Platon ;
    rdf:_2  ex:Aristote ;
    rdf:_3  ex:Xenophon
] .

# rdf:Alt — des alternatives (la première est la valeur par défaut)
ex:Platon  ex:ecole  [
    a  rdf:Alt ;
    rdf:_1  ex:Academie ;
    rdf:_2  ex:Lycee
] .
🧓 Note historique : Les conteneurs rdf:Bag, rdf:Seq, rdf:Alt étaient la première tentative du W3C pour représenter des groupes en RDF (1999). Mais ils ont plusieurs défauts : (1) pas de fermeture — on peut toujours ajouter rdf:_4 sans changer le type ; (2) pas de restriction sur les indices — rdf:_42 est valide même s'il n'y a que 3 éléments ; (3) ils sont lourds à parser. Les listes (rdf:first/rdf:rest) sont arrivées plus tard et sont devenues la méthode recommandée. Les conteneurs sont comme les « pantalons à taille haute » de RDF : ils existent encore, mais plus personne ne les utilise vraiment.

Les collections RDF en pratique

Au quotidien, vous utiliserez presque exclusivement la syntaxe parenthésée vue au chapitre 3. C'est plus propre, plus court, et sémantiquement plus clair. Les conteneurs rdf:Bag/rdf:Seq sont surtout utiles quand vous importez des données d'anciens systèmes RDF.

Turtle
# Recommandé : liste RDF (propre, fermée, ordonnée)
ex:Socrate  ex:oeuvres  ( "Apologie" "Criton" "Phédon" "République" ) .

# Acceptable : rdf:Seq (si vous avez besoin de compatibilité ascendante)
ex:Socrate  ex:oeuvres  [ a rdf:Seq ; rdf:_1 "Apologie" ; rdf:_2 "Criton" ] .

# À éviter : rdf:Bag (sauf si vraiment pas d'ordre)
ex:Socrate  ex:oeuvres  [ a rdf:Bag ; rdf:_1 "Apologie" ; rdf:_2 "Criton" ] .

⚖️ Comparaison

Listes : ordre garanti, fermeture, syntaxe courte, mais 2n+1 triplets. rdf:Seq : ordre garanti, pas de fermeture, n+2 triplets. rdf:Bag : pas d'ordre, pas de fermeture, n+2 triplets.

🔄 Bonne pratique

Si vous créez des données aujourd'hui, utilisez les listes ((...)). Si vous lisez des données historiques, préparez-vous à gérer les trois formats. L'interopérabilité, c'est la guerre.

CHAPITRE 7 VALIDATION

SHACL : la grammaire du graphe

Turtle (et RDF) est très permissif : n'importe quel sujet peut avoir n'importe quelle propriété avec n'importe quelle valeur. C'est la liberté. Mais la liberté sans règles, c'est le chaos.

SHACL (Shapes Constraint Language) est le langage qui permet de valider un graphe RDF. C'est comme une grammaire pour vos données : « un Humain DOIT avoir un nom, PEUT avoir un âge, et son âge DOIT être un entier. »

Une shape SHACL

Turtle
# Définition d'une forme (shape) pour les Humains
ex:HumainShape  a  sh:NodeShape ;
    sh:targetClass  ex:Humain ;          # s'applique à tous les Humain
    sh:property  [
        sh:path  ex:nom ;
        sh:minCount  1 ;                 # au moins 1 nom
        sh:maxCount  3 ;                 # au plus 3 noms
        sh:datatype  xsd:string ;        # doit être une chaîne
        sh:minLength  2 ;
        sh:maxLength  100
    ] ;
    sh:property  [
        sh:path  ex:age ;
        sh:datatype  xsd:integer ;
        sh:minInclusive  0 ;
        sh:maxInclusive  150
    ] ;
    sh:property  [
        sh:path  ex:estLeMaitreDe ;
        sh:class  ex:Humain              # l'objet doit être un Humain
    ] .

Avec cette shape, tout graphe RDF contenant des ex:Humain peut être validé : chaque Humain doit avoir entre 1 et 3 noms (chaînes de 2 à 100 caractères), un âge entier entre 0 et 150, et ses élèves doivent être des Humains.

Combinaison avec les property paths

SHACL supporte les chemins de propriétés dans les contraintes. Vous pouvez exprimer des règles complexes :

Turtle
# Règle : un Humain ne peut pas être son propre ancêtre
ex:AntiHeritage  a  sh:NodeShape ;
    sh:targetClass  ex:Humain ;
    sh:property  [
        sh:path  ( ex:maitreDe+ ) ;      # chemin « un ou plus »
        sh:maxCount  0 ;                 # interdit
        sh:message  "Pas d'auto-heritage academique"@fr
    ] .

# Règle : un maître doit avoir au moins un élève
ex:MaitreShape  a  sh:NodeShape ;
    sh:targetClass  ex:Humain ;
    sh:property  [
        sh:path  ( ^ex:estLeMaitreDe ) ; # inverse
        sh:minCount  1 ;
        sh:message  "Un maitre doit avoir au moins un eleve"@fr
    ] .
🔬 SHACL vs. OWL : OWL et SHACL sont souvent confondus, mais ils font des choses différentes : OWL est un moteur d'inférence. SHACL est un validateur XML pour RDF. Les deux sont utiles. Les deux sont standards. Les deux peuvent cohabiter dans le même fichier Turtle.

🔍 sh:pattern

Validation par regex : sh:pattern "^[A-Z]" — le nom doit commencer par une majuscule. Utile pour les noms propres.

🔗 sh:node

Un nœud doit être conforme à une autre shape : sh:node ex:AdresseShape. Permet de valider des structures complexes.

🔢 sh:qualifiedValueShape

Contrainte sur le nombre de valeurs ayant une certaine forme : « exactement 2 élèves doivent être des philosophes ».

ÉPILOGUE

Et après ? Turtle n'a pas fini de vous surprendre

Turtle est souvent présenté comme « la syntaxe simple de RDF ». J'espère que ce cours vous a montré qu'il est bien plus que ça. Avec ses raccourcis (;, ,, a), ses nœuds anonymes ([]), ses listes ((...)), ses littéraux typés (^^, @), et ses chemins (/, |, +, *), Turtle est un langage riche et expressif.

Ce que vous savez maintenant faire

  1. Écrire du Turtle concis — fini les répétitions, vous maîtrisez ; et ,.
  2. Créer des nœuds anonymes — vous savez représenter des ressources sans URI, imbriquées si nécessaire.
  3. Encoder des listes — des séquences ordonnées avec la syntaxe ( ... ).
  4. Typer vos littéraux — langues, nombres, dates, booléens : vos données sont précises.
  5. Parcourir le graphe avec des chemins — séquence, union, étoile, inverse : vous naviguez dans RDF comme dans un GPS.
  6. Valider avec SHACL — vos données respectent des contraintes, ou elles ne sont pas validées.

Directions pour la suite

📘 SPARQL 1.2

Les property paths sont encore plus puissants en SPARQL. Ajoutez-y FILTER, OPTIONAL, CONSTRUCT, SERVICE — vous avez un langage de requête complet.

🛡️ SHACL avancé

SHACL permet des règles d'inférence (SHACL-Rule), des rapports d'erreur détaillés, et des formes paramétrées. C'est le niveau supérieur.

🚀 JSON-LD

Le même RDF, mais en JSON. Pour les développeurs web qui trouvent que Turtle c'est bien mais que tout est en JSON de toute façon. Même graphe, syntaxe différente.

🧮 N3 (Notation 3)

L'extension de Turtle par Tim Berners-Lee avec des règles logiques. C'est Turtle + Prolog dans le même fichier. Le Graal du web sémantique.

🌐 RDF* / SPARQL*

Des triplets qui parlent d'autres triplets (réification simplifiée). « Socrate a dit que Platon est un Homme, avec une confiance de 0.9. »

🔗 Linked Data Platform

Publier et éditer des données RDF via HTTP. Créez votre propre API REST sémantique. Turtle comme format de sérialisation.

« Turtle, ce n'est pas juste une syntaxe. C'est une façon de voir le monde comme un graphe de relations, où chaque nœud est une idée, chaque arc est un lien, et chaque chemin est une histoire. » — Un développeur qui a passé trop de temps à écrire des .ttl

Références

ConceptNorme / Référence
Turtle (spec)W3C Recommendation — Turtle
SPARQL 1.1 Property PathsSPARQL 1.1 Query Language §9
RDF 1.1 ConceptsW3C — RDF 1.1
SHACLW3C — Shapes Constraint Language
RDF ListsRDF Schema §5.3
BCP47 (langues)IETF — Tags for Identifying Languages
🎓 Bilan des quatre cours :
Cours #1 : Du texte aux vecteurs — TF-IDF, embeddings
Cours #2 : Des triplets aux graphes — RDF, Turtle, Prolog
Cours #3 : Des faits aux concepts — OWL, raisonnement, SPARQL
Cours #4 : Du graphe aux motifs — Turtle avancé, listes, chemins, SHACL

Vous avez maintenant toutes les clés pour comprendre, modéliser, interroger, valider et raisonner sur le web sémantique. Pas mal pour quatre cours. Tim Berners-Lee serait fier. Et si vous voulez continuer, rappelez-vous : le web sémantique est un chantier, pas un produit fini.
; , [ ] ( ) / | + * ^