SW-2-RDFBasics

Navigation : << 1-Setup | Index | 3-GraphOperations >>

Les fondamentaux de RDF : Triplets, Noeuds et Serialisation

Ce notebook explore en detail le modèle de données RDF (Resource Description Framework), la brique fondamentale du Web sémantique. Nous etudierons l’anatomie des triplets, les différents types de noeuds, la gestion des espaces de noms et les principaux formats de serialisation.

Objectifs d’apprentissage

A la fin de ce notebook, vous saurez : 1. Decrire l’anatomie d’un triplet RDF (sujet, predicat, objet) et sa signification 2. Distinguer et créer les trois types de noeuds : URI, Blank et Literal 3. Configurer des espaces de noms et des prefixes avec NamespaceMapper 4. Serialiser un graphe RDF dans les 4 formats principaux (NTriples, Turtle, RDF/XML, JSON-LD)

Concepts cles

Concept Description
Triplet RDF Unite fondamentale : assertion (sujet, predicat, objet)
IUriNode Noeud identifie par un URI, represente une ressource
IBlankNode Noeud anonyme sans identifiant global
ILiteralNode Noeud contenant une valeur (texte, nombre, date)
Espace de noms Prefixe qui abrege les URIs longues
Serialisation Encodage d’un graphe RDF dans un format textuel

Prerequis

  • Notebook SW-1-Setup complete

Duree estimee : 45 minutes


0. Installation de dotNetRDF

Comme dans le notebook précédent, nous commencons par charger la bibliotheque dotNetRDF et ses espaces de noms principaux.

// Installation du package dotNetRDF (version épinglée pour reproductibilité)
#r "nuget: dotNetRDF, 3.2.1"

using VDS.RDF;
using VDS.RDF.Parsing;
using VDS.RDF.Writing;
using System;
using System.IO;
using StringWriter = System.IO.StringWriter;

Console.WriteLine("dotNetRDF 3.2.1 charge avec succes.");
Console.WriteLine("Espaces de noms disponibles : VDS.RDF, VDS.RDF.Parsing, VDS.RDF.Writing");
Installed Packages
  • dotNetRDF, 3.2.1
dotNetRDF 3.2.1 charge avec succes.
Espaces de noms disponibles : VDS.RDF, VDS.RDF.Parsing, VDS.RDF.Writing

Interpretation

La cellule ci-dessus installe et importe les trois espaces de noms principaux de dotNetRDF :

Espace de noms Contenu Usage dans ce notebook
VDS.RDF Classes de base (Graph, Triple, INode) Creation de graphes et de noeuds
VDS.RDF.Parsing Parsers (TurtleParser, RdfXmlParser) Lecture de données RDF
VDS.RDF.Writing Writers (NTriplesWriter, CompressingTurtleWriter) Serialisation de graphes

Note technique : La version 3.2.1 est epinglee pour garantir la reproductibilite. L’alias using StringWriter = System.IO.StringWriter evite un conflit de noms avec VDS.RDF.Writing.StringWriter.


1. Les triplets RDF

Anatomie d’un triplet

En RDF, toute information est exprimee sous forme d’un triplet compose de trois éléments :

RDF (Resource Description Framework) est le standard W3C de description de données du Web Sémantique, défini a l’origine par Lassila & Swick (1999) et raffine dans RDF 1.1 (Cyganiak, Wood & Lanthaler, W3C Recommendation 2014). Le modèle de triplet expose ci-dessous en est la brique fondamentale.

  (Sujet)  ---[Predicat]--->  (Objet)
Élément Rôle Types autorises
Sujet La ressource decrite URI Node, Blank Node
Predicat La relation / propriete URI Node uniquement
Objet La valeur ou la ressource liee URI Node, Blank Node, Literal Node

Chaque triplet est une assertion qui exprime une relation entre deux entites :

Phrase naturelle Sujet Predicat Objet
“dotNetRDF dit Hello World” http://www.dotnetrdf.org http://example.org/says "Hello World"
“Alice connait Bob” ex:Alice foaf:knows ex:Bob
“Alice a 30 ans” ex:Alice foaf:age "30"^^xsd:integer

Un graphe RDF est un ensemble de triplets. Visuellement, il forme un graphe oriente :

  (Alice) ---connait---> (Bob)
     |                     |
     +---nom---> "Alice"   +---nom---> "Bob"
     |                     |
     +---age---> 30        +---age---> 28

Creons nos premiers triplets en C#.

// Création d'un graphe vide et de nos premiers triplets
IGraph g = new Graph();

// Création des noeuds URI (sujet et prédicat)
IUriNode dotNetRDF = g.CreateUriNode(UriFactory.Create("http://www.dotnetrdf.org"));
IUriNode says = g.CreateUriNode(UriFactory.Create("http://example.org/says"));

// Création des noeuds literals (objets)
ILiteralNode helloWorld = g.CreateLiteralNode("Hello World");
ILiteralNode bonjourMonde = g.CreateLiteralNode("Bonjour tout le Monde", "fr");

// Assertion des triplets dans le graphe
g.Assert(new Triple(dotNetRDF, says, helloWorld));
g.Assert(new Triple(dotNetRDF, says, bonjourMonde));

Console.WriteLine($"Nombre de triplets dans le graphe : {g.Triples.Count}");
Console.WriteLine();

// Affichage détaillé de chaque triplet
foreach (Triple t in g.Triples)
{
    Console.WriteLine($"  Sujet:    {t.Subject}");
    Console.WriteLine($"  Predicat: {t.Predicate}");
    Console.WriteLine($"  Objet:    {t.Object}");
    Console.WriteLine();
}
Nombre de triplets dans le graphe : 2

  Sujet:    http://www.dotnetrdf.org/
  Predicat: http://example.org/says
  Objet:    Hello World^^http://www.w3.org/2001/XMLSchema#string

  Sujet:    http://www.dotnetrdf.org/
  Predicat: http://example.org/says
  Objet:    Bonjour tout le Monde@fr

Interpretation : Premier triplet RDF

Nous avons créé un graphe contenant deux triplets qui partagent le même sujet et le même predicat, mais différent par l’objet :

Triplet Sujet Predicat Objet
1 <http://www.dotnetrdf.org> <http://example.org/says> "Hello World"
2 <http://www.dotnetrdf.org> <http://example.org/says> "Bonjour tout le Monde"@fr

Points cles : 1. g.Assert() ajoute un triplet au graphe. C’est l’equivalent de “declarer un fait” dans la base de connaissances. 2. UriFactory.Create() interne les URIs pour optimiser la memoire et accelerer les comparaisons d’egalite. 3. Le second literal possede une etiquette de langue ("fr"), ce qui en fait un noeud distinct du premier.

Note : La sortie affichée par les proprietes Subject, Predicate, Object est une representation de debogage, pas une syntaxe RDF standard. Pour une serialisation conforme, il faut utiliser un Writer (cf. section 4).


2. Types de noeuds

RDF définit trois types de noeuds fondamentaux, representes dans dotNetRDF par des interfaces spécifiques.

Type Interface dotNetRDF Notation RDF Rôles autorises
URI Node IUriNode <http://...> Sujet, Predicat, Objet
Blank Node IBlankNode _:id Sujet, Objet
Literal Node ILiteralNode "valeur" Objet uniquement

2.1 URI Nodes (IUriNode)

Les noeuds URI identifient de maniere unique et globale une ressource sur le Web. Ils constituent le coeur de RDF : chaque ressource, chaque propriete est identifiee par un URI.

Deux méthodes de creation existent dans dotNetRDF.

IGraph g = new Graph();

// Méthode 1 : URI absolue avec UriFactory
IUriNode person = g.CreateUriNode(UriFactory.Create("http://example.org/person/Alice"));
Console.WriteLine($"URI absolue : {person.Uri}");

// Méthode 2 : URI avec préfixe (QName) - nécessite un namespace déclaré
g.NamespaceMap.AddNamespace("ex", UriFactory.Create("http://example.org/"));
IUriNode knows = g.CreateUriNode("ex:knows");
Console.WriteLine($"URI via prefixe : {knows.Uri}");

// Les deux méthodes produisent des IUriNode equivalents
IUriNode alice2 = g.CreateUriNode("ex:person/Alice");
Console.WriteLine($"\nComparaison : {person.Uri} == {alice2.Uri} ? {person.Uri == alice2.Uri}");
Console.WriteLine($"Type du noeud : {person.NodeType}");
URI absolue : http://example.org/person/Alice
URI via prefixe : http://example.org/knows

Comparaison : http://example.org/person/Alice == http://example.org/person/Alice ? True
Type du noeud : Uri

Interpretation : Creation d’URI Nodes

Méthode Code Quand l’utiliser
URI absolue g.CreateUriNode(UriFactory.Create("...")) URIs ponctuelles, URIs externes
Prefixe QName g.CreateUriNode("prefix:local") Usage repete d’un même namespace

Points cles : 1. Les URIs sont des identifiants globaux : deux noeuds avec la même URI sont identiques, même dans des graphes différents. 2. UriFactory.Create() optimise la memoire en internant les URIs (une seule instance par URI distincte). 3. La méthode QName necessite que le prefixe soit prealablement declare dans g.NamespaceMap.

2.2 Blank Nodes (IBlankNode)

Les noeuds anonymes (blank nodes) representent des ressources dont on ne connait pas (ou n’a pas besoin de) l’identifiant global. Ils sont identifies localement par un ID interne au graphe.

Cas d’usage typiques : - Structures intermediaires (adresses composees, coordonnees) - Ressources dont l’identite exacte n’importe pas - Existentielles : “il existe quelque chose qui…”

IGraph g = new Graph();
g.NamespaceMap.AddNamespace("ex", UriFactory.Create("http://example.org/"));

// Blank node avec ID généré automatiquement
IBlankNode bnode1 = g.CreateBlankNode();
Console.WriteLine($"Blank node auto     : _:{bnode1.InternalID}");

// Blank node avec ID explicite
IBlankNode address = g.CreateBlankNode("addr1");
Console.WriteLine($"Blank node explicite : _:{address.InternalID}");

// Utilisation : Alice a une adresse (structure anonyme)
IUriNode alice = g.CreateUriNode("ex:Alice");
IUriNode hasAddress = g.CreateUriNode("ex:hasAddress");
IUriNode street = g.CreateUriNode("ex:street");
IUriNode city = g.CreateUriNode("ex:city");

g.Assert(new Triple(alice, hasAddress, address));
g.Assert(new Triple(address, street, g.CreateLiteralNode("42 rue de la Paix")));
g.Assert(new Triple(address, city, g.CreateLiteralNode("Paris")));

Console.WriteLine($"\nNombre de triplets : {g.Triples.Count}");
foreach (Triple t in g.Triples)
{
    Console.WriteLine($"  {t}");
}
Blank node auto     : _:autos1
Blank node explicite : _:addr1

Nombre de triplets : 3
  http://example.org/Alice , http://example.org/hasAddress , _:addr1
  _:addr1 , http://example.org/street , 42 rue de la Paix^^http://www.w3.org/2001/XMLSchema#string
  _:addr1 , http://example.org/city , Paris^^http://www.w3.org/2001/XMLSchema#string

Interpretation : Blank Nodes

Le blank node _:addr1 sert de pivot pour regrouper les proprietes de l’adresse :

  ex:Alice ---ex:hasAddress---> _:addr1
                                  |--- ex:street ---> "42 rue de la Paix"
                                  |--- ex:city   ---> "Paris"
Propriete Blank Node vs URI Node
Portee Locale au graphe (pas d’identifiant global)
Reutilisabilite Ne peut pas etre reference depuis un autre graphe
Notation _:id en NTriples/Turtle
Creation auto g.CreateBlankNode() genere un ID unique

Bonne pratique : Preferez les URI Nodes pour les ressources importantes. Reservez les Blank Nodes aux structures intermediaires ou temporaires.

2.3 Literal Nodes (ILiteralNode)

Les noeuds literaux representent des valeurs concretes : texte, nombres, dates, booléens. Ils ne peuvent apparaitre qu’en position objet dans un triplet.

Trois variantes existent :

Variante Syntaxe RDF Exemple
Plain literal "texte" "Hello World"
Literal avec langue "texte"@lang "Bonjour"@fr
Literal type "valeur"^^xsd:type "42"^^xsd:integer
IGraph g = new Graph();

// --- Variante 1 : Plain literal (chaine simple) ---
ILiteralNode plain = g.CreateLiteralNode("Hello World");
Console.WriteLine($"Plain literal   : \"{plain.Value}\"");

// --- Variante 2 : Literal avec étiquette de langue ---
ILiteralNode langFr = g.CreateLiteralNode("Bonjour le monde", "fr");
ILiteralNode langEn = g.CreateLiteralNode("Hello World", "en");
Console.WriteLine($"Literal @fr     : \"{langFr.Value}\"@{langFr.Language}");
Console.WriteLine($"Literal @en     : \"{langEn.Value}\"@{langEn.Language}");

// --- Variante 3 : Literal type (avec type XSD) ---
// Méthode manuelle (verbose)
ILiteralNode ageManuel = g.CreateLiteralNode("30",
    UriFactory.Create(XmlSpecsHelper.XmlSchemaDataTypeInteger));
Console.WriteLine($"\nTyped (manuel)  : \"{ageManuel.Value}\"^^<{ageManuel.DataType}>");

// Méthode avec extension .ToLiteral() (recommandée)
INode ageExt = (30).ToLiteral(g);
INode piExt = (3.14159).ToLiteral(g);
INode dateExt = DateTime.Now.ToLiteral(g);
INode boolExt = (true).ToLiteral(g);

Console.WriteLine($"\nTyped via .ToLiteral() :");
Console.WriteLine($"  int      -> {ageExt}");
Console.WriteLine($"  double   -> {piExt}");
Console.WriteLine($"  DateTime -> {dateExt}");
Console.WriteLine($"  bool     -> {boolExt}");
Plain literal   : "Hello World"
Literal @fr     : "Bonjour le monde"@fr
Literal @en     : "Hello World"@en

Typed (manuel)  : "30"^^<http://www.w3.org/2001/XMLSchema#integer>

Typed via .ToLiteral() :
  int      -> 30^^http://www.w3.org/2001/XMLSchema#integer
  double   -> 3.14159^^http://www.w3.org/2001/XMLSchema#double
  DateTime -> 2026-06-03T02:03:19.983039+02:00^^http://www.w3.org/2001/XMLSchema#dateTime
  bool     -> true^^http://www.w3.org/2001/XMLSchema#boolean

Interpretation : Les trois variantes de literals

Variante Code C# Notation RDF Type XSD
Plain CreateLiteralNode("Hello") "Hello" xsd:string (implicite)
Langue CreateLiteralNode("Bonjour", "fr") "Bonjour"@fr Aucun (mutuellement exclusif)
Type int (30).ToLiteral(g) "30"^^xsd:integer xsd:integer
Type double (3.14).ToLiteral(g) "3.14"^^xsd:double xsd:double
Type date DateTime.Now.ToLiteral(g) "2025-..."^^xsd:dateTime xsd:dateTime
Type bool (true).ToLiteral(g) "true"^^xsd:boolean xsd:boolean

Points cles : 1. Les méthodes d’extension .ToLiteral() evitent la construction manuelle des URIs XSD et rendent le code beaucoup plus lisible. 2. Un literal ne peut pas avoir a la fois un type et une etiquette de langue (c’est l’un ou l’autre). 3. Sans type ni langue, un literal est considere comme un xsd:string par defaut.

Note technique : Les types XSD (XML Schema Datatypes) definissent un ensemble standard de types de données utilises dans tout le Web sémantique. Pour les types courants (int, DateTime, etc.), les extensions .ToLiteral() produisent automatiquement l’encodage RDF correct.

Recapitulatif : les trois types ensemble

Construisons un graphe utilisant les trois types de noeuds en combinaison.

// Graphe combinant les trois types de noeuds
IGraph g = new Graph();
g.NamespaceMap.AddNamespace("ex", UriFactory.Create("http://example.org/"));
g.NamespaceMap.AddNamespace("foaf", UriFactory.Create("http://xmlns.com/foaf/0.1/"));

// URI Nodes (ressources nommées)
IUriNode alice = g.CreateUriNode("ex:Alice");
IUriNode bob = g.CreateUriNode("ex:Bob");
IUriNode knows = g.CreateUriNode("foaf:knows");
IUriNode name = g.CreateUriNode("foaf:name");
IUriNode age = g.CreateUriNode("foaf:age");
IUriNode rdfType = g.CreateUriNode("rdf:type");
IUriNode foafPerson = g.CreateUriNode("foaf:Person");

// Blank Node (compétence anonyme d'Alice)
IBlankNode skill = g.CreateBlankNode("skill1");
IUriNode hasSkill = g.CreateUriNode("ex:hasSkill");
IUriNode skillName = g.CreateUriNode("ex:skillName");
IUriNode skillLevel = g.CreateUriNode("ex:skillLevel");

// Assertions avec les 3 types de noeuds
g.Assert(new Triple(alice, rdfType, foafPerson));                                    // URI -> URI
g.Assert(new Triple(alice, name, g.CreateLiteralNode("Alice Dupont", "fr")));       // URI -> Literal@fr
g.Assert(new Triple(alice, age, (30).ToLiteral(g)));                                 // URI -> Literal^^xsd:int
g.Assert(new Triple(alice, knows, bob));                                              // URI -> URI
g.Assert(new Triple(alice, hasSkill, skill));                                         // URI -> Blank
g.Assert(new Triple(skill, skillName, g.CreateLiteralNode("C#")));                  // Blank -> Literal
g.Assert(new Triple(skill, skillLevel, g.CreateLiteralNode("Expert")));             // Blank -> Literal
g.Assert(new Triple(bob, rdfType, foafPerson));                                      // URI -> URI
g.Assert(new Triple(bob, name, g.CreateLiteralNode("Bob Martin", "fr")));          // URI -> Literal@fr

Console.WriteLine($"Graphe avec {g.Triples.Count} triplets :");
Console.WriteLine();
foreach (Triple t in g.Triples)
{
    string sType = t.Subject is IBlankNode ? "Blank" : "URI";
    string oType = t.Object is IBlankNode ? "Blank" : (t.Object is ILiteralNode ? "Literal" : "URI");
    Console.WriteLine($"  [{sType}] {t.Subject}  -->  {t.Predicate}  -->  [{oType}] {t.Object}");
}
Graphe avec 9 triplets :

  [URI] http://example.org/Alice  -->  http://www.w3.org/1999/02/22-rdf-syntax-ns#type  -->  [URI] http://xmlns.com/foaf/0.1/Person
  [URI] http://example.org/Alice  -->  http://xmlns.com/foaf/0.1/name  -->  [Literal] Alice Dupont@fr
  [URI] http://example.org/Alice  -->  http://xmlns.com/foaf/0.1/age  -->  [Literal] 30^^http://www.w3.org/2001/XMLSchema#integer
  [URI] http://example.org/Alice  -->  http://xmlns.com/foaf/0.1/knows  -->  [URI] http://example.org/Bob
  [URI] http://example.org/Alice  -->  http://example.org/hasSkill  -->  [Blank] _:skill1
  [Blank] _:skill1  -->  http://example.org/skillName  -->  [Literal] C#^^http://www.w3.org/2001/XMLSchema#string
  [Blank] _:skill1  -->  http://example.org/skillLevel  -->  [Literal] Expert^^http://www.w3.org/2001/XMLSchema#string
  [URI] http://example.org/Bob  -->  http://www.w3.org/1999/02/22-rdf-syntax-ns#type  -->  [URI] http://xmlns.com/foaf/0.1/Person
  [URI] http://example.org/Bob  -->  http://xmlns.com/foaf/0.1/name  -->  [Literal] Bob Martin@fr

