Full SPARQL training
Covers all SPARQL : basic graph patterns, FILTERs, functions, property paths, optional, negation, assignation, aggregation, subqueries, federated queries.
Does not cover except SPARQL updates.
Includes exercices on DBPedia.
CC BY license
SPARQL introduction and training (130+ slides with exercices)
1. SPARQL
Thomas Francart,
Crédits : This work remixes, translates and complete a presentation from Fabien Gandon, INRIA, under an open licence. Thanks to him.
This work is placed under « Attribution ShareAlike 4.0 International ». You are free to share and adapt this work, even for commercial purposes.
You must give appropriate credit, provide a link to the license, and indicate if changes were made. If you remix, transform, or build upon the
material, you must distribute your contributions under the same license as the original. For more information, see the license.
2. RDF and its triples
is the first level (after URI)
in the standards of the
semantic web
3. SPARQL
is on top of RDF . It is a query
language and query protocol.
It is the SQL for RDF data.
4. SPARQL
• Query data
• Traverse graph from heterogeneous sources
• Consistency checking
• Data analytics
• Data management (copy, move, delete, etc.)
• Convert data from one structure to another
• Make some inferences : find new data/relations from
existing data
• Generate exports (tabular or graph)
• Make federated queries (query multiple databases) …
5. SPARQL limits
• No full-text search indexes (proprietary extensions)
• No geographical indexes (proprietary extensions)
• No query hints to control exécution plan (proprietary
extensions)
• No stored procedures
• No triggers
6. SPARQL standard has 3 parts
Part 1: query language syntax
Part 2: result format specification
Part 3: query protocol
6
13. Example – persons with their names
PREFIX ex: <http://foo.org/ontology#>
SELECT ?person ?name
WHERE {
?person rdf:type ex:Person .
?person ex:name ?name .
}
14. Patterns with 1 variable
# ?x that are Persons
?x rdf:type foaf:Person .
# ?x that Tom knows
ex:Tom foaf:knows ?x .
# ?x that link Tom and Oliver
ex:Tom ?x ex:Oliver .
15. Patterns with 2 variables
# ?x and ?y that know each other
?x foaf:knows ?y .
# All verbs and values about Tom
ex:Tom ?x ?y .
# All subject and verbs that link to Tom
?x ?y ex:Tom .
16. Patterns with 3 variables
… or no variable at all
# Everyting on everything !
# (returns all database)
?x ?y ?z .
# Tom is a Person
ex:Tom rdf:type foaf:Person .
17. Exemple – same query as before
PREFIX ex: <http://foo.org/ontology#>
SELECT ?person ?name
WHERE {
?person a ex:Person ;
ex:name ?name .
}
Avoid confusion and always write full « sentences » :
- Subject verb complement dot
- Subject verb complement dot
- Subject verb complement dot
- …
18. Whitespace between subject / predicate / object
No whitespace in a URI or a variable name
Never put whitespace afer or before the “:” in prefixed URIs.
Never put whitespace after the “?” in variables !
If you want, a whitespace before final “.”
Whitespaces
?aPerson rdf:type foaf:Person .
19. WHERE {
# Don’t use foaf:Person
?person a ex:Person .
}
Comments
20. Methodology
Write your queries step by step and test at each
step :
• Add a first criteria
• Use LIMIT keyword to avoid too long result sets
• Test
• Add a criteria
• Test
• Add a criteria
• Etc.
21. Exercise 1 : a first query with a basic graph
patterns
• Write a query that returns…
• All the companies…
• … with their names
PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
…
• Company = dbo:Company
• Name = rdfs:label
http://dbpedia.org/sparql
22. Exercise 1 : a first query with a basic graph
patterns
PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?x ?label
WHERE {
?x a dbo:Company .
?x rdfs:label ?label .
}
24. Methodology
1. Look at notices of entities to understand their
description
In HTML or in RDF
2. And/or read the model documentation
3. And/or look at sample queries provided
4. And/or do SPARQL exploration queries (see annex)
It is possible to discover the graph data model by issuing specific
SPARQL queries
5. Draw graph sketches
25. Exercise 2 : A basic graph pattern that
traverses the graph
http://dbpedia.org/sparql
• Write a query that returns…
• All the companies with their names…
• … that have been founded by someone …
• … born in a place …
• … that is in the United States
PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX dbr: <http://dbpedia.org/resource/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
• Company = dbo:Company
• Name = rdfs:label
• founded by = dbo:founder
• Born in = dbo:birthPlace
• In country : dbo:country
• United States : dbr:United_States
26. Exercise 2 : A basic graph pattern that
traverses the graph
PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?x ?label
WHERE {
?x a dbo:Company .
?x rdfs:label ?label .
?x dbo:owner ?owner .
?owner dbo:birthPlace ?somewhere .
?somewhere dbo:country dbr:United_States
}
28. Sorting and paging
ORDER BY ?x variable(s) to
order on. Use DESC(?x) to sort from Z-A
LIMIT 100 limit the total size of
result set
OFFSET 10 index of the first result in
total result set
All identical to SQL
29. Exemple – results 21 to 40 sorted by name
PREFIX ex: <http://foo.org/ontology#>
SELECT ?person ?name
WHERE {
?person rdf:type ex:Person .
?person ex:name ?name .
}
ORDER BY ?name
LIMIT 20
OFFSET 20
31. Functions
Functions are applied on variables. They are
used to :
1. FILTER the values of variables we want
FILTER(lang(?x) = "fr")
2. Change the content of a column in the
result set (assignation – see later)
36. Functions on RDF
literals / resources
lang(?x) : language of ?x (« fr »)
str(?x) : string value of ?x (without
language/datatype)
datatype(?x) : datatype of ?x
37. Exercice 3 : Using FILTER
• Keep only the names of the companies in
English
http://dbpedia.org/sparql
38. Exercice 3 : Using FILTER
PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?x ?label
WHERE {
?x a dbo:Company .
?x rdfs:label ?label .
FILTER(lang(?label) = "en")
}
39. SELECT (f(?x) AS ?y)
In the SELECT clause, you can
apply a function on a variable
and assign the result to a new
variable with AS.
This is assignation – more on this later
40. Exercise 4 : Using a function in the SELECT
clause with AS
• We would like to get rid of the « @en » of
the label column in the result set
• Use « str(?label) » in the SELECT clause
to select only the label string without the
language
41. Exercise 4 : Using a function in the SELECT
clause with AS
PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?x (STR(?label) AS ?theLabel)
WHERE {
?x a dbo:Company .
?x rdfs:label ?label .
FILTER(lang(?label) = "en")
}
42. Functions on RDF
literals / resources
isIRI(?x) : true if ?x is an IRI
isLiteral(?x) : true if ?x is a literal
isBlank(?x) : true if ?x is an
anonymous node
43. Functions on strings
UCASE(?x) / LCASE(?x) : ?x in upper-case /
lower case
STRLEN(?x) : length of ?x
STRSTARTS(?x, ?y) STRENDS(?x,
?y) CONTAINS(?x, ?y) : test if ?x starts with
/ ends with / contains ?y
44. STRBEFORE(?x,"foo") /
STRAFTER(?x,"foo") : substring after of
before « foo » in ?x
REPLACE(?x,"http","https") :
replaces « http » with « https » in ?x
Functions on strings
45. If « test » is true, returns
« then », otherwise returns
« else »
IF(<test>,<then>,<else>)
51. Starts with « tom » regex(?x, "^tom", "i")
Ends with « tom » regex(?x, "tom$", "i")
Contains a number regex(?x, "[0-9]")
Contains only a number regex(?x, "^[0-9]$")
Contains date in format JJ/MM/AAAA or
JJ-MM-AAAA (with day or month in or or
two caracters)
regex(?x, "[0-9][0-9]?[/-][0-
9][0-9]?[/-][0-9][0-9][0-9][0-
9]")
Starts with http:// or https:// regex(?x, "^https?://[^s]+$")
…
52. Character Legend Example Sample Match
d
Most engines: one digit
from 0 to 9
file_dd file_25
w
Most engines: "word character": ASCII letter, digit or
underscore
w-www A-b_1
s
Most engines: "whitespace character": space, tab,
newline, carriage return, vertical tab
asbsc
a b
c
D
One character that is not a digit as defined by your
engine's d
DDD ABC
W
One character that is not a word character as defined by
your engine's w
WWWWW *-+=)
S
One character that is not a whitespace character as
defined by your engine's s
SSSS Yoyo
Quantifier Legend Example Sample Match
+ One or more Version w-w+ Version A-b1_1
* Zero or more times A*B*C* AAACC
? Once or none plurals? plural
{3} Exactly three times D{3} ABC
{2,4} Two to four times d{2,4} 156
{3,} Three or more times w{3,} regex_tutorial
53. Character Legend Example Sample Match
. Any character except line break a.c abc
.
Any character except line break, any number
of times
.* whatever, man.
.
A period (special character: needs to be
escaped by a )
a.c a.c
Escapes a special character .*+? $^/ .*+? $^/
Escapes a special character [{()}] [{()}]
Character Legend Example Sample Match
[ … ] One of the characters in the brackets [AEIOU] One uppercase vowel
[ … ] One of the characters in the brackets T[ao]p Tap or Top
- Range indicator [a-z] One lowercase letter
[x-y] One of the characters in the range from x to y [A-Z]+ GREAT
[ … ] One of the characters in the brackets [AB1-5w-z]
One of either:
A,B,1,2,3,4,5,w,x,y,z
[x-y] One of the characters in the range from x to y [ -~]+
Characters in the printable
section of the ASCII table.
[^x] One character that is not x [^a-z]{3} A1!
[^x-y]
One of the characters not in the range from x
to y
[^ -~]+
Characters that are not in the
printable section of the ASCII
table.
55. OPTIONAL
Make one or more query
patterns optional
Even if they don’t match, results will still
be returned.
Very useful to build result sets when we
are not 100% all properties exist
56. Exemple – return age if it is know in the graph
PREFIX ex: <http://foo.org/ontology#>
SELECT ?person ?name ?age
WHERE {
?person rdf:type ex:Person .
?person ex:name ?name .
OPTIONAL { ?person ex:age ?age }
}
57. Exercise 5 : Making some patterns optional
• Write a query that returns…
• All the companies…
• … with their names
• … and their slogan if they have one !
• Company = dbo:Company
• Name = rdfs:label
• Slogan : dbo:slogan
58. Exercise 5 : Making some patterns optional
PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?x ?label ?slogan
WHERE {
?x a dbo:Company .
?x rdfs:label ?label .
FILTER(lang(?label) = "en")
OPTIONAL { ?x dbo:slogan ?slogan }
}
59. NOT EXISTS / MINUS
Make some query patterns
negative.
“I am looking for resources that don’t have …”
“I am looking for all resources that have this
minus those that have that”
60. Exemple – persons who don’t know Tom (FILTER
NOT EXISTS)
PREFIX ex: <http://foo.org/ontology#>
SELECT ?person
WHERE {
?person rdf:type ex:Person .
FILTER NOT EXISTS {
?person ex:knows ex:Tom .
}
}
61. Exemple – persons except those that know Tom
(MINUS)
PREFIX ex: <http://foo.org/ontology#>
SELECT ?person
WHERE {
?person rdf:type ex:Person .
MINUS {
?person ex:knows ex:Tom .
}
}
62. NOT EXISTS / MINUS
There are subtle differences
between FILTER NOT EXISTS
and MINUS
63. SELECT * WHERE {
?s ?p ?o
FILTER NOT EXISTS
{ ?x ?y ?z }
}
0 results
PREFIX ex: <http://ex.fr/>
SELECT * WHERE {
?s ?p ?o
FILTER NOT EXISTS
{ ex:A ex:B ex:C }
}
0 results
SELECT * WHERE {
?s ?p ?o
MINUS
{ ?x ?y ?z }
}
All results
PREFIX ex: <http://ex.fr/>
SELECT * WHERE {
?s ?p ?o
MINUS
{ ex:A ex:B ex:C }
}
All results
64. Exercise 6 : Making some patterns negative
• Write a query that returns…
• All the companies…
• … with their names
• … for those that do NOT have a slogan
• Company = dbo:Company
• Name = rdfs:label
• Slogan : dbo:slogan
65. Exercise 6 : Making some patterns negative
PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?x ?label
WHERE {
?x a dbo:Company .
?x rdfs:label ?label .
FILTER(lang(?label) = "en")
FILTER NOT EXISTS { ?x dbo:slogan ?slogan }
}
70. Exemple – Persons who are friends of a friends of
Tom
PREFIX ex: <http://foo.org/ontology#>
SELECT ?person
WHERE {
?person rdf:type ex:Person ;
ex:knows/ex:knows ex:Tom .
}
?x Ex:Tom
ex:knows ex:knows
71. ex:knows/ex:livesIn
ex:knows followed by ex:livesIn
ex:knows|ex:marriedWith
ex:knows or ex:marriedWith
!ex:knows
any property except ex:knows
ex:Tom ^ex:knows ?x :
ex:knows from ?x to ex:Tom
(to be combined with “/” paths)
72. ex:Tom ex:knows+ ?x
All ?x that Tom knows, and friends of friends of
friends… recursively, including ex:Tom
ex:Tom ex:knows* ?x
All ?x that Tom knows, and friends of friends of
friends… recursively, not including ex:Tom
ex:Tom ex:knows? ?x
Tom and any person he knows
(...)
Combine operators
73. Exemple Query ancestors of Tom
?ancestor (ex:motherOf|ex:fatherOf)+ ex:Tom
?c1 skos:broader|^skos:narrower ?c2
Exemple Querying inverse links
Exemple Querying RDF lists
?c1 rdf:rest*/rdf:first ?c2
74. Exercise 7 : Using property paths to traverse /
navigate the graph
http://dbpedia.org/sparql
• Write a query that returns…
• All the companies with their names…
• … that have been founded by someone …
• … born in a place …
• … that is in the United States
• Use a property path
75. Exercise 7 : Using property paths to traverse /
navigate the graph
PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?x ?label
WHERE {
?x a dbo:Company .
?x rdfs:label ?label .
?x dbo:owner/dbo:birthPlace/dbo:country dbr:United_States
}
77. Assignation allows to set the
value of a variable with :
• result of a computation
• result of a function
• result of an aggregation function (GROUP BY)
• a (list of) value(s) known in advance
78. Exemple – Compute “body mass index”
PREFIX ex: <http://foo.org/ontology#>
SELECT ?person ((?w/(?h*?h)) AS ?BMI)
WHERE {
?person a ex:Person ;
ex:height ?h .
ex:weight ?w .
}
79. Assignation can be done in
SELECT or in WHERE by using
the BIND operator to reuse the
value elsewhere
80. Exemple – Persons with low BMI
PREFIX ex: <http://foo.org/ontology#>
SELECT ?person ?BMC
WHERE {
?person rdf:type ex:Person .
?person ex:weight ?w .
?person ex:height ?h .
BIND((?w/(?h*?h)) AS ?BMC)
FILTER (?BMC < 25)
}
82. Exemple – Number of Persons with low BMI
PREFIX ex: <http://foo.org/ontology#>
SELECT (COUNT(?person) as ?count)
WHERE {
?person rdf:type ex:Person ;
ex:weight ?w ;
ex:height ?h .
FILTER ((?w/(?h*?h)) < 25)
}
83. Exemple – Number of Persons with low BMI per
country
PREFIX ex: <http://foo.org/ontology#>
SELECT ?country (COUNT(?person) as ?count)
WHERE {
?person rdf:type ex:Person ;
ex:weight ?w ;
ex:height ?h .
?person ex:livesIn ?country .
FILTER ((?w/(?h*?h)) > 25)
} GROUP BY ?country
85. Exemple – Concatenate all names of friends of
Tom in a single string
PREFIX ex: <http://foo.org/ontology#>
SELECT (GROUP_CONCAT(?nameOfFriend; separator=“,”) AS
?allNamesOfFriends)
WHERE {
ex:Tom ex:knows/ex:name ?nameOfFriend .
}
86. HAVING keyword enables to
set a criteria on a group of the
GROUP BY clause, using
aggregates
Rarely used in practice
87. Exemple – Number of persons with low BMC per
country, for country with average BMC < 20
PREFIX ex: <http://foo.org/ontology#>
SELECT ?country (COUNT(?person) as ?count)
WHERE {
?person a ex:Person ; ex:weight ?w ;
ex:height ?h ; ex:livesIn ?country .
BIND ((?w/(?h*?h)) AS ?IMC)
FILTER(?IMC > 25)
} GROUP BY ?country
HAVING (AVG(?IMC) > 20)
88. VALUES is a very useful
keyword to directly assign the
values of certain variables. It
enable to pass list of values in
the query
89. Exemple – Read 3 known person names
PREFIX ex: <http://foo.org/ontology#>
SELECT ?person ?name
WHERE {
?person rdf:type ex:Person .
?person ex:name ?name .
VALUES ?person {
ex:Tom ex:Oliver ex:Mark
}
}
90. VALUES and FILTER(…
IN(…)) are NOT equivalents
« FILTER IN » is applied after pattern
matching, VALUES is applied during
it.
VALUES is more performant
than « FILTER IN ».
92. Nested queries are
SELECT subqueries
inside the WHERE
clause.
Use-case 1 : limit / sort / aggregate a subset
Use-case 2 : control the order of exécution of the
query
93. Exemple – Read top ten most used keywords,
then read their labels
SELECT ?cpt ?label
WHERE {
{
SELECT DISTINCT ?cpt
WHERE {
?doc dcterms:subject ?cpt .
}
ORDER BY DESC(COUNT(?cpt) as ?c)
LIMIT 10
}
?cpt skos:prefLabel ?label
}
94. Nested queries are
always executed before
the rest of the clauses.
This enables to control the execution
order of the query
95. It is possible to combine the
results of multiple SPARQL
services with the SERVICE
keyword. This is federated
querying.
96. Exemple – Read country names from DBPedia, then select
the concepts from a thesaurus having the same label
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
PREFIX rdfs:<http://www.w3.org/2000/01/rdf-
schema#>
SELECT ?concept
WHERE {
?concept skos:prefLabel ?countryName .
SERVICE <http://dbpedia.org/sparql> {
?country rdfs:label ?countryName .
?country a <http://dbpedia.org/ontology/Country>
}
}
97. Be careful of the joins when querying an
remote database. Do not write :
SELECT ?person ?countryName
WHERE {
?person rdf:type ex:Person ;
?person ex:livesIn ?country .
SERVICE <http://dbpedia.org/sparql> {
?country rdfs:label ?countryName
}}
98. Use sub-queries to garantee the order of
exécution of the queries. Write instead :
SELECT ?country ?countryName
WHERE {
{
SELECT DISTINCT ?country WHERE {
?person rdf:type ex:Person ;
?person ex:livesIn ?country .
}
}
SERVICE <http://dbpedia.org/sparql> {
?country rdfs:label ?countryName
}}
100. GRAPH
Allows patterns to be searched in
a subset of the complete data. A
graph is identified by a URI.
By default, without GRAPH, patterns are
searched in all graphs.
101. Exemple – keywords used in “production data”
PREFIX …
SELECT ?document ?tag ?label
WHERE {
GRAPH ex:baseProd {
?document dcterms:subject ?tag
}
?tag skos:prefLabel ?label
}
102. Exemple – return all graphs
PREFIX …
SELECT DISTINCT ?g
WHERE {
GRAPH ?g {
?s ?p ?o
}
}
105. Exemple – keywords from “test data” and
“production data”
PREFIX …
SELECT DISTINCT ?tag
FROM ex:baseProd
FROM ex:baseTest
WHERE {
?document dcterms:subject ?tag
}
107. Exemple – keywords from “test data” and
“production data” with their source
PREFIX …
SELECT ?doc ?tag ?g
FROM NAMED ex:baseProd
FROM NAMED ex:baseTest
WHERE
{
GRAPH ?g {
?doc dcterms:subject ?tag
}
}
108. Other forms of SPARQL
queries
CONSTRUCT / ASK / DESCRIBE
110. Exemple – return adults for persons over 18
PREFIX ex: <http://foo.org/ontology#>
CONSTRUCT
{
?person rdf:type ex:Adult
}
WHERE
{
?person ex:age ?age
FILTER (?age > 18)
}
111. Exemple – extract triples of age of persons
PREFIX ex: <http://foo.org/ontology#>
CONSTRUCT
{
?person ex:age ?age
}
WHERE
{
?person ex:age ?age
}
112. ASK
Test the existence of a
condition and simply
returns « true » / « false »
For consistency checking – but not much
used in practive. Use a SELECT most of
the time
113. Exemple – Are there any person over 18 ?
PREFIX ex: <http://foo.org/ontology#>
ASK
{
?person ex:age ?age
FILTER (?age > 18)
}
114. DESCRIBE
Give the « description »
(set of triples) of a
resource.
Typically, triples that have the URI(s) as
subject, + the labels of the object resources
124. One can forge IRIs and literals
and assign them :
IRI(string) : Builds an IRI from a string
ENCODE_FOR_URI(string) : escape a string to put in an
IRI
STR(literal) : string value of a literal or IRI as a
string
STRLANG and STRDT : build literals with value +
language or value + datatype
125. Exemple – Generate URIs from labels
PREFIX ex: <http://foo.org/ontology#>
SELECT ?newIRI
WHERE {
?person a ex:Person .
?person ex:name ?name .
BIND(
IRI(CONCAT(
“http://sparna.fr/”,
ENCODE_FOR_URI(?name)
))
AS ?newIRI)
}
126. One can cast values from one
type to another using Xpath
constructors
xsd:boolean(?x), xsd:double(?x),
xsd:float(?x), xsd:decimal(?x),
xsd:integer(?x), xsd:dateTime(?x),
xsd:string(?x)
127. Exemple – Add one to a literal string value
PREFIX ex: <http://foo.org/ontology#>
SELECT
(
(xsd:integer(?age) + 1) AS
?ageAnneeProchaine
)
WHERE {
?person a ex:Person .
?person ex:age ?age .
}
129. SPARQL Protocol
Standardizes the way to
issue queries to a
triplestore
Unlike SQL. Consequence : you can
switch database implementation
transparently
130. Exemple – HTTP query following SPARQL
protocol
GET /sparql/?query=<encoded query> HTTP/1.1
Host: dbpedia.org
User-agent: my-sparql-client/0.1
131. The result format in XML
<?xml version="1.0"?>
<sparql xmlns="http://www.w3.org/2005/sparql-results#" >
<head>
<variable name="person"/>
<variable name="name"/>
</head>
<results ordered="false" distinct="false">
<result>
<binding name="person">
<uri>http://inria.fr/schema#fg</uri>
</binding>
<binding name="name">
<literal>gandon</literal>
</binding>
</result>
<result> ...
132. The result format in JSON
{
"head": { "vars": [ "book" , "title" ]
} ,
"results": {
"bindings": [
{
"book": { "type": "uri" , "value": "http://example.org/book/book6" } ,
"title": { "type": "literal" , "value": "Harry Potter and the Half-Blood Prince" }
} ,
{
"book": { "type": "uri" , "value": "http://example.org/book/book7" } ,
"title": { "type": "literal" , "value": "Harry Potter and the Deathly Hallows" }
} ,
{
"book": { "type": "uri" , "value": "http://example.org/book/book5" } ,
"title": { "type": "literal" , "value": "Harry Potter and the Order of the Phoenix" }
} ,
{
"book": { "type": "uri" , "value": "http://example.org/book/book4" } ,
"title": { "type": "literal" , "value": "Harry Potter and the Goblet of Fire" }
}
]
}
}
133. We neverdirectly see this
structure. It is always interpreted for us
by RDF/SPARQL libraries.