Il linguaggio RDF(S)
Secondo la proposta (e questa ci teniamo) del *W3C* il set di linguaggi su cui costruire il web semantico è RDF(S) (cioè RDFS + *RDF1*), un set di linguaggi dichiarativi basati su sintassi *XML*.
Due cose è bene che siano chiare fin dall'inizio. Il rapporto tra le diverse parti di RDF(S) e le parentele e le diversità con XML.
Il web semantico nasce come tentativo di controllare le informazioni ancorandole ad uno schema. Questa idea funziona se si dividono bene i compiti.
Da qualche parte avremo di sicuro i dati, da qualche parte di sicuro uno schema che definisce come i dati si strutturano e relazionano far loro, in mezzo serve un ulteriore livello perché abbiamo bisogno di tenere traccia di quando un dato specifico (istanza) può essere espresso a partire dallo schema.
Scendiamo nel concreto e vediamo come questo si realizzi in RDF(S).
In informatica una risorsa, un documento, è definibile in base al suo path; nel Web una risorsa è la localizzazione di un file affidata alle *URL*. Immaginiamo perciò di avere una risorsa di questo tipo
http://www.nomesito.it/nomecorso/nomecorso.html
Lo schema
Immaginiamo che i nostri contenuti siano relativi a corsi e lezioni online. Dobbiamo avere perciò uno schema, o ontologia, per definire quel dominio. Come dichiarazione iniziale si definiscono dei namespace (delle *URI*) che identificare i costrutti RDF, RDFS e l'ontologia. Per il resto lo schema descrive le classi e proprietà. Ne abbozzo un pezzetto.
<?xml version='1.0' encoding='ISO-8859-1'?>
<rdf:RDF
xmlns:rdf ="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:rdfs ="http://www.w3.org/2000/01/rdf-schema#"
xmlns:a=" http://www.nomesito.it/data/nomeontologia# ">
<rdfs:Class rdf:about resource="http://www.nomesito.it/data/nomeontologia#Corso"/>
<rdfs:subClassof rdf:resource="#Resource"/>
</rdfs:Class>
<rdfs:Class rdf:about resource="http://www.nomesito.it/data/nomeontologia#Argomento"/>
<rdfs:subClassof rdf:resource="#Corso"/>
</rdfs:Class>
<rdfs:Class rdf:about resource="http://www.nomesito.it/data/nomeontologia#Specializzazione"/>
<rdfs:subClassof rdf:resource="#Resource"/>
</rdfs:Class>
<rdfs:Property rdf:about resource="http://www.nomesito.it/data/nomeontologia#Titolo"/>
<rdfs:domain rdf:resource="#Corso"/>
<rdfs:range rdf:resource="#Literal"/>
</rdfs:Class>
<rdfs:Property rdf:about resource="http://www.nomesito.it/data/nomeontologia#Livello_di_Specializzazione"/>
<rdfs:domain rdf:resource="#Corso"/>
<rdfs:range rdf:resource="#Specializzazione"/>
</rdfs:Class>
<rdfs:Property rdf:about resource="http://www.nomesito.it/data/nomeontologia#Utenti"/>
<rdfs:domain rdf:resource="#Specializzazione"/>
<rdfs:range rdf:resource="#Utenti"/>
</rdfs:Class>
<rdfs:Property rdf:about resource="http://www.nomesito.it/data/nomeontologia#Preparazione_Utenti"/>
<rdfs:domain rdf:resource="#Specializzazione"/>
<rdfs:range rdf:resource="#Literal"/>
</rdfs:Class>
</rdf:RDF>
Abbiamo definito innanzi tutto una classe (rdfs:Class) che avrà come nome (rdf:about) la risorsa (rdf:resource=) http://www.nomesito.it/data/nomeontologia#Corso. I nomi delle risorse si identificano utilizzando URI. La parte dell'URL che precede # indica una precisa ontologia, indica il nome dello schema al quale è riferito un elemento, la parte successiva al # indica il nome che si è voluto dare a quell'elemento. Abbiamo poi detto che questa classe Corso è sottoclasse (rdfs.subClassof) di Resource. Resource rappresenta una risorsa, o una classe generica. Riferire un elemento a Resource significa dire che quell'elemento è genericamente una risorsa, significa collegarsi al livello radice del nostro dominio.
Considerando il livello radice come livello 0 la classe Corso apparterà al livello 1 del nostro dominio. La classe Argomento è a sua volta sottoclasse di Corso. La classe Corso ha una proprietà, ossia un attributo, chiamato Titolo, di tipo stringa. Questo lo si capisce in quanto l'elemento Titolo è stato definito come rdf:Property, con dominio (rdfs:domain) la classe Corso e con codominio (rdfs:range), Literal, ossia la risorsa standard che in *RDF* definisce i dati di testo, siano essi stringhe o interi.
Una classe può essere definita specificando i suoi attributi (e, per essere completi, ma lo vedremo più avanti, collegandola attraverso un metadato ad un URL). La classe Corso ha un titolo che deve essere specificato tramite una stringa. La classe Argomento in quanto sottoclasse di corso eredita la proprietà Titolo. Anche l'argomento quindi potrà essere definito da un titolo.
Ora entriamo negli aspetti più difficili della modellazione dello schema. La classe Corso ha una proprietà che si chiama Livello_di_Specializzazione. Questa proprietà ha il compito di tener traccia del livello di specializzazione col quale è stato preparato un corso. Questa proprietà non è però semplice, non è definibile semplicemente riempiendo una stringa, ma punta ad un'altra classe.
Nella classe Specializzazione abbiamo a loro volta due attributi. Uno indica il tipo di utenti, e punta ad un classe utenti non descritta nell'esempio, uno indica la preparazione di questi utenti. In pratica la proprietà Livello_di_Specializzazione, per il fatto di puntare ad un'altra classe, non è più una semplice proprietà ma diventa una relazione fra classi. Diversamente dalle relazioni di subClassof questa relazione è stata liberamente battezzata dal progettista. SubClassof possiede un significato molto chiaro e indica una parentela di ereditarietà: gli attributi del padre sono trasmessi ai figli. Le relazioni definite tramite le property non hanno un significato specifico, se non per il fatto di delimitare le proprietà di una classe attraverso quelle di un'altra.
Con questo piccolo esempio si può vedere le possibilità espressive di uno schema ontologico. Il corso può avere un livello di specializzazione che dipende dal tipo di utenti a cui si rivolge e dalla preparazione che si presume questi abbiano. Con una situazione di questo tipo si sta descrivendo una proprietà, Livello_di_Specializzazione, che ha un grado, con una sorta di restrizione a seconda dell'utente a cui di volta in volta si attribuisce.
I metadati
Adesso che abbiamo lo schema riprendiamo quanto detto più avanti. In partenza avevamo una risorsa, un documento, localizzabile da questa URL http://www.nomesito.it/nomecorso/nomecorso.html. Incominciamo a descrivere qualche metadato e ad indicare come questa risorsa si relaziona al nostro schema. Se gli schemi venivano scritti in file RDFS i metadati si esprimono all'interno di file RDF. Qui la dicharazione iniziale non necessita del namespace rdfs.
<?xml version='1.0' encoding='ISO-8859-1'?>
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:a=" http://www.nomesito.it/data/nomeontologia# ">
<a:Corso rdf:about="http://www.nomesito.it/nomecorso/nomecorso.html">
<a:Titolo="nomecorso"/>
</a:Corso>
<a:Argomento rdf:about=" http://www.nomesito.it/nomecorso/nomecorso.html"
a:Titolo="nomeargomento1"/>
</a:Argomento>
<a:Argomento rdf:about=" http://www.nomesito.it/nomecorso/nomecorso.html"
a:Titolo="nomeargomento2"/>
</a:Argomento>
</rdf:RDF>
Per il momento abbiamo prodotto dei metadati molto semplici. Abbiamo detto che la prima risorsa è un corso dal titolo nomecorso. Poi abbiamo detto che questa stessa risorsa è legata a due argomenti diversi. I metadati sono costituiti tutti da asserzioni (delle specie di affermazioni o dichiarazioni che si fanno su una risorsa).
Ogni asserzione è costituita, da un punto di vista logico, da tre elementi fondamentali: soggetto, predicato e oggetto. L'idea di partenza sarebbe che il soggetto sia una classe dello schema, il predicato una proprietà della classe, l'oggetto un dato. Per ottenere maggiore espressività questo regola può essere espansa. In realtà le classi dello schema possono essere espresse come URL. Ogni schema è identificabile da un namespace (che è un tipo di URI), attraverso il namespace di uno schema si può identificare la classe. La nostra classe #Argomento, sostituendo il cancelletto con lo schema dichiarato in cima al documento, potrebbe essere espansa come http://miosito/rdfs/nomeschema/Argomento. In questo modo si può notevolmente ampliare la capacità espressiva delle asserzioni RDF. Sia soggetto che predicato che oggetto possono essere considerate URI. Il soggetto sarà generalmente la classe di uno schema ma potrà anche essere la classe di uno schema diverso (usando l'URI per identificarla), il predicato sarà sempre un attributo (che può però puntare ad un'altra classe) , l'oggetto può essere o una stringa, oppure un'altra classe dello schema, o ancora una classe di schemi differenti (per collegare due schemi fra di loro).
La struttura a tripla delle asserzioni è molto flessibile, come abbiamo visto, e abbastanza potente. La sua potenza però può essere ampliata se si collegano fra loro più asserzioni. Le asserzioni si possono collegare facilmente tramite degli ID.
<a:Corso rdf:about="http://www.nomesito.it/nomecorso/nomecorso.html">
<a: Livello_di_Specializzazione =" http://www.nomesito.it/data/nomeontologia/model.rdf#ID_13"/>
</a:Corso>
<a:Specializzazione rdf:about="http://www.nomesito.it/data/nomeontologia/model.rdf#ID_13"
a:Preparazione_Utenti="alta"/>
</a: Specializzazione >
<a:Specializzazione rdf:about="http://www.nomesito.it/data/nomeontologia/model.rdf#ID_13"
a:Utenti=" http://www.nomesito.it/data/nomeontologia/model.rdf#ID_14"/>
</a: Specializzazione >
<a:Utenti rdf:about="http://www.nomesito.it/data/nomeontologia/model.rdf#ID_14"
a:nome="nomeutenti"/>
</a: Specializzazione >
Ma posso anche inserire un'asserzione nell'altra ampliando la complessità della sua struttura. In questo caso dico che in una certa pagina si dice che c'è un corso che ha titolo nomecorso.
<rdf:Description rdf:about=" http://www.nomesito.it/nomecorso/nomesito.html">
<a:assert
rdf:resource="http:// http://www.nomesito.it/data/nomeontologia/model.rdf#ST_168_sp"/>
</rdf:Description>
<rdf:statement rdf:about=" http://www.nomesito.it/data/nomeontologia/model.rdf#ST_168_sp">
<rdf:subject rdf:resource="#Corso"/>
<rdf:predicate rdf:resource="#Titolo"/>
<rdf:object rdf:resource="nomecorso"/>
</rdf:statement>
Questo modo di concatenare asserzioni viene chiamato reificazione. Per un approfondimento sul tema si rimanda al documento Metadati: RDF e RDFS.
RDF oltre XML
Dopo aver chiarito la differenza tra RDFS e RDF. Vediamo quali differenze ci sono tra RDF(S) e XML. Le differenze fondamentali sono sicuramente due.
Per prima cosa RDF(S) è stato pensato espressamente per esprimere metadati. XML fa molte cose, e può anche essere usato per descrivere metadati, ma generalmente ha un rapporto molto più stretto con i dati, contiene già in se dei dati che possono essere richiamati. RDF(S) esprime metadati, nel senso più proprio: di un documento descrive contenuti che nel documento non sono presenti.
L'altra differenza rispetto a XML è legata alla capacità espressiva di descrivere le relazioni. XML è centrato su una struttura a inclusione, riesce perciò ad esprimere senza difficoltà le relazioni di parentela o di essere parte di, ma per le altre relazioni dimostra dei limiti. Se volessi esprimere una relazione associativa fra due classi, cioè dire che esse hanno una relazione ma non sono incluse una nell'altra, con XML devo ricorrere agli ID e IDREF.
Ad esempio per dire che un corso ha un livello di specializzazione dovrei scrivere:
<xsd:complexType namespace="CORSO">
<xsd.:element namespace="TITOLO" type="xsd:string">
<xsd.:element namespace="LIV_SPECId" type="IDREFS">
</xsd:complexType>
<xsd:complexType namespace="SPECIALIZZAZIONE">
<xsd.:element namespace="UTENTI" type="xsd:string">
<xsd.:element namespace="PRE_UTENTI" type="xsd:string">
<xsd.:element namespace="CORSOId" type="ID">
</xsd:complexType>
Non è impossibile ma perché la relazione funzioni il controllo deve essere doppio, verificando che id coincida con idref. Inoltre per non allungare l'esempio ho dovuto considerare Utenti come un elemento semplice, rinunciando a descrivere Utenti come classe. La cosa avrebbe ulteriormente complicato il codice obbligando ad inserire delle keyref. Per una spiegazione più approfondita su come si possono rendere i vari tipi di relazione in XML trovate un articolo molto completo sul sito dell'Association for Computing Machinery
Per una semplice ma efficace descrizione delle differenze tra XML e RDF consiglio l'introduzione all'ontology engineering del prof. Ernesto Damiani. Da non perdere naturalmente le specifiche ufficiali del linguggio RDF e un documento in PDF di Oreste del Signore, Manager dell'ufficio italiano del W3C.