Interpretation : Graphe multi-types

Ce graphe illustre toutes les combinaisons de types rencontrees en pratique :

Triplet Sujet Predicat Objet Pattern
Alice est une Person URI URI URI Classification
Alice a un nom URI URI Literal@fr Propriete textuelle multilingue
Alice a 30 ans URI URI Literalxsd:int Propriete numérique
Alice connait Bob URI URI URI Relation entre ressources
Alice a une competence URI URI Blank Lien vers structure anonyme
La competence s’appelle C# Blank URI Literal Detail de la structure

Point cle : Le predicat est toujours un URI Node. C’est la seule position contrainte a un seul type.


3. Espaces de noms et prefixes

Le problème des URIs longues

Sans prefixes, chaque URI doit etre ecrite en entier, ce qui rend le code verbeux et difficile a lire :

// Sans prefixes (fastidieux)
g.CreateUriNode(UriFactory.Create("http://xmlns.com/foaf/0.1/name"));
g.CreateUriNode(UriFactory.Create("http://xmlns.com/foaf/0.1/knows"));
g.CreateUriNode(UriFactory.Create("http://xmlns.com/foaf/0.1/mbox"));

// Avec prefixes (lisible)
g.CreateUriNode("foaf:name");
g.CreateUriNode("foaf:knows");
g.CreateUriNode("foaf:mbox");

Les espaces de noms (namespaces) associent un prefixe court a un URI de base. Le NamespaceMapper de dotNetRDF gere cette correspondance.

IGraph g = new Graph();

// Prefixes prédéfinis par dotNetRDF
Console.WriteLine("=== Prefixes predefinis ===");
foreach (var prefix in g.NamespaceMap.Prefixes)
{
    Console.WriteLine($"  {prefix}: -> {g.NamespaceMap.GetNamespaceUri(prefix)}");
}

// Ajout de préfixes standard
g.NamespaceMap.AddNamespace("foaf", UriFactory.Create("http://xmlns.com/foaf/0.1/"));
g.NamespaceMap.AddNamespace("dc", UriFactory.Create("http://purl.org/dc/elements/1.1/"));
g.NamespaceMap.AddNamespace("schema", UriFactory.Create("http://schema.org/"));
g.NamespaceMap.AddNamespace("ex", UriFactory.Create("http://example.org/"));

Console.WriteLine("\n=== Apres ajout des prefixes personnalises ===");
foreach (var prefix in g.NamespaceMap.Prefixes)
{
    Console.WriteLine($"  {prefix}: -> {g.NamespaceMap.GetNamespaceUri(prefix)}");
}

// Utilisation des préfixes pour créer des noeuds
IUriNode foafName = g.CreateUriNode("foaf:name");
IUriNode dcTitle = g.CreateUriNode("dc:title");
Console.WriteLine($"\nResolution : foaf:name -> {foafName.Uri}");
Console.WriteLine($"Resolution : dc:title  -> {dcTitle.Uri}");
=== Prefixes predefinis ===
  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#

=== Apres ajout des prefixes personnalises ===
  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#
  foaf: -> http://xmlns.com/foaf/0.1/
  dc: -> http://purl.org/dc/elements/1.1/
  schema: -> http://schema.org/
  ex: -> http://example.org/

Resolution : foaf:name -> http://xmlns.com/foaf/0.1/name
Resolution : dc:title  -> http://purl.org/dc/elements/1.1/title

Interpretation : NamespaceMapper

Prefixes predefinis dans tout graphe dotNetRDF :

Prefixe URI Usage
rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns# Vocabulaire RDF de base (type, Property)
rdfs: http://www.w3.org/2000/01/rdf-schema# Schema RDF (Class, subClassOf, label)
xsd: http://www.w3.org/2001/XMLSchema# Types de données (integer, string, dateTime)

Prefixes standard recommandes (a ajouter selon le domaine) :

Prefixe URI Domaine
foaf: http://xmlns.com/foaf/0.1/ Personnes et relations sociales
dc: http://purl.org/dc/éléments/1.1/ Metadonnees Dublin Core
schema: http://schema.org/ SEO / données structurees (Google)
skos: http://www.w3.org/2004/02/skos/core# Thesaurus et taxonomies
owl: http://www.w3.org/2002/07/owl# Ontologies Web

Bonne pratique : Declarez vos prefixes en debut de notebook pour eviter les URIs longues dans le code. Le registre officiel des prefixes est disponible sur prefix.cc.

Resolution et reduction d’URIs

Le NamespaceMapper fonctionne dans les deux sens : resolution (prefixe vers URI complete) et reduction (URI complete vers prefixe).

IGraph g = new Graph();
g.NamespaceMap.AddNamespace("foaf", UriFactory.Create("http://xmlns.com/foaf/0.1/"));

// Résolution : préfixe -> URI complete
Uri fullUri = g.NamespaceMap.GetNamespaceUri("foaf");
Console.WriteLine($"Resolution : foaf: -> {fullUri}");

// Réduction : URI complete -> préfixe:local
Uri testUri = UriFactory.Create("http://xmlns.com/foaf/0.1/name");
string reduced;
if (g.NamespaceMap.ReduceToQName(testUri.ToString(), out reduced))
{
    Console.WriteLine($"Reduction  : {testUri} -> {reduced}");
}

// Vérification d'existence de préfixes
Console.WriteLine($"\nPrefixe 'foaf' existe ? {g.NamespaceMap.HasNamespace("foaf")}");
Console.WriteLine($"Prefixe 'owl' existe ?  {g.NamespaceMap.HasNamespace("owl")}");
Resolution : foaf: -> http://xmlns.com/foaf/0.1/
Reduction  : http://xmlns.com/foaf/0.1/name -> foaf:name

Prefixe 'foaf' existe ? True
Prefixe 'owl' existe ?  False

Interpretation : Opérations sur les namespaces

Opération Méthode Direction
Ajout AddNamespace(prefix, uri) Declaration d’un prefixe
Resolution GetNamespaceUri(prefix) Prefixe -> URI complete
Reduction ReduceToQName(uri, out qname) URI complete -> Prefixe:local
Verification HasNamespace(prefix) Le prefixe existe-t-il ?

Note technique : Les prefixes sont essentiels pour la lisibilite en Turtle et en SPARQL. Les Writers de dotNetRDF les utilisent automatiquement lors de la serialisation.


4. Formats de serialisation

Un graphe RDF est une structure abstraite (un ensemble de triplets). Pour le stocker ou le transmettre, il faut le serialiser dans un format textuel. Quatre formats principaux existent, chacun avec ses forces et faiblesses.

