Semantic Web Practical Sessions Answers
Semantic Web Practical Sessions Answers
by : Yassine ASSAFI
Email : [email protected]
• A real text editor (e.g. Notepad++, Gedit, Sublime Text, Emacs, etc.)
• The RDF XML online validation service by W3C: https://www.w3.org/RDF/Validator/
• The RDF online translator: http://rdf-translator.appspot.com/
• The SPARQL Corese engine: https://project.inria.fr/corese/
Create RDF
Read carefully the following statements:
“Jen is a 42-year old woman and she has a shoe size of 36 and trouser size of 38. She is,
married to Seb who is a man with whom she had two children: Anny who is a woman and
Steffen who is a man. Jen is also an engineer and Catherine and Fabien are her colleagues.
Jen’s father is a man named Thomas”
1. Use your text editor and write the above statements in RDF in N3 syntax inventing your own vocabulary.
Save you file as “Jen.ttl”
2. Use your favorite text or XML editor and write the above statements in RDF in XML syntax reusing the
same vocabulary “Jen.rdf”
3. Use the RDF XML online validation service to validate your XML and see the triples
https://www.w3.org/RDF/Validator/
4. In the validator use the option to visualize the graph
5. Use the RDF online translator to validate your N3 and translate it into RDF/XML:
http://rdf-translator.appspot.com/
6. Compare your RDF/XML with the result of the N3 translation
7. Translate in other formats to see the results.
<#Seb> a :Man;
:name "Seb"^^xsd:string;
:hasChild <#Anny>, <#Steffen>;
:hasSpouse <#Jen>.
<#Anny> a :Woman;
:name "Anny"^^xsd:string.
<#Steffen> a :Man;
:name "Steffen"^^xsd:string.
<#Thomas> a :Man;
:name "Thomas"^^xsd:string.
<#Catherine> a :Woman;
:name "Catherine"^^xsd:string.
<#Fabien> a :Man;
:name "Fabien"^^xsd:string.
<rdf:Description rdf:about="#Jen">
<rdf:type rdf:resource="&class;#Woman"/>
<rdf:type rdf:resource="&class;#Engineer"/>
<name rdf:datatype="&xsd;string">Jen</name>
<age rdf:datatype="&xsd;integer">42</age>
<shoesize rdf:datatype="&xsd;integer">36</shoesize>
<trousersize rdf:datatype="&xsd;integer">38</trousersize>
<hasSpouse rdf:resource="#Seb"/>
<hasChild rdf:resource="#Anny"/>
<hasChild rdf:resource="#Steffen"/>
<hasFather rdf:resource="#Thomas"/>
<hasColleague rdf:resource="#Fabien"/>
<hasColleague rdf:resource="#Catherine"/>
</rdf:Description>
<rdf:Description rdf:about="#Seb">
<rdf:type rdf:resource="&class;#Man"/>
<name rdf:datatype="&xsd;string">Seb</name>
<hasSpouse rdf:resource="#Jen"/>
<hasChild rdf:resource="#Anny"/>
<hasChild rdf:resource="#Steffen"/>
</rdf:Description>
<rdf:Description rdf:about="#Anny">
<rdf:type rdf:resource="&class;#Woman"/>
<name rdf:datatype="&xsd;string">Seb</name>
</rdf:Description>
<rdf:Description rdf:about="#Steffen">
<rdf:type rdf:resource="&class;#Man"/>
<name rdf:datatype="&xsd;string">Steffen</name>
</rdf:Description>
<rdf:Description rdf:about="#Thomas">
<rdf:type rdf:resource="&class;#Man"/>
<name rdf:datatype="&xsd;string">Thomas</name>
</rdf:Description>
<rdf:Description rdf:about="#Fabien">
<rdf:type rdf:resource="&class;#Man"/>
<name rdf:datatype="&xsd;string">Fabien</name>
</rdf:Description>
<rdf:Description rdf:about="#Catherine">
<rdf:type rdf:resource="&class;#Woman"/>
<name rdf:datatype="&xsd;string">Catherine</name>
</rdf:Description>
</rdf:RDF>
Query your data
Download the Corese.jar library and start it as a standalone application: On Window double-click the file “.jar”.
If it does not work or on other platforms, run the command " java -jar -Dfile.encoding=UTF8 " followed by the
name of the “.jar” archive. Notice that you need java on your machine and proper path configuration.
This interface provides two tabs: (1) one to load input files and see traces of execution, and (2) the default tab
to start loading or writing queries and see their result. Load the annotations contained in the file “Jen.rdf” you
created and validated before. The interface contains a default SPARQL query:
The SPARQL language will be presented in the next course. Just know that this query can find all of the
resources referred to in the data you loaded and their types. Launch the query and check the results.
1, Get the RDF/XML about http://ns.inria.fr/fabien.gandon#me and translate the RDF/XML into Turtle/N3
<http://ns.inria.fr/fabien.gandon> a foaf:PersonalProfileDocument ;
foaf:maker <http://ns.inria.fr/fabien.gandon#me> ;
foaf:primaryTopic <http://ns.inria.fr/fabien.gandon#me> .
<http://ns.inria.fr/fabien.gandon#me> a foaf:Person ;
foaf:title "Dr" ;
foaf:family_name "Gandon" ;
foaf:givenname "Fabien" ;
foaf:name "Fabien Gandon" ;
foaf:nick "Bafien" ;
foaf:knows [ a foaf:Person ;
rdfs:seeAlso <http://www.i3s.unice.fr/~faron/> ;
foaf:mbox <mailto:[email protected]> ;
foaf:name "Catherine Faron-Zucker" ],
[ a foaf:Person ;
rdfs:seeAlso <http://www-sop.inria.fr/members/Olivier.Corby/> ;
foaf:mbox <mailto:[email protected]> ;
foaf:name "Olivier Corby" ] ;
foaf:homepage <http://fabien.info> ;
foaf:depiction <http://www-sop.inria.fr/members/Fabien.Gandon/common/FabienGandonBackground.jpg>
foaf:mbox <mailto:[email protected]> ;
foaf:phone <http://ns.inria.fr/tel:0492387788> ;
foaf:schoolHomepage <http://www.insa-rouen.fr> ;
foaf:workInfoHomepage <http://fabien.info> ;
foaf:workplaceHomepage <http://www.inria.fr/> .
2, Get the Turtle data of Paris on DBpedia.org then in the file find the triple that declares it as a capital in
Europe.
3, If you don’t have the human dataset file yet, at the following address you will find an RDF file containing
several annotations:
http://wimmics.inria.fr/doc/tutorial/human_2013.rdf
Download the file and use the RDF XML online validation service to validate the XML and see the triples and the
graph.
1. What is the namespace used for instances / resources created in this file?
xml:base="http://www.inria.fr/2007/09/11/humans.rdfs-instances">
2. By which mechanism is the association between instances and namespace done i.e. how was the
instance namespace specified?
By defining the BASE namespace in the root.
3. What is the namespace of the vocabulary used to describe the resources in the dataset and how is
it associated with the tags?
xmlns="http://www.inria.fr/2007/09/11/humans.rdfs#"
John is a Person
name : John
shoesize : 14
shirtsize : 12
trousersize : 44
age : 37
has parent : Sophie, Harry
father of : Mark
friend of : Alice
spouse of : Jennifer
<http://www.inria.fr/2007/09/11/humans.rdfs-instances#Eve> a :Lecturer,
:Person ;
:hasFriend <http://www.inria.fr/2007/09/11/humans.rdfs-instances#Alice> ;
:hasSpouse <http://www.inria.fr/2007/09/11/humans.rdfs-instances#David> ;
:name "Eve" .
<http://www.inria.fr/2007/09/11/humans.rdfs-instances#Flora> a :Woman ;
:age 95 ;
:hasChild <http://www.inria.fr/2007/09/11/humans.rdfs-instances#Pierre> ;
:hasSpouse <http://www.inria.fr/2007/09/11/humans.rdfs-instances#Gaston> ;
:name "Flora" .
• A real text editor (e.g. Notepad++, Gedit, Sublime Text, Emacs, etc.)
• The RDF XML online validation service by W3C: https://www.w3.org/RDF/Validator/
• The SPARQL Corese engine: https://project.inria.fr/corese/
• The human dataset file and the human shape file from the archive
With you text editor open the file human_2013_shape.ttl and look at the content
In Corese load the dataset human_2013_dataset_rdf.ttl (menu “load RDF”) and this shape (menu “load SHACL”)
and run the validation in a query tab (button “SHACL”). Explain in English what the report is saying:
The validation reports indicates false conformity. The :Person Karl is missing a name, so we get a violation.
Extend the shape to add a constraint of severity level “Warning” enforcing that a Person should have an age:
sh:property [
sh:message "a Person must have an age"@en;
sh:severity sh:Warning;
sh:path :age ;
sh:minCount 1
].
In Corese load the human dataset (menu “load RDF”) and this shape (menu “load SHACL”) and run the
validation in a query tab (button “SHACL”). Explain in English shat the report is saying:
The validation reports indicates false conformity. There are 3 warnings and 1 violation. The :Person Karl is missing
a name, and the people Eve, David and Laura are missing the age value.
Extend the shape to add a constraint of severity level “Info” enforcing that a person’s name should be in
English:
sh:property [
sh:message "a Person name must be in english"@en;
sh:severity sh:Info;
sh:path :name ;
sh:languageIn ( "en" )
].
In Corese load the human dataset (menu “load RDF”) and this shape (menu “load SHACL”) and run the
validation in a query tab (button “SHACL”). Explain in English shat the report is saying:
In addition to past 1 violation and 3 warnings, the validation reports indiquates 6 new non-conformities of
severity INFO.
Day 03: Answers to the practical session on SPARQL.
Software requirements
• The RDF XML online validation service by W3C: https://www.w3.org/RDF/Validator/
• The RDF online translator: http://rdf-translator.appspot.com/
• The SPARQL Corese engine: https://project.inria.fr/corese/
On Window double-click the file “.jar”. If it does not work or on other platforms, run the command " java -jar -
Dfile.encoding=UTF8 " followed by the name of the “.jar” archive. Notice that you need java on your machine
and proper path configuration
This interface provides two tabs: (1) one to load input files and see traces of execution, and (2) the default tab to
start loading or writing queries and see their result.
If you don’t have the human dataset file yet download the following file of annotations and save it as “human.rdf”:
http://wimmics.inria.fr/doc/tutorial/human_2013.rdf
Question 1:
Create a new tab to enter the following query and explain what it does and the results you get. This is a good way to
familiarize yourself with the data.
CONSTRUCT { ?s ?p ?o } WHERE { ?s ?p ?o }
Explanation:
Screenshot:
Question 2:
Create a new tab to enter the following query:
prefix h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
select * where { ?x a ?t . filter(strstarts(?t, h:)) }
Translate this query in plain English.
Returns all triples for which the resources correspond to Types (ex: Man, Lecturer..) that have the qualified name
h:Type.
21
Question 3:
1. formulate a SELECT query to find all the properties of John, using his URI
Query
PREFIX c: <http://www.inria.fr/2007/09/11/humans.rdfs-instances#>
SELECT ?p ?y
WHERE { { c:John ?p ?y } UNION { ?x ?p c:John } }
Results:
Query
DESCRIBE <http://www.inria.fr/2007/09/11/humans.rdfs-instances#John>
Results:
Question 4
Create a new tab to enter the following query:
prefix h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
select * where { ?x h:hasSpouse ?y }
Translate this query in plain English.
6 triples
Question 5:
In the RDF file, find the name of the property that is used to give the shoe size of a person.
1. Deduce a query to extract all the persons (h:Person) with their shoe size.
Query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
SELECT ?x ?size
WHERE { ?x a h:Person; h:shoesize ?size }
Result:
2. Change this query to retrieve all the persons and, if available, their shoe size.
Query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
SELECT ?x ?size
WHERE { ?x a h:Person. OPTIONAL { ?x h:shoesize ?size} }
Result:
3. Change this query to retrieve all the persons whose shoe size is greater than 8 or whose shirt size is greater than
12.
Query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
SELECT ?x ?shoesize?shirtsize
WHERE { ?x a h:Person; h:shoesize ?shoesize; h:shirtsize ?shirtsize. FILTER(?shoesize>=8 || ?shirtsize>=12) }
Result:
Question 6:
In the RDF file, find the name of the property that is used to indicate the children of a person.
1. Formulate a query to find the parents who have at least one child.
Query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
SELECT ?x
WHERE { ?x h:hasChild ?y }
How many answers do you get? How many duplicates do you identify in these responses?
Query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
SELECT DISTINCT ?x
WHERE { ?x h:hasChild ?y }
4 answers.
Query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
SELECT ?x
WHERE { ?x a h:Person. FILTER ( ! EXISTS { ?x h:hasChild ?y } ) }
Question 7
In the RDF file, find the name of the property that is used to give the age of a person.
Query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
SELECT ?x ?age
WHERE { ?x a h:Person. OPTIONAL {?x h:age ?age} }
Result:
Query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
SELECT ?x ?age
WHERE { ?x a h:Person; h:age ?age. FILTER ( ?age < 18 ) }
1 answer.
3. Use the appropriate query clause to check if Mark is an adult; use the proper clause statement for this type of
query to get a true or false answer.
Query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
ASK { ?x a h:Person; h:name "Mark"; h:age ?age. FILTER ( ?age >= 18 ) }
4. Write a query that indicates for each person if her age is even (true or false).
Query:
1. Construct the symmetric of all hasFriend relations using the good SPARQL statement (ex. When finding Thomas
hasFriend Fabien, your query should construct Fabien hasFriend Thomas)
Query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
CONSTRUCT { ?y h:hasFriend ?x }
WHERE { ?x h:hasFriend ?y }
2. Insert the symmetric of all hasFriend relations using the adequate SPARQL statement but check the results with
a select query before and after.
Query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
INSERT { ?y h:hasFriend ?x }
WHERE { ?x h:hasFriend ?y }
Question 9
Choose and edit one of the SELECT WHERE queries previously written to transform them into a CONSTRUCT WHERE
query (retaining the same WHERE clause) in order to visualize the results as a graph.
Query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
CONSTRUCT { ?x h:age ?age }
WHERE { ?x a h:Person; h:age ?age. FILTER ( ?age < 18 ) }
Result:
Question 10
Edit the file to add your own annotation (about you) to the RDF file reusing the properties of the file. Build queries to
verify and visualize the annotations you added.
Addition to file:
<Man rdf:ID="Yassine">
<shoesize rdf:datatype="&xsd;integer">10</shoesize>
<trouserssize rdf:datatype="&xsd;integer">36</trouserssize>
<age rdf:datatype="&xsd;integer">26</age>
<shirtsize rdf:datatype="&xsd;integer">10</shirtsize>
<name>Yassine</name>
<hasMother rdf:resource="#Catherine"/>
<hasFather rdf:resource="#Karl"/>
<hasFriend rdf:resource="#Alice"/>
</Man>
screenshots:
Question 11
1. Formulate a query to find the persons who share the same shirt size.
Query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
SELECT ?x ?y
WHERE { ?x h:shirtsize ?size. ?y h:shirtsize ?size. FILTER (?x != ?y && ?x<?y) }
2. Find the persons who have the same size shirt and construct a seeAlso relationship between them.
Query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
CONSTRUCT { ?x rdfs:seeAlso ?y }
WHERE { ?x h:shirtsize ?size. ?y h:shirtsize ?size. FILTER (?x != ?y && ?x<?y) }
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
INSERT { ?x rdfs:seeAlso ?y }
WHERE { ?x h:shirtsize ?size. ?y h:shirtsize ?size. FILTER (?x != ?y && ?x<?y) }
screenshot:
5. Adapt the first query to find persons who have the same shoe size and insert a seeAlso relationship between
them.
Query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
INSERT { ?x rdfs:seeAlso ?y }
WHERE { ?x h:shoesize ?size. ?y h:shoesize ?size. FILTER (?x != ?y && ?x<?y) }
screenshot:
7. Change the query to find the resources connected by a path consisting of one or several seeAlso relationships.
Query:
8. Reload the engine (option reload in the menu) and rerun the last visualization query.
Question 12
1. Find the largest shoe size
Query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
SELECT ( max(?size) AS ?maxshoesize )
WHERE { ?x h:shoesize ?size }
2. Find people who have the biggest size of shoe (subquery + aggregate)
Query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
SELECT ?x
WHERE { {
SELECT ( max(?size) AS ?maxshoesize )
WHERE { ?x h:shoesize ?size } }
?x h:shoesize ?maxshoesize }
3. Calculate the average shoe size using the appropriate aggregation operator
Query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
SELECT ( avg(?size) AS ?avgshoesize )
WHERE { ?x h:shoesize ?size }
Result = "9.285714285714286"^^xsd:decimal
4. Check the average with your own calculation using sum() and count()
Query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
SELECT ?avgshoesize
WHERE { {
SELECT ( sum(?size) AS ?sumshoesize ) (count(?size) AS ?countshoesize)
WHERE { ?x h:shoesize ?size } }
BIND ( ?sumshoesize/?countshoesize AS ?avgshoesize ) }
Result = "9.285714285714286"^^xsd:decimal
Question 13
Find couples without children
Query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
SELECT ?x ?y
WHERE { ?x h:hasSpouse|^h:hasSpouse ?y. MINUS { ?x h:hasChild ?z } }
Question 14
Using INSERT DATA, create a new person with its properties. Then, check that it has been created.
Insert:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
PREFIX i: <http://www.inria.fr/2007/09/11/humans.rdfs-instances#>
INSERT DATA { i:Yassine a h:Man;
h:age 26;
h:name "Yassine";
h:shoesize 10;
h:hasFriend i:Harry, i:Sophie. }
Screenshot result:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
PREFIX i: <http://www.inria.fr/2007/09/11/humans.rdfs-instances#>
SELECT *
WHERE { i:Yassine ?p ?v }
Question 15
Find the people connected by paths of any family links. Construct an arc seeAlso between them to visualize the
result.
query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
SELECT ?x ?y
WHERE { { ?x (h:hasChild|h:hasParent|h:hasMother|h:hasFather)+ ?y }
UNION { ?x h:hasSpouse/h:hasChild ?y }
UNION { ?x h:hasSpouse/^h:hasSpouse ?y }
FILTER (?x != ?y) }
screenshot:
Question 16
Run the following query:
prefix db: <http://dbpedia.org/ontology/>
prefix foaf: <http://xmlns.com/foaf/0.1/>
prefix h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
construct { ?x h:name ?nx . ?y h:name ?ny . ?x h:hasSpouse ?y }
where {
service <http://fr.dbpedia.org/sparql/> {
select * where {
?x db:spouse ?y .
?x foaf:name ?nx .
?y foaf:name ?ny .
}
limit 20
}
}
The Query constructs the RDF triples by using the top 20 rows of the results obtained from a query that is sent
remotely to the dbpedia SPARQL endpoint. This query extracts spouses and their names using dbpedia and foaf
ontologies and constructs them locally using humans.rdfs ontology.
modify it to insert new persons in the base and check the results.
query:
Software requirements
• The RDF XML online validation service by W3C: https://www.w3.org/RDF/Validator/
• The RDF online translator: http://rdf-translator.appspot.com/
• The SPARQL Corese engine: https://project.inria.fr/corese/
• Write the RDF schema that you used in the description of Jen in a RDF/XML (or in turtle and then translate it)
and save the RDF/XML in a file called “Family.rdfs”. Of course, this assumes that the URIs for the classes and
properties declared/used must match in both files. You mays have to update the files Jen.rdf and Jen.ttl to use
your ontology.
Your schema:
<#Person> a :Class ;
:label "human"@en, "person"@en,"homme"@fr, "personne"@fr, "être humain"@fr ;
:comment "a member of the human species"@en, "un membre de l'espèce humaine."@fr.
<#Man> a :Class ;
:subClassOf <#Person>;
:seeAlso <#Woman>;
:label "man"@en, "homme"@fr;
:comment "an adult male person"@en, "mâle adulte de l'espèce humaine."@fr.
<#Woman> a :Class ;
:subClassOf <#Person>;
:seeAlso <#Man>;
:label "woman"@en, "femme"@fr;
:comment "an adult female person"@en, "femelle adulte de l'espèce humaine."@fr.
<#Engineer> a :Class ;
:subClassOf <#Person>;
:label "engineer"@en, "ingénieur"@fr;
:comment "a person who designs or maintains machines or structures."@en, "personne qui conçoit
ou entretient des machines ou des structures."@fr.
<#Researcher> a :Class ;
:subClassOf <#Person>;
:label "researcher"@en, "scientist"@en, "chercheur"@fr, "scientifique"@fr;
:comment "a person who devotes himself to doing research"@en, "personne adonnée à des
recherches spécialisées."@fr.
<#name> a rdf:Property ;
:range :Literal;
:label "name"@en, "nom"@fr ;
:comment "designation of something."@en, "désignation de quelque chose."@fr .
<#age> a rdf:Property ;
:label "age"@en, "âge"@fr ;
:comment "complete existence duration."@en, "durée complète d'existence."@fr .
<#shirtsize> a rdf:Property ;
:domain <#Person> ;
:label "shirt size"@en, "size"@en, "taille"@fr,"taille de chemise"@fr ;
:comment "express in some way the approximate dimensions of the shirts of a person."@en,
"dimensions approximatives des chemises portées par une personne."@fr .
<#shoesize> a rdf:Property ;
:domain <#Person> ;
:label "shoe size"@en, "size"@en, "pointure"@fr ;
:comment "express in some way the approximate length of the shoes for a person."@en, "taille,
exprimée en points, des chaussures d'une personne."@fr .
<#trouserssize> a rdf:Property ;
:domain <#Person> ;
:label "size"@en, "trousers size"@en, "taille"@fr, "taille de pantalon"@fr ;
:comment "express in some way the approximate dimensions of the trousers of a person."@en,
"dimensions approximatives des pantalons portés par une personne."@fr .
<#hasChild> a rdf:Property ;
:domain <#Person> ;
:range <#Person> ;
:label "has for child"@en, "a pour enfant"@fr ;
:comment "relation between an animal and another animal to which it gave birth."@en, "relation
entre un animal et un autre animal auquel il a donné naissance."@fr .
<#hasFather> a rdf:Property ;
:subPropertyOf <#hasParent>;
:domain <#Person> ;
:range <#Man> ;
:label "has for father"@en, "a pour père"@fr ;
:comment "to have for parent a male."@en, "avoir pour parent un mâle."@fr .
<#hasMother> a rdf:Property ;
:subPropertyOf <#hasParent>;
:domain <#Person> ;
:range <#Woman> ;
:label "has for mother"@en, "a pour mère"@fr ;
:comment "to have for parent a female."@en, "avoir pour parent un femmelle."@fr .
<#hasParent> a rdf:Property ;
:domain <#Person> ;
:range <#Person> .
<#hasSpouse> a rdf:Property ;
:domain <#Person> ;
:range <#Person> ;
:label "has for spouse"@en, "est en ménage avec"@fr ;
:comment "a person's partner in marriage."@en, "le partenaire d'une personne dans un
mariage."@fr .
<#hasColleague> a rdf:Property ;
:domain <#Person> ;
:range <#Person> ;
:label "has for colleague"@en, "a pour collègue"@fr ;
:comment "to have a person with whom one works in a profession."@en, "avoir une personne avec
qui on travaille dans une profession."@fr .
• Check that your RDF schema and RDF files are valid using the W3C's RDF validation service.
• Launch the standalone interface of Corese and load your files Family.rdfs and Jen.rdf
• The interface contains a default SPARQL query:
Select ?x ?t where {?x rdf:type ?t}
Launch the query and look at the results.
Screenshot:
• Modify your ontology to declare the classes of Man and Woman as sub classes of Human (don’t change the
data), reload the schemas and data and search for the humans to see the results
Screenshot:
PREFIX h: <http://dsti.institute/family.rdfs#>
SELECT ?x
WHERE {?x a h:Human}
Explanation:
Since Man and Woman are subclasses of Human, all their instances are inferred to be Human as well.
• Modify your ontology to declare the properties hasChild and hasSpouse as sub properties of familyLink (don’t
change the data), reload the schemas and data and search for the family links to see the results.
Screenshot:
PREFIX h: <http://dsti.institute/family.rdfs#>
SELECT ?x ?y
WHERE {?x h:familyLink ?y}
Explanation:
Since hasChild and hasSpouse are subproperties of familyLink, all the instances related using these relations are
also inferred to be related with familyLink.
• Modify your ontology to declare the class FamilyMember and use it to specify the signature of the property
familyLink (don’t change the data) then reload the schemas and data and search for the family members.
Screenshot:
Explanation:
Since we applied the signature on familyLink, all instances involved will be inferred as a FamilyMember.
About the human.rdfs schema
1. If you don’t have the human schema file yet, download the RDF schema available at this address and
save it as “human.rdfs”:
http://wimmics.inria.fr/doc/tutorial/human_2013.rdfs
2. What is the namespace associated with this ontology? How was it associated?
3. Look at the XML structure of this file and locate different syntactic properties: the different possible uses of the
markup (ex: opening tag and closing, single tag), the use of namespaces for qualified names, the use of entities,
etc.
4. Locate the use of the terms of the RDF (S) language: Class, Property, label, comment, range, domain, subClassOf,
subPropertyOf, etc. To what namespaces are they associated?
Apart from “Property” which belongs to the namespace rdf, all the other statements belong to rdfs :
"http://www.w3.org/2000/01/rdf-schema#"
5. What are the classes of resources that can have the age property? Explain
There’s no restriction and no implicit inference with domain and range. So all resources can have the age
property.
6. Look at the beginning of the file and draw the subgraph of the hierarchy containing the classes Animal, Man
and Woman.
Reset or relaunch the standalone Corese search engine interface and load the file human.rdfs (and only this one).
query:
query:
3. Write a query to find the definitions and translations of "shoe size" (other labels and comments in different
languages for the resource labeled "shoe size").
query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT *
WHERE { { h:shoesize rdfs:label ?y }
UNION { h:shoesize rdfs:comment ?y} }
answers:
4. Write a query to find the synonyms in French of the word 'personne' in French (other labels in the same
language for the same resource/class/property). What are the answers?
query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?y
WHERE { h:Person rdfs:label ?y. FILTER(lang(?y)="fr" && ?y!="personne"@fr) }
answers:
5. Write a query to find the different meaning of the term "size" (disambiguation using the different comments
attached to different resources/classes/properties having the label "size"). What are the answers?
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?y
WHERE { ?x rdfs:comment ?y; rdfs:label "size"@en. FILTER(lang(?y)="en") }
answers:
6. Write a query to find the properties that use the class Person in their signatures?
query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT DISTINCT ?x
WHERE { ?x a rdf:Property; rdfs:domain|rdfs:range h:Person }
7. Make CORESE draw the graph of the hierarchy of Classes using a CONSTRUCT query considering only the classes
in the humans.rdfs schema
query:
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
CONSTRUCT { ?x rdfs:subClassOf ?y }
WHERE { ?x rdfs:subClassOf ?y }
screenshot:
8. To the previous CONSTRUCT add the signatures of the relations.
query:
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
CONSTRUCT { ?x rdfs:subClassOf ?y. ?v rdfs:domain ?w. ?m rdfs:range?n }
WHERE { {?x rdfs:subClassOf ?y} UNION {?v rdfs:domain ?w} UNION {?m rdfs:range?n} }
screenshot:
Question 1
1. Reset the Corese engine and load only the annotations (.rdf)
2. Write a query to find the Persons.
Query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
SELECT ?x
WHERE { ?x a h:Person }
New number of results after and your explanation: 17. The number has grown because when the schema was
added, subsumptions were added such as subclasses of Person or signatures of properties, so new entities are
added to results.
Question 2
1. Write a query to find Males and their wives. How many answers do you get? Explain this result.
Query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
SELECT ?x ?y
WHERE { ?x a h:Male; h:hasSpouse ?y }
2. In the data declare that Lucas has as father Karl. Reset Corese, reload the ontology and the data, and then rerun
the query to find Males and their wives. Explain the new result.
Question 3
1. Write a query to find the Lecturers and their types. How many answers do you get? See how this typing is
declared in the data and explain the result.
Query:
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
SELECT ?x ?y
WHERE { ?x a h:Lecturer; rdf:type ?y }
Laura is a Person, Lecturer and Research because she was declared as so, but were also added Female and Animal.
Animal comes from the fact Person is subclass of Animal, and Female from the fact she was assigned as a Mother
of Catherine.
2. Write a query to find common instances of the classes Person and Male. See how this typing is declared in the
data and explain the presence of Jack.
Query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
SELECT ?x
WHERE { ?x a h:Person, h:Male }
Your explanation of the result:
We get Jack because he is a Man, which is a subclass of both Male and Person.
Question 4
Write a query to find the hasAncestor relations. Explain the result after checking where this property is used in the
data.
Query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
SELECT ?x ?y
WHERE { ?x h:hasAncestor ?y }
Question 5
1. Write a query to find the family cores (couples and their children) using a SELECT
Query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
SELECT ?x ?y ?child
WHERE { ?x h:hasSpouse|^h:hasSpouse ?y.
OPTIONAL { ?x h:hasChild|^h:hasParent ?child } }
Query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
CONSTRUCT { ?x h:hasSpouse ?y. ?child h:hasParent ?x}
WHERE { ?x h:hasSpouse|^h:hasSpouse ?y.
OPTIONAL { ?x h:hasChild|^h:hasParent ?child } }
Question 6
1. Declare the olderThan relationship in the schema to indicate between two people which is eldest and construct
the arcs between peoples with a SPARQL query
Addition to schema:
<rdf:Property rdf:ID="olderThan">
<domain rdf:resource="#Person"/>
<range rdf:resource="#Person"/>
<label xml:lang="en">is older Than</label>
<comment xml:lang="en">relation between a person and another person that describes who is
older.</comment>
<label xml:lang="fr">plus âgé que</label>
<comment xml:lang="fr">relation entre une personne et une autre personne qui décrit qui est plus âgé que
l'autre.</comment>
</rdf:Property>
Query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
CONSTRUCT { ?x h:olderThan ?y }
WHERE {?x h:age ?xage. ?y h:age ?yage. FILTER ( ?xage > ?yage ) }
2. Find a query that generates only the minimum number of links without redundancy with olderThan transitivity.
Query:
PREFIX h:<http://www.inria.fr/2007/09/11/humans.rdfs#> .
CONSTRUCT { ?x h:olderThan ?y}
WHERE { ?x h:age ?xage.
?y h:age ?yage.
FILTER (?xage > ?yage && NOT EXISTS { z h:age ?zage. FILTER (?xage > ?zage && ?zage > ?yage) } ) }
Question 7
Write a query to find for John the properties which label contains the string "size" and the value of these properties.
Query:
PREFIX i: <http://www.inria.fr/2007/09/11/humans.rdfs-instances#>
SELECT DISTINCT ?p ?v
WHERE {i:John ?p ?v. ?p rdfs:label ?label. FILTER( CONTAINS(?label, "size") ) }
Question 8
Use the ontology to document your answers in natural language: write a query to find the types and properties of
Laura in French.
Query:
My query returns all the French labels and comments of both types and properties associated with Laura.
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
PREFIX i: <http://www.inria.fr/2007/09/11/humans.rdfs-instances#>
SELECT ?entity ?label ?comment
WHERE { { i:Laura rdf:type ?type.
?type rdfs:label ?label; rdfs:comment ?comment.
FILTER( lang(?label)="fr" && lang(?comment)="fr" )
BIND (STRAFTER(?type, STR(h:)) AS ?entity)}
UNION
{ i:Laura ?prop ?value.
?prop rdfs:label ?label; rdfs:comment ?comment.
FILTER( lang(?label)="fr" && lang(?comment)="fr" )
BIND (STRAFTER(?prop, STR(h:)) AS ?entity) }
}
Day 04: Answers to the practical session on OWL.
Software requirements
• The RDF XML online validation service by W3C: https://www.w3.org/RDF/Validator/
• The RDF online translator: http://rdf-translator.appspot.com/
• The SPARQL Corese engine: https://project.inria.fr/corese/
Make a copy of the human.rdfs file, name it humans.owl and use it for the rest of the session. For each of the
following statements, specify a SPARQL query that shows that the difference before and after running the OWL
inferences: you will find that answers to these queries are different depending on whether you load the ontology
humans.rdfs or the humans.owl you modified.
1. Declare that hasSpouse is a symmetrical property and do the same for and hasFriend .
<owl:SymmetricProperty rdf:ID="hasSpouse"/>
<owl:SymmetricProperty rdf:ID="hasFriend"/>
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
SELECT ?x ?y
WHERE {?x h:hasSpouse ?y}
Explanation:
Since hasSpouse has become symmetric, this relation once applied in one direction, becomes also applied in the
other. So we get the same results as when querying with : WHERE {?x h:hasSpouse|^h:hasSpouse ?y}
2. Declare that hasChild is the inverse property of the hasParent property.
<rdf:Property rdf:ID="hasChild">
<owl:inverseOf rdf:resource="#hasParent"/>
</rdf:Property>
Query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
SELECT ?x ?y
WHERE {?x h:hasChild ?y}
Explanation:
Since hasChild is the invere of hasParent, all resources linked in one direction with hasParent will also be assigned
the inverse property hasChild in the other direction.
<owl:TransitiveProperty rdf:ID="hasAncestor"/>
Query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
SELECT ?x ?y
WHERE {?x h:hasAncestor ?y}
Explanation:
Since hasAncestor is transitive, it propagates from peers to peers. For example, in the first result, we see that
Harry has as ancestor Jack (line 1) and Jack has as ancestor Gaston (line 5). With transitivity, a link will be added
between Harry and Gaston, as Gaston now is declared as an ancestor of Harry, which we can see in the second
result (line 1).
4. Declare the disjunction between Male and Female. Violate the constraint in the data, check the results and then
remove the violation you created.
<Class rdf:ID="Male">
<owl:disjointWith rdf:resource="#Female"/>
…
</Class>
Query:
PREFIX h:<http://www.inria.fr/2007/09/11/humans.rdfs#>
SELECT ?x ?p WHERE { ?x ?p ?y. ?y h:name "Jack"}
A violation is added to the results, which is due to the fact Jack is declared as both male and female whilst male
and female are disjoint classes.
5. Declare that the class Professor is the intersection of the class Lecturer and Researcher class.
<owl:Class rdf:ID="Professor">
<owl:intersectionOf rdf:parseType="Collection">
<owl:Class rdf:about="#Researcher"/>
<owl:Class rdf:about="#Lecturer"/>
</owl:intersectionOf>
</owl:Class>
Query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
SELECT ?x
WHERE {?x a h:Professor}
None
Explanation:
Laura is declared as both a Lecturer and Researcher, and since Professor is the intersection of both, Laura is also
declared as Professor.
6. Declare that the Academic class is the union of classes Lecturer and Researcher.
<owl:Class rdf:ID="Academic">
<owl:unionOf rdf:parseType="Collection">
<owl:Class rdf:about="#Researcher"/>
<owl:Class rdf:about="#Lecturer"/>
</owl:unionOf>
</owl:Class>
Query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
SELECT ?x
WHERE {?x a h:Academic}
None
Explanation:
Each resource of the 4 results belong either to Researcher or Lecturer type, and since Academic is the union of
both, they’re all declared to be Academic as well.
7. Create a class Organization and its sub class University. Create a new property mainEmployer, with
domain Person and range Organization. Use a restriction to declare that any Professor has for main
employer a University.
Code added to the schema (new property, new classes and new restriction):
<Class rdf:ID="Organization">
<subClassOf rdf:resource="#Organization"/>
<label xml:lang="en">organization</label>
<label xml:lang="fr">organisation</label>
</Class>
<Class rdf:ID="University">
<subClassOf rdf:resource="#Organization"/>
<label xml:lang="en">university</label>
<label xml:lang="fr">université</label>
</Class>
<rdf:Property rdf:ID="mainEmployer">
<domain rdf:resource="#Person"/>
<range rdf:resource="#Organization"/>
<label xml:lang="en">has for main employer</label>
<label xml:lang="fr">a pour principal employeur</label>
</rdf:Property>
<owl:Class rdf:ID="Professor">
<subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource="#mainEmployer" />
<owl:allValuesFrom rdf:resource="#University" />
</owl:Restriction>
</subClassOf>
<owl:intersectionOf rdf:parseType="Collection">
<owl:Class rdf:about="#Researcher"/>
<owl:Class rdf:about="#Lecturer"/>
</owl:intersectionOf>
</owl:Class>
Code added to the data (just declare the main employer of a Professor):
<Organization rdf:about="#DSTI"/>
<Researcher rdf:about="#Laura">
<name>Laura</name>
<mainEmployer rdf:resource="#DSTI"/>
</Researcher>
Query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
SELECT ?employer ?type
WHERE { ?x a h:Professor; h:mainEmployer ?employer. OPTIONAL { ?employer a ?type } }
Explanation:
In the first result, Professor Laura is declared to has Organization DSTI as a main employer, so we get DSTI being of
type Organization only. When we added the restriction, all Professor instances have their mainEmployer property
restricted to University. Consequently, Organization DSTI is inferred to be a University in the second result.
8. Use a restriction to declare that any person must have a parent who is a woman. For this last statement, you
need to run the rule engine after loading the ontology and data.
Code added to the data ( Adding an animal that has a Woman parent ):
<Animal rdf:ID="Milo">
<hasParent rdf:resource="#Alice"/>
</Animal>
Query:
PREFIX h: <http://www.inria.fr/2007/09/11/humans.rdfs#>
SELECT ?x ?y
WHERE { ?x h:hasParent ?y. FILTER ( not exists { ?x a h:Person } ) }
Explanation:
Since a Person is restricted to an instance that must have a Woman as a parent, any instance that satisfies this
condition is inferred to become a Person. Which is why the animal Milo, who has the Woman Alice as a parent,
became also a Person instance, and wasn’t shown in the second result.