Ces formats sont normalises par le W3C : NTriples et Turtle (Beckett & Berners-Lee, W3C Rec 2014), RDF/XML (W3C Rec 1999, revise en RDF 1.1 en 2014) et JSON-LD (Speicher, Kellogg et al., W3C Rec 2014/2020). Les vocabulaires couramment utilises (foaf:, dc:, skos:) renvoient respectivement a FOAF (Brickley & Miller), Dublin Core (DCMI Metadata Terms) et SKOS (Miles & Bechhofer, W3C Rec 2009).

Nous allons créer un graphe de reference, puis le serialiser dans chaque format pour comparer.

// Graphe de référence pour les démonstrations de sérialisation
IGraph demo = new Graph();
demo.NamespaceMap.AddNamespace("ex", UriFactory.Create("http://example.org/"));
demo.NamespaceMap.AddNamespace("foaf", UriFactory.Create("http://xmlns.com/foaf/0.1/"));

IUriNode alice = demo.CreateUriNode("ex:Alice");
IUriNode bob = demo.CreateUriNode("ex:Bob");
IUriNode rdfType = demo.CreateUriNode("rdf:type");
IUriNode foafPerson = demo.CreateUriNode("foaf:Person");
IUriNode foafName = demo.CreateUriNode("foaf:name");
IUriNode foafAge = demo.CreateUriNode("foaf:age");
IUriNode foafKnows = demo.CreateUriNode("foaf:knows");

demo.Assert(new Triple(alice, rdfType, foafPerson));
demo.Assert(new Triple(alice, foafName, demo.CreateLiteralNode("Alice Dupont", "fr")));
demo.Assert(new Triple(alice, foafAge, (30).ToLiteral(demo)));
demo.Assert(new Triple(alice, foafKnows, bob));
demo.Assert(new Triple(bob, rdfType, foafPerson));
demo.Assert(new Triple(bob, foafName, demo.CreateLiteralNode("Bob Martin", "fr")));

Console.WriteLine($"Graphe de reference cree : {demo.Triples.Count} triplets.");
Console.WriteLine("Ce graphe sera serialise dans 4 formats differents.");
Graphe de reference cree : 6 triplets.
Ce graphe sera serialise dans 4 formats differents.

4.1 NTriples : le format le plus simple

NTriples est un format ligne par ligne, sans abreviations ni prefixes. Chaque ligne contient un triplet complet, termine par un point.

// Sérialisation en NTriples
var ntWriter = new NTriplesWriter();
var sw = new StringWriter();
ntWriter.Save(demo, sw);

string ntOutput = sw.ToString();
Console.WriteLine("=== Format NTriples ===");
Console.WriteLine(ntOutput);
Console.WriteLine($"Taille : {ntOutput.Length} caracteres");
=== Format NTriples ===
<http://example.org/Alice> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://xmlns.com/foaf/0.1/Person> .
<http://example.org/Alice> <http://xmlns.com/foaf/0.1/name> "Alice Dupont"@fr .
<http://example.org/Alice> <http://xmlns.com/foaf/0.1/age> "30"^^<http://www.w3.org/2001/XMLSchema#integer> .
<http://example.org/Alice> <http://xmlns.com/foaf/0.1/knows> <http://example.org/Bob> .
<http://example.org/Bob> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://xmlns.com/foaf/0.1/Person> .
<http://example.org/Bob> <http://xmlns.com/foaf/0.1/name> "Bob Martin"@fr .

Taille : 586 caracteres

Interpretation : Format NTriples

Conventions syntaxiques : - URIs toujours entre chevrons : <http://example.org/Alice> - Literals entre guillemets : "Alice Dupont" - Etiquettes de langue après le literal : "Bonjour"@fr - Types indiques par ^^ : "30"^^<http://www.w3.org/2001/XMLSchema#integer> - Chaque triplet termine par un point .

Avantage Inconvenient
Très simple a parser Très verbeux (URIs repetees integralement)
Pas d’ambiguite Fichiers volumineux
Ideal pour le streaming ligne par ligne Peu lisible pour un humain

4.2 Turtle : le format lisible

Turtle (Terse RDF Triple Language) est le format le plus lisible pour les humains. Il utilise des prefixes, des abreviations et des regroupements par sujet.

// Sérialisation en Turtle (CompressingTurtleWriter pour les abréviations maximales)
var turtleWriter = new CompressingTurtleWriter();
var sw = new StringWriter();
turtleWriter.Save(demo, sw);

string turtleOutput = sw.ToString();
Console.WriteLine("=== Format Turtle ===");
Console.WriteLine(turtleOutput);
Console.WriteLine($"Taille : {turtleOutput.Length} caracteres");
=== Format Turtle ===
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
@prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
@prefix ex: <http://example.org/>.
@prefix foaf: <http://xmlns.com/foaf/0.1/>.

ex:Alice a foaf:Person;
         foaf:age 30 ;
         foaf:knows ex:Bob;
         foaf:name "Alice Dupont"@fr.
ex:Bob a foaf:Person;
       foaf:name "Bob Martin"@fr.

Taille : 426 caracteres

Interpretation : Format Turtle

Turtle introduit plusieurs abreviations syntaxiques :

Syntaxe Signification Exemple
@prefix p: <uri> . Declaration de prefixe @prefix foaf: <http://xmlns.com/foaf/0.1/> .
; Même sujet, predicat différent ex:Alice foaf:name "Alice" ; foaf:age 30 .
, Même sujet et predicat, objet différent ex:Alice foaf:knows ex:Bob, ex:Carol .
a Raccourci pour rdf:type ex:Alice a foaf:Person .
. Fin de la description du sujet Termine le bloc
Avantage Inconvenient
Très lisible et compact Parsing plus complexe que NTriples
Syntaxe proche de SPARQL Necessite la declaration des prefixes
Format prefere pour la documentation Moins adapte au streaming

Bonne pratique : Utilisez CompressingTurtleWriter plutot que TurtleWriter pour beneficier de toutes les compressions syntaxiques (a, ;, ,).

4.3 RDF/XML : le format historique

RDF/XML est le premier format de serialisation RDF, standardise par le W3C en 1999. Il utilise la syntaxe XML avec des espaces de noms.

// Sérialisation en RDF/XML
var rdfXmlWriter = new RdfXmlWriter();
var sw = new StringWriter();
rdfXmlWriter.Save(demo, sw);

string rdfXmlOutput = sw.ToString();
Console.WriteLine("=== Format RDF/XML ===");
Console.WriteLine(rdfXmlOutput);
Console.WriteLine($"Taille : {rdfXmlOutput.Length} caracteres");
=== Format RDF/XML ===
<?xml version="1.0" encoding="utf-16"?>
<!DOCTYPE rdf:RDF [
    <!ENTITY rdf 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'>
    <!ENTITY rdfs 'http://www.w3.org/2000/01/rdf-schema#'>
    <!ENTITY xsd 'http://www.w3.org/2001/XMLSchema#'>
    <!ENTITY ex 'http://example.org/'>
    <!ENTITY foaf 'http://xmlns.com/foaf/0.1/'>
]>
<rdf:RDF xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:ex="http://example.org/" xmlns:foaf="http://xmlns.com/foaf/0.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
  <foaf:Person rdf:about="&ex;Alice">
    <foaf:age rdf:datatype="&xsd;integer">30</foaf:age>
    <foaf:knows rdf:resource="&ex;Bob" />
    <foaf:name xml:lang="fr">Alice Dupont</foaf:name>
  </foaf:Person>
  <foaf:Person rdf:about="&ex;Bob">
    <foaf:name xml:lang="fr">Bob Martin</foaf:name>
  </foaf:Person>
</rdf:RDF>
Taille : 884 caracteres

Interpretation : Format RDF/XML

Élément XML Signification RDF
<rdf:RDF> Racine du document RDF
<rdf:Description rdf:about="..."> Declaration d’un sujet
<foaf:name>Alice</foaf:name> Triplet (sujet, foaf:name, “Alice”)
xmlns:foaf="..." Declaration d’espace de noms
Avantage Inconvenient
Standard W3C historique Verbeux (syntaxe XML)
Compatible outils XML (XSLT, XPath) Peu lisible
Bon support dans les frameworks Plusieurs serialisations possibles pour le même graphe

Note : Le writer genere automatiquement des prefixes nsX pour les URIs non declarees dans le NamespaceMap. RDF/XML est de moins en moins utilise au profit de Turtle et JSON-LD.

4.4 JSON-LD : le format moderne

JSON-LD (JSON for Linked Data) encode des données RDF dans du JSON standard. C’est le format privilegie pour les APIs Web et le SEO (Schema.org utilise par Google).

// Sérialisation en JSON-LD
// Note : JsonLdWriter implémente IStoreWriter (pas IRdfWriter)
// Il faut donc envelopper le graphe dans un TripleStore
using VDS.RDF;

var store = new TripleStore();
store.Add(demo);

var jsonLdWriter = new JsonLdWriter();
var sw = new StringWriter();
jsonLdWriter.Save(store, sw);

string jsonLdOutput = sw.ToString();
Console.WriteLine("=== Format JSON-LD ===");
Console.WriteLine(jsonLdOutput);
Console.WriteLine($"Taille : {jsonLdOutput.Length} caracteres");
=== Format JSON-LD ===
[
  {
    "@id": "http://example.org/Alice",
    "@type": [
      "http://xmlns.com/foaf/0.1/Person"
    ],
    "http://xmlns.com/foaf/0.1/name": [
      {
        "@language": "fr",
        "@value": "Alice Dupont"
      }
    ],
    "http://xmlns.com/foaf/0.1/age": [
      {
        "@value": "30",
        "@type": "http://www.w3.org/2001/XMLSchema#integer"
      }
    ],
    "http://xmlns.com/foaf/0.1/knows": [
      {
        "@id": "http://example.org/Bob"
      }
    ]
  },
  {
    "@id": "http://example.org/Bob",
    "@type": [
      "http://xmlns.com/foaf/0.1/Person"
    ],
    "http://xmlns.com/foaf/0.1/name": [
      {
        "@language": "fr",
        "@value": "Bob Martin"
      }
    ]
  }
]
Taille : 750 caracteres

Interpretation : Format JSON-LD

JSON-LD utilise des mots-cles speciaux prefixes par @ :

Mot-cle Signification Equivalent RDF
@context Declaration des prefixes @prefix en Turtle
@id Identifiant de la ressource URI du sujet
@type Type de la ressource rdf:type
@value Valeur d’un literal Contenu du literal
@language Langue d’un literal Etiquette de langue
Avantage Inconvenient
Compatible ecosysteme JSON / JavaScript Moins compact que Turtle
Utilise par Schema.org et Google Contextualisation peut etre complexe
Facile a integrer dans les APIs REST Plusieurs formes (expanded, compacted, flattened)

Comparaison des 4 formats

Critere NTriples Turtle RDF/XML JSON-LD
Lisibilite Faible Excellente Faible Bonne
Compacite Faible Elevee Moyenne Moyenne
Complexite de parsing Très faible Moyenne Elevee Moyenne
Prefixes Non Oui (@prefix) Oui (xmlns) Oui (@context)
Streaming Oui (ligne par ligne) Difficile Difficile Non
Usage principal Dump de données Documentation, SPARQL Interoperabilite XML APIs Web, SEO
Writer dotNetRDF NTriplesWriter CompressingTurtleWriter RdfXmlWriter JsonLdWriter

Recommandation : Utilisez Turtle pour la lisibilite et le travail humain, NTriples pour les traitements batch et le streaming, JSON-LD pour les APIs Web et le SEO.


5. Exemple guide 1 : Modeliser un reseau social

Objectif : Créer un graphe RDF modelisant un petit reseau social avec : - 3 personnes (avec nom, age et email) - Des relations foaf:knows entre elles - Au moins un Blank Node (par exemple, une adresse) - Serialiser le résultat en Turtle

Vocabulaires a utiliser : foaf: (Friend of a Friend), ex: (votre domaine)

Le code ci-dessous est une solution possible. Modifiez-le pour decrire votre propre reseau.

// Exemple guide 1 : Modéliser un réseau social en RDF
IGraph social = new Graph();

// Déclaration des préfixes
social.NamespaceMap.AddNamespace("foaf", UriFactory.Create("http://xmlns.com/foaf/0.1/"));
social.NamespaceMap.AddNamespace("ex", UriFactory.Create("http://example.org/"));

// Noeuds prédicats réutilisables
IUriNode rdfType = social.CreateUriNode("rdf:type");
IUriNode foafPerson = social.CreateUriNode("foaf:Person");
IUriNode foafName = social.CreateUriNode("foaf:name");
IUriNode foafAge = social.CreateUriNode("foaf:age");
IUriNode foafMbox = social.CreateUriNode("foaf:mbox");
IUriNode foafKnows = social.CreateUriNode("foaf:knows");
IUriNode exAddress = social.CreateUriNode("ex:hasAddress");
IUriNode exStreet = social.CreateUriNode("ex:street");
IUriNode exCity = social.CreateUriNode("ex:city");

// --- Carol ---
IUriNode carol = social.CreateUriNode("ex:Carol");
social.Assert(new Triple(carol, rdfType, foafPerson));
social.Assert(new Triple(carol, foafName, social.CreateLiteralNode("Carol Lefevre", "fr")));
social.Assert(new Triple(carol, foafAge, (28).ToLiteral(social)));
social.Assert(new Triple(carol, foafMbox,
    social.CreateUriNode(UriFactory.Create("mailto:carol@example.org"))));

// --- David ---
IUriNode david = social.CreateUriNode("ex:David");
social.Assert(new Triple(david, rdfType, foafPerson));
social.Assert(new Triple(david, foafName, social.CreateLiteralNode("David Moreau", "fr")));
social.Assert(new Triple(david, foafAge, (35).ToLiteral(social)));
social.Assert(new Triple(david, foafMbox,
    social.CreateUriNode(UriFactory.Create("mailto:david@example.org"))));

// --- Emma ---
IUriNode emma = social.CreateUriNode("ex:Emma");
social.Assert(new Triple(emma, rdfType, foafPerson));
social.Assert(new Triple(emma, foafName, social.CreateLiteralNode("Emma Durand", "fr")));
social.Assert(new Triple(emma, foafAge, (42).ToLiteral(social)));

// Relations foaf:knows
social.Assert(new Triple(carol, foafKnows, david));
social.Assert(new Triple(david, foafKnows, emma));
social.Assert(new Triple(emma, foafKnows, carol));

// Blank Node : adresse de Carol
IBlankNode carolAddr = social.CreateBlankNode("carolAddr");
social.Assert(new Triple(carol, exAddress, carolAddr));
social.Assert(new Triple(carolAddr, exStreet, social.CreateLiteralNode("15 avenue Victor Hugo")));
social.Assert(new Triple(carolAddr, exCity, social.CreateLiteralNode("Lyon")));

// Sérialisation en Turtle
var turtleWriter = new CompressingTurtleWriter();
var sw = new StringWriter();
turtleWriter.Save(social, sw);

Console.WriteLine($"Reseau social : {social.Triples.Count} triplets");
Console.WriteLine();
Console.WriteLine(sw.ToString());
Reseau social : 17 triplets

@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
@prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
@prefix foaf: <http://xmlns.com/foaf/0.1/>.
@prefix ex: <http://example.org/>.

ex:Carol ex:hasAddress [ex:street "15 avenue Victor Hugo" ; 
                        ex:city "Lyon"];
         a foaf:Person;
         foaf:age 28 ;
         foaf:knows ex:David;
         foaf:mbox <mailto:carol@example.org>;
         foaf:name "Carol Lefevre"@fr.
ex:David a foaf:Person;
         foaf:age 35 ;
         foaf:knows ex:Emma;
         foaf:mbox <mailto:david@example.org>;
         foaf:name "David Moreau"@fr.
ex:Emma a foaf:Person;
        foaf:age 42 ;
        foaf:knows ex:Carol;
        foaf:name "Emma Durand"@fr.

Interpretation de l’Exemple guide 1

Le graphe modelise un reseau social minimal avec les trois types de noeuds :

Personne Proprietes Relations
Carol nom@fr, agexsd:int, email (URI), adresse (Blank Node) connait David
David nom@fr, agexsd:int, email (URI) connait Emma
Emma nom@fr, agexsd:int connait Carol

Observations sur la sortie Turtle : - Les prefixes @prefix foaf: et @prefix ex: sont declares en tete - Les proprietes d’un même sujet sont regroupees avec ; - L’adresse de Carol apparait comme _:carolAddr (Blank Node) - Le raccourci a remplace rdf:type dans la sortie


6. Exemple guide 2 : Comparer les tailles de serialisation

Objectif : Serialiser le graphe du reseau social dans les différents formats et comparer les tailles obtenues. Cela illustre concretement les différences de compacite entre formats.

// Exemple guide 2 : Comparer les tailles de sérialisation

// Fonction utilitaire pour sérialiser et mesurer
string SerializeGraph(IGraph graph, IRdfWriter writer)
{
    var sw = new StringWriter();
    writer.Save(graph, sw);
    return sw.ToString();
}

// Formats IRdfWriter (NTriples, Turtle, RDF/XML)
var formats = new List<(string Name, IRdfWriter Writer)>
{
    ("NTriples", new NTriplesWriter()),
    ("Turtle", new CompressingTurtleWriter()),
    ("RDF/XML", new RdfXmlWriter())
};

Console.WriteLine($"Graphe de test : {social.Triples.Count} triplets\n");
Console.WriteLine($"{"Format",-12} {"Taille (car)",-15} {"Lignes",-10} {"Ratio vs NT",-15}");
Console.WriteLine(new string('-', 52));

int ntSize = 0;
foreach (var (formatName, writer) in formats)
{
    string output = SerializeGraph(social, writer);
    int size = output.Length;
    int lines = output.Split('\n').Length;

    if (formatName == "NTriples") ntSize = size;
    string ratio = ntSize > 0 ? $"{(double)size / ntSize:P0}" : "---";

    Console.WriteLine($"{formatName,-12} {size,-15} {lines,-10} {ratio,-15}");
}

// JSON-LD : IStoreWriter (nécessite un TripleStore)
var jsonStore = new TripleStore();
jsonStore.Add(social);
var jsonLdWriter = new JsonLdWriter();
var jsonSw = new StringWriter();
jsonLdWriter.Save(jsonStore, jsonSw);
string jsonOutput = jsonSw.ToString();
string jsonRatio = ntSize > 0 ? $"{(double)jsonOutput.Length / ntSize:P0}" : "---";
Console.WriteLine($"{"JSON-LD",-12} {jsonOutput.Length,-15} {jsonOutput.Split('\n').Length,-10} {jsonRatio,-15}");
Graphe de test : 17 triplets

Format       Taille (car)    Lignes     Ratio vs NT    
----------------------------------------------------
NTriples     1644            18         100 %          
Turtle       803             23         49 %           
RDF/XML      1567            32         95 %           
JSON-LD      2069            99         126 %          

Interpretation de l’Exemple guide 2

Résultats attendus (les valeurs exactes varient selon le graphe) :

Format Taille relative Raison
NTriples 100% (reference) Aucune compression, URIs completes repetees
Turtle ~40-60% Prefixes, regroupement par sujet, raccourci a
RDF/XML ~95% Espaces de noms XML, structure verbose (proche de NTriples sur ce graphe)
JSON-LD ~126% Contexte JSON, structure d’objets (plus verbose que NTriples ici, format le plus lourd)

Conclusion : Turtle est presque toujours le format le plus compact grace aux prefixes et aux abreviations syntaxiques. Le choix du format depend de l’usage : - Documentation et lecture humaine : Turtle - Echange machine / streaming : NTriples - APIs Web et SEO : JSON-LD - Integration XML : RDF/XML


7. Exercice : a vous de jouer

Vous maitrisez maintenant les triplets, les trois types de noeuds, les namespaces et la serialisation. Mettez tout en pratique sur un cas concret.

Enonce : Construisez un graphe RDF decrivant un livre :

  1. Un noeud URI pour le livre (ex : ex:livre/RDF101).
  2. Un literal type (xsd:integer) pour l’annee de publication.
  3. Un literal avec tag de langue (@fr) pour le titre.
  4. Un blank node pour l’auteur, relie au livre via ex:auteur, avec un nom (literal simple).
  5. Declarez les prefixes ex (http://example.org/) et dc (http://purl.org/dc/éléments/1.1/).
  6. Serialisez le graphe en Turtle et affichez-le, puis affichez le nombre de triplets (g.Triples.Count).

Indice : reutilisez UriFactory.Create, g.CreateLiteralNode(valeur, new Uri(...)) pour le type, g.CreateLiteralNode(valeur, "fr") pour la langue, g.CreateBlankNode(), g.NamespaceMap.AddNamespace(...) et CompressingTurtleWriter.

Résultat attendu : un graphe de ~5-6 triplets serialise en Turtle lisible.

Exercice : Construire un graphe avec les 3 types de noeuds

Les sections 2.1-2.3 ont montre les URI Nodes, Blank Nodes et Literal Nodes. Construisez un graphe qui combine les trois types.

Indices :

  • g.CreateUriNode("ex:resource"), g.CreateBlankNode(), g.CreateLiteralNode("text")
  • g.Assert(new Triple(s, p, o)) pour ajouter un triplet
// Exercice : Construire un graphe combinant URI, Blank et Literal nodes
// TODO étudiant : construisez un graphe avec au moins 1 URI, 1 Blank et 1 Literal
//
// Étape 1 : créer IGraph g = new Graph() et définir un namespace
// Étape 2 : créer un sujet URI, un prédicat URI, un objet Literal
// Étape 3 : ajouter un Blank Node comme sujet d'un autre triplet
// Étape 4 : afficher tous les triplets avec g.Triples

Console.WriteLine("Exercice a completer");
Exercice a completer

Exercice : Serialiser un graphe dans les 4 formats

Les sections 4.1-4.4 ont montre les formats NTriples, Turtle, RDF/XML et JSON-LD. Construisez un graphe RDF et comparez la taille de chaque format de serialisation.

Indices :

  • CompressingTurtleWriter, NTriplesWriter, RdfXmlWriter, JsonLdWriter
  • writer.Save(g, sw) puis sw.ToString().Length pour la taille
// Exercice : Sérialiser un graphe dans les 4 formats et comparer les tailles
// TODO étudiant : construisez un graphe avec 5 triplets, puis sérialisez dans les 4 formats
//
// Étape 1 : créer un Graph et ajouter 5 triplets (sujet, prédicat, objet)
// Étape 2 : sérialiser avec CompressingTurtleWriter, NTriplesWriter, RdfXmlWriter, JsonLdWriter
// Étape 3 : comparer la taille (en caractères) de chaque format
// Étape 4 (bonus) : quel format est le plus compact ? Le plus lisible ?

Console.WriteLine("Exercice a completer");
Exercice a completer

Exercice : Créer un graphe RDF complet avec namespaces

En utilisant les concepts vus dans ce notebook (URI nodes, literals, blank nodes, namespaces), construisez un graphe RDF complet et serialisez-le en Turtle.

Indices : utilisez NamespaceMap, UriFactory, et CompressingTurtleWriter.

// Exercice : votre code ici
// Etapes suggerees :
//   IGraph g = new Graph();
//   g.NamespaceMap.AddNamespace("ex", UriFactory.Create("http://example.org/"));
//   g.NamespaceMap.AddNamespace("dc", UriFactory.Create("http://purl.org/dc/elements/1.1/"));
//   ... créer les noeuds (URI, literals type/langue, blank node) ...
//   ... ajouter les triplets avec g.Assert(...) ...
//   ... sérialiser en Turtle avec CompressingTurtleWriter ...
//   Console.WriteLine($"Nombre de triplets : {g.Triples.Count}");

Console.WriteLine("Exercice a completer");
Exercice a completer

Resume

Élément Ce que nous avons appris
Triplet RDF Unite fondamentale (sujet, predicat, objet), asserte avec g.Assert()
URI Nodes IUriNode : identifiant global, creation par URI absolue ou QName
Blank Nodes IBlankNode : noeud anonyme local, pour structures intermediaires
Literal Nodes ILiteralNode : valeurs (plain, avec langue @fr, avec type ^^xsd:)
Espaces de noms NamespaceMapper : prefixes pour abreger les URIs (foaf:, dc:, etc.)
NTriples Format simple, une ligne par triplet, pas de prefixes
Turtle Format lisible avec prefixes et abreviations (;, ,, a)
RDF/XML Format historique W3C base sur XML
JSON-LD Format moderne pour APIs Web et SEO

Ce qui vient ensuite

Dans le notebook suivant (SW-3-GraphOperations), nous apprendrons a : - Sélectionner des triplets avec GetTriplesWithXxx() - Fusionner et comparer des graphes - Lire des fichiers RDF depuis le disque et le Web - Convertir entre formats de serialisation

References

  • RDF 1.1 Concepts and Abstract Syntax — Cyganiak, Wood & Lanthaler, W3C Recommendation (2014). w3.org/TR/rdf11-concepts
  • Resource Description Framework (RDF) Model and Syntax — Lassila & Swick, W3C Recommendation (1999). Premier formalisme des triplets RDF.
  • Turtle – Terse RDF Triple Language — Beckett & Berners-Lee, W3C Recommendation (2014). w3.org/TR/turtle
  • RDF 1.1 N-Triples — W3C Recommendation (2014). Format ligne par ligne canonique.
  • RDF 1.1 XML Syntax — W3C Recommendation (2014). w3.org/TR/rdf-syntax-grammar
  • JSON-LD 1.1 — Speicher, Kellogg et al., W3C Recommendation (2020). w3.org/TR/json-ld11
  • FOAF Vocabulary Specification — Brickley & Miller. Vocabulaire “Friend of a Friend”.
  • DCMI Metadata Terms — Dublin Core Metadata Initiative. Vocabulaire dc:.
  • SKOS Simple Knowledge Organization System — Miles & Bechhofer, W3C Recommendation (2009). Vocabulaire skos:.

Navigation : << 1-Setup | Index | 3-GraphOperations >>

Retour au sommet