pOTTR: Reasonable Ontology Templates Fundamentals
Table of Contents
Reasonable Ontology Templates Fundamentals

Learn the basics of OTTR
- Authors
- Martin G. Skjæveland, Leif Harald Karlsen, Daniel Lupp
- Issues
- https://gitlab.com/ottr/language/pOTTR/issues
1 Introductionπ
This primer is a lightweight introduction to the basic concepts of OTTR templates. The fundamentals of OTTR are formally defined in mOTTR [1].
The primer presents the necessary concepts for understanding, using and creating OTTR templates for engineering ontologies and knowledge bases. This includes:
- Templates, signatures and base templates and template instances
- Expansion of template instances
- Types and non-blank parameters
- Optional and default parameters
- List arguments and expansion modes
- Template libraries
The primer assumes a basic understanding of the semantic web technologies RDF and OWL.
1.1 Syntaxπ
The OTTR syntax used in this primer is called stOTTR [3]. stOTTR is designed to be a compact and easy to read and write OTTR templates and instances. stOTTR builds on a subset of the RDF Turtle syntax, so prefixes, IRIs, blank nodes, literals and RDF lists are written just as in RDF Turtle syntax. As for RDF Turtle whitespace characters in stOTTR are not significant, i.e., spaces, tab and linebreaks can be added between language tokens without changing the content.
There are other serialisations formats for OTTR templates and instances. Information about them may be found via http://ottr.xyz.
1.2 Toolsπ
Lutra is our open source reference implementation of OTTR. It is available as a standalone Java command line interface and as a feature limited web application called WebLutra.
Lutra is used in the examples of this primer, using version
0.6.6-SNAPSHOT
. The interactive examples in this
primer uses WebLutra. The project is in active development, so the
version used when generating this document may be different from
the latest release of Lutra and of WebLutra.
More information about Lutra and WebLutra, including source code and licence, can be found via http://ottr.xyz.
1.3 Prefixesπ
The following prefixes are used throughout the document. You may also use these prefixes in the interactive examples/exercises without declaration. If you need to declare more prefixes this can be done in the input form using RDF Turtle syntax.
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . @prefix owl: <http://www.w3.org/2002/07/owl#> . @prefix xsd: <http://www.w3.org/2001/XMLSchema#> . @prefix foaf: <http://xmlns.com/foaf/0.1/> . @prefix dbp: <http://dbpedia.org/ontology/> . @prefix ex: <http://example.com/ns#> . @prefix ottr: <http://ns.ottr.xyz/0.4/> . @prefix ax: <http://tpl.ottr.xyz/owl/axiom/0.1/> . @prefix rstr: <http://tpl.ottr.xyz/owl/restriction/0.1/> .
1.4 Document setupπ
This is an example.
This is an interactive example/exercise.
2 Templates and Instancesπ
In this section we cover the most basic concepts of OTTR: template instances, template signatures, templates, base templates and the process of expanding template instances.
2.1 Template instanceπ
A template instance, or just instance, consists of a reference to a template and a list of arguments.
All argument values must be RDF resources, i.e., IRIs, literals, or blank nodes. An argument can also be an RDF list whose list elements may also be RDF lists of arbitrary nesting depth.
In stOTTR, instances are written by first stating the template IRI, followed by the list of arguments enclosed in parenthesis and separated by commas. An instance is terminated by a dot.
Instance
Below are two instances of the template ex:Person
, which will be
introduced further down. The first instance has the three arguments
"Ann"
, "Strong"
and <mailto:ann.strong@example.com>
. These
arguments are regular RDF resources.
ex:Person("Ann", "Strong", <mailto:ann.strong@example.com>) . ex:Person("Bob", "Brite", <mailto:bob.brite@example.com>) .
The instance arguments must match the number and type of the parameters specified by the template signature.
2.2 Templates and template signaturesπ
A template consists of a signature and a pattern.
A signature consists of a template IRI and a list of parameter declarations. The different aspects of parameter declarations will be covered later in this primer.
Intuitively, the signature specifies the interface of a template, i.e., the name of which to identify the template and what input the template expects. This is similar to method signatures in many programming languages.
It is possible to only state the signature of a template, and not the full template. This can be convenient when the full template is not (yet) available. Users can then, without knowing the full template, still make instances of the template by following the input specification set by the signature.
In stOTTR, a template signature is written by first stating the IRI of
the template, followed by the list of parameter declarations enclosed
in brackets ([...]
) and separated by commas. When a signature given
not as part of a template, it is terminated by a dot.
Signature
This is the signature of the ex:Person
template. It specifies three
parameters, ?firstName
, ?lastName
and ?email
. Notice that the
instances in the previous example match this signature.
ex:Person[ ?firstName, ?lastName, ?email ] .
In addition to a signature, a template requires a pattern. The pattern of a template contains (other) instances and may use the template's parameters as arguments.
Intuitively, the template pattern expresses a modelling pattern or how the input parameters are related in terms of other templates.
In stOTTR, pattern instances are enclosed in curly braces ({...}
)
and separated by commas. The signature and pattern are separated by
two colons (::
), and a template is terminated by a dot.
Few templates are "native" to OTTR and are
defined in the formal specifications that underlies the OTTR
framework. The ottr:Triple
is one such template; it is used for representing regular
RDF triples.
Template
This is the ex:Person
template. The template pattern contains three
instances of the ottr:Triple
template in its pattern, and uses the
predicates rdf:type
, foaf:firstName
, foaf:lastName
and
foaf:mbox
to model a person. Notice the use of a named blank node
for "connecting" or "joining" the instances in the pattern.
ex:Person[ ?firstName, ?lastName, ?email ] :: { ottr:Triple(_:person, rdf:type, foaf:Person ), ottr:Triple(_:person, foaf:firstName, ?firstName ), ottr:Triple(_:person, foaf:lastName, ?lastName ), ottr:Triple(_:person, foaf:mbox, ?email ) } .
2.3 Base templatesπ
A base template is a template with no pattern.
A base template is necessary when the pattern cannot be represented
by means of instances of templates. This is typically the case for patterns that
represent basic structures in another formalism. The ottr:Triple
template introduced above is in fact a base template. Instances of
base templates must therefore be interpreted or specified in other
ways, typically by the implementation that handles the OTTR
templates.
In stOTTR, a base template is written by letting the keyword
BASE
follow the template signature.
Base template
This is a base template:
ex:MyBaseTemplate[?s, ?p, ?o] :: BASE .
User-defined base templates are possible, however, there is not yet any
way of specifying how instances of user-defined base templates are
handled, such as ottr:Triple
instances are translated to RDF triples.
Currently, an instance of a user defined base template will simply
be "left as is" and can/must be handled by other means/tools.
One could imagine having Quad
as a base template, for expressing
quads,
cf. https://www.w3.org/TR/rdf11-concepts/#section-dataset. However, the base templates currently supported by OTTR only result in RDF triples.
2.4 Expansionπ
Observe that OTTR templates are a recursive data structure: a template is defined from other templates. It is "templates all the way down", where base templates form the "bottom".
Expansion is the process of translating or rewriting a template instance to a copy of its pattern. A template instance can be seen to represent a "replica" or a "clone" of the pattern of the template it is an instance of where the template's parameters have been replaced by the arguments of the instance. If the pattern contains a blank node, then new fresh blank nodes will be created for each of the clones of the pattern.
An instance is expanded by recursively replacing instances with the pattern they represent. The process of expanding instances terminates when all instances are instances of base templates. In other words, fully expanding a template instance really means to translate the template instance to the language which underlies the base templates the instance is expanded to.
In the current specification and implementation, all base templates represent RDF triples. Therefore all expansions will terminate as a set of instances that represents a set of RDF triples, i.e, an RDF graph.
Expansion
The result of expanding the two example instances of the ex:Person
given above to stOTTR syntax is given below. We see that each
ex:Person
instance has been expanded to a copy of the pattern of the
ex:Person
template, where, in the case of the first instance, the
parameters ?firstName
, ?lastName
and ?email
have been replaced
by arguments "Ann"
, "Strong"
and <mailto:ann.strong@example.com>
respectively.
Notice that a fresh blank node in the pattern is minted for each of the instances.
@prefix dbp: <http://dbpedia.org/ontology/> . @prefix ex: <http://example.com/ns#> . @prefix ottr: <http://ns.ottr.xyz/0.4/> . @prefix ax: <http://tpl.ottr.xyz/owl/axiom/0.1/> . @prefix rstr: <http://tpl.ottr.xyz/owl/restriction/0.1/> . @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 owl: <http://www.w3.org/2002/07/owl#> . @prefix foaf: <http://xmlns.com/foaf/0.1/> . ottr:Triple(_:blank2, foaf:firstName, "Ann") . ottr:Triple(_:blank2, foaf:lastName, "Strong") . ottr:Triple(_:blank2, foaf:mbox, <mailto:ann.strong@example.com>) . ottr:Triple(_:blank2, rdf:type, foaf:Person) . ottr:Triple(_:blank3, foaf:firstName, "Bob") . ottr:Triple(_:blank3, foaf:lastName, "Brite") . ottr:Triple(_:blank3, foaf:mbox, <mailto:bob.brite@example.com>) . ottr:Triple(_:blank3, rdf:type, foaf:Person) .
This is result of expanding the two example instances to RDF triples:
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . @prefix foaf: <http://xmlns.com/foaf/0.1/> . [ a foaf:Person ; foaf:firstName "Ann" ; foaf:lastName "Strong" ; foaf:mbox <mailto:ann.strong@example.com> ] . [ a foaf:Person ; foaf:firstName "Bob" ; foaf:lastName "Brite" ; foaf:mbox <mailto:bob.brite@example.com> ] .
Getting familiar with the interactive exercise form
This primer contains interactive examples/exercises where you can test and run your solution directly. Usually each interactive examples contains one input box for template instances, and one box for templates. When clicking the "Run" button at the bottom, the instances in the instance box are expanded using the templates in the template box, and templates from standard library at http://tpl.ottr.xyz if this setting is set to true. The process is run by WebLutra.
It is possible to change the input and output formats and the action. If you want RDF as output, set "wottr" as output format.
To get familiar with this setup, try the following:
- Click the "Run" button to expand the given instances.
- Add a few more instances of the
ex:Person
template in the instance-box and click "Run" to expand them. - Make changes in the pattern of the
ex:Person
template, e.g., changefoaf:lastName
tofoaf:surname
, click "Run" and see the effects of the expansion. - Extend the signature with an additional parameter, e.g.,
?age
, and extend the pattern accordingly. - Change the output format to stOTTR and click "Run".
Create a new template
Create a template ex:Organization
such that the instance below
expands to the following RDF graph:
Note that #
can be used to add comments in stOTTR.
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . @prefix foaf: <http://xmlns.com/foaf/0.1/> . [ a foaf:Organization ; foaf:age 208 ; foaf:homepage <http://uio.no> ; foaf:name "University of Oslo" ] .
Solutionπ
3 Nesting templatesπ
The templates we have seen so far in this primer only contain
instances of the ottr:Triple
template in their pattern. However,
the pattern of a template may contain instances of any templateβas
long as there are no cyclic dependency between templates: a template
cannot depend (directly or indirectly) on itself; this will result
in an error.
The ability to compose templates from existing templates is a powerful feature of OTTR templates which allows templates to hide the complexity of modelling patterns at different levels of abstraction. The user of a template need only to understand what input the template expects and what the output will be, and not the details of how it is modelled. This is similar to how programming APIs work; users of an API do not need to understand how specific API calls are implemented, only how to use the API correctly. This is usually achieved by reading the API's documentation. A documentation system for OTTR templates is under construction.
Nested template
The ex:Pizza
template pattern contains instances of
ex:SubClass
and the ottr:Triple
template.
(The templates in the example are typed to avoid a type error. We will learn what types are later in the primer.)
The ex:SubClass
template models the rdfs:subclassOf
relationship
between two classes. The ex:SubClass
template now "hides" the
complexity of this relationship (which we for the sake of the
argument could imagine being more complex than it is), such that the
user of the template does not need to care about how this is
modelled, only that correctly instantiating the template will give
the correct results, i.e., that providing two classes as argument to this template
will create a subclass relationship between them.
Nested template
Rewrite the ex:Person
template to use the ex:PersonName
template
given in the form below. The instances should expand to the same
RDF result as before.
Template dependency error
The templates below are ill-defined; why?
If you need help, read the error message you get when you expand the given instance.
Solutionπ
Refactoring templates
Below is the definition of the template ex:Type
.
(The parameters of ex:Type
are typed. We will learn what types are
later in the primer.)
Change the ex:Organization
from the previous exercise to use this
template instead of the ottr:Triple
instances which use
rdf:type
as argument.
To see what the ex:Type
template expands to, we have provided
some example instances below.
Solutionπ
4 Template librariesπ
A library of "official" OTTR templates is available at http://tpl.ottr.xyz.
This library contains many templates that model common patterns for the W3C standards OWL, RDFS and RDF, particularly for expressing OWL axioms. The library also includes templates that are useful for understanding how OTTR templates may be built and used.
Our intention is that this library will grow to contain OTTR templates for many useful patterns and for many prominent vocabularies.
The library is currently only published as a set of files in RDF format and is therefore a bit hard to read. A documentation system for OTTR templates and a set of guidelines for managing the library is under development.
Using the standard library
The template http://tpl.ottr.xyz/rdf/0.1/Type is identical to the
ex:Type
introduced above. Update the ex:Organization
template to
use this template instead. Since templates from the standard library are loaded if the
"Load tpl.ottr.xyz" setting is set to true, there is no need to input the template
in the "Libray" text box.
Remember that if you use full IRIs, they must be enclosed in angle
brackets, e.g., <http://tpl.ottr.xyz/rdf/0.1/Type>
.
Using the standard library
The template http://tpl.ottr.xyz/owl/axiom/0.1/SubClassOf is identical
to the ex:SubClass
template introduced above. Update the ex:Pizza
template to use this and the http://tpl.ottr.xyz/rdf/0.1/Type
template.
Using the standard library
The signature of the template http://tpl.ottr.xyz/owl/axiom/0.1/SubObjectSomeValuesFrom is
SubObjectSomeValuesFrom [ owl:Class ?C, owl:ObjectProperty ?P, owl:Class ?D ]
and it models the existential class restriction axiom \(C \sqsubseteq \exists P . D\).
Create the following axiom using template instances:
ex:Pizza
\(\sqsubseteq\) \(\exists\) ex:hasTopping
. Topping
5 Parameter types and non-blank flagsπ
Each template parameter has a type. The permissible parameter
types are IRIs from the RDF, RDFS, OWL and XSD vocabularies and
specifications, such as owl:Class
, rdfs:Resource
and
xsd:integer
. We have also introduced some types that do not exist
in these standards, such as ottr:IRI
. The type system also
allows for lists. The mOTTR [1] and rOTTR [2] specifications
contain more information on the type system.
The default type which is used in case no parameter type is
specified is the most general one, rdfs:Resource
.
In stOTTR, parameter types are specified by giving the type before the parameter variable.
Parameter types
The example shows the previously seen ex:Person
signature, now
including reasonable parameter types.
ex:Person[ xsd:string ?firstName, xsd:string ?lastName, ottr:IRI ?email ] .
5.1 Type compatibilityπ
The parameter type specifies the permissible type or datatype the
corresponding argument may have: the argument type must be
compatible [1] with the parameter type. In essence, this
means that a parameter with the type X
requires that the type of
the argument must be X
or a subtype of X
. For example, if a
parameter has the type xsd:integer
, then arguments to this
parameter must also be of type xsd:integer
or a more restricted
type than xsd:integer
, e.g., xsd:nonNegativeInteger
.
Type error
Some of the instances give a type error. Can you identify the errors and fix them?
5.2 Type consistencyπ
In addition to checking if argument types match the corresponding parameter type, we can also check that arguments are consistently typed: an argument cannot be forced to have multiple incompatible types. This happens if one argument is given to two (or more) parameters which have incompatible types. This case is relevant for arguments where the argument type cannot be determined by the argument value alone and must be determined by how the argument is used.
The typical example is an IRI where is it not possible to know just
from the IRI if it for instance identifies a owl:Class
or an
owl:ObjectProperty
. (An example where the type is clear from the
value only is the literal "34"^^xsd:int
. Here the argument type is
equal to the literal datatype xsd:int
.)
Type inconsistency
The types owl:ObjectProperty
and owl:DatatypeProperty
are
incompatible (This is because the OWL specification defines all
property types as disjoint.)
Assume we have the two templates with these signatures:
ex:A[ owl:ObjectProperty ?x ] . ex:B[ owl:DatatypeProperty ?x ] .
Then adding the following template will force a type inconsistency as any
argument to the template ex:C
will be forced to have both the types
owl:ObjectProperty
and owl:DatatypeProperty
.
ex:C[ ?x ] :: { ex:A(?x), ex:B(?x) } .
5.3 NonBlank parametersπ
A parameter declaration can also specify a parameter to be nonblank. This means it will not accept a blank node as argument.
In stOTTR, a parameter is declared as nonblank by adding !
before
the parameter type. We call this a nonblank flag.
NonBlanks
As per the RDF specification, the predicate of an RDF triple cannot
be a blank node. Hence, the complete definition of the
ottr:Triple
is the following. Notice how types are used and
where the nonblank flag is.
ottr:Triple [ ottr:IRI ?subject, ! ottr:IRI ?predicate, rdfs:Resource ?object ] :: BASE .
A parameter which is used as an argument in its template pattern to a parameter marked as non-blank must also be marked as non-blank.
The single parameter of the base template ex:A
is nonblank.
ex:A[ ! ?x ] :: BASE .
The effect of this is that any parameter which is used as arguments to
an instance of the ex:A
template must also be marked as nonblank.
ex:B[ ! ?x ] :: { ex:A(x) } . ## correct, the parameter has a non-blank flag ex:C[ ?x ] :: { ex:A(x) } . ## incorrect, missing non-blank flag
Nonblank parameters need not only be used to ensure correct RDF triples, but can also disallow the use of blank nodes for IRI or literal parameters.
For the ex:Person
template one could for instance set a nonblank
flag on the ?lastName
parameter to force instances to have a
concrete literal as argument.
ex:Person[ xsd:string ?firstName, ! xsd:string ?lastName, ottr:IRI ?email ] .
Non-blank error
Some of the instances give a non-blank error. Can you identify the errors and fix them?
6 None values and optionals parametersπ
The specific IRI ottr:none
is in the OTTR framework used to
represent a missing or no value, somewhat similar to NULL
values
in relational databases or undefined/null values in programming
languages. In stOTTR, the IRI ottr:none
can be written as just
none
.
A parameter can be specified as optional. Whether or not a
parameter is declared as optional or not has consequences for how
none
arguments are treated during expansion. There are two cases
to consider:
- If
none
is used as argument to a parameter which is optional, then the instance is expanded as for any other value. - If
none
is used as argument to a parameter which is not optional, then the instance is removed in the expansion.
In stOTTR, a parameter is specified as optional by adding ?
before
its type. We call this the optional flag.
Note that all parameters of the ottr:Triple
base template are
non-optional. This means that instances of this template will never result in
RDF triples that contain a none value.
Expanding none values 1
Observe which of the following ottr:Triple
instances expand to RDF.
Expanding none values 2
In the ex:Person
template below ?firstName
is optional, while
?lastName
is not. Observe how this affects the expansion of the
given instances.
In the case of the instance ex:Person("David", none)
, since
?lastName
is not optional, this instance is simply removed when it
is expanded and the result of expanding this instance is an empty set
of triples.
In the case of the instance ex:Person(none, "Erikson")
, since
?firstName
is optional, the none
value is "passed on" to the
instance in the pattern of the template. Hence the result after one
step in the expansion is:
ottr:Triple (_:person, foaf:firstName, none ) . ottr:Triple (_:person, foaf:lastName, "Erikson" ) .
Now, since all parameters of the ottr:Triple
template are
non-optional the first of these instances are removed and only the
last remains. Hence the result of expanding this instance is the
single RDF triple [] foaf:lastName "Erikson"
.
In the case of the instance ex:Person("Ann", "Strong")
there are no
none values in play and the instance expands to the RDF triples
[] foaf:firstName "Ann" ; foaf:lastName "Strong" .
Exercise: What happens with the expansion if you make ?firstName
non-optional?
As noted earlier, all parameters of the ottr:Triple
template are
non-optional. If you need to produce RDF triples that contain the
value none
, there is a different base template, ottr:NullableTriple
,
where all parameters are declared as optional:
ottr:NullableTriple[? ottr:IRI ?subject, !? ottr:IRI ?predicate, ? rdfs:Resource ?object ] :: BASE .
Triple vs. NullableTriple
Observe the difference of expanding instances of ottr:Triple
and
ottr:NullableTriple
by changing the pattern of ex:TripleWrapper
from using ottr:Triple
to using ottr:NullableTriple
.
The signature of ex:TripleWrapper
contains many of the features
available for parameter declarations. Try and see if you understand
it all.
Solutionπ
7 Default valuesπ
Parameters can specify a default value. The default value is used
whenever the argument value is none
. The default value can be any legal argument value. If the
default value is set to a blank node, then a fresh blank node will be created for
each instance.
In stOTTR, a default value is specified by appending the value to the parameter
variable separated by =
, i.e., ?variable=default
.
Default value
This version of the ex:Relative
template has a default value set
for the ?relation
parameter. It defaults to ex:hasRelative
in the
case that no relation is provided.
Setting a default value for OWL axiom
The template
ax:SubObjectSomeValuesFrom[owl:Class ?class, owl:ObjectProperty ?property, owl:Class ?qualifier ] .
can be used to create OWL axioms of the form \(C \sqsubseteq \exists P . D\)
How would you need to change the signature so that the instance
ax:SubObjectSomeValuesFrom(ex:A, ex:Q, none) .
would produce \(A \sqsubseteq \exists Q . \top\)
Solutionπ
Setting concrete default values
Change the template ex:Organization
to include an extra argument
?loc
which states that the organisation is dbp:locatedIn ?loc
and set the default value to ex:norway
. The instances given in
the form should expand to the following:
@prefix dbp: <http://dbpedia.org/ontology/> . @prefix ex: <http://example.com/ns#> . @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . @prefix foaf: <http://xmlns.com/foaf/0.1/> . ex:uio a foaf:Organization ; dbp:locatedIn ex:norway ; foaf:age 208 ; foaf:homepage <http://uio.no> ; foaf:name "University of Oslo" . ex:google a foaf:Organization ; dbp:locatedIn ex:usa ; foaf:age 21 ; foaf:homepage <http://google.com> ; foaf:name "Google" .
Solutionπ
Setting blank node default values
Change the template ex:Person
so that it generates
a fresh blank node if no IRI is provided for the person.
The instances given in the form should expand to the following:
@prefix ex: <http://example.com/ns#> . @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . @prefix foaf: <http://xmlns.com/foaf/0.1/> . [ a foaf:Person ; foaf:firstName "Ann" ; foaf:lastName "Jones" ; foaf:mbox <mailto:ann@example.com> ] . ex:cindy a foaf:Person ; foaf:firstName "Cindy" ; foaf:lastName "Stevens" ; foaf:mbox <mailto:cindy@example.com> . [ a foaf:Person ; foaf:firstName "Bill" ; foaf:lastName "Bright" ; foaf:mbox <mailto:bill@example.com> ] .
Solutionπ
8 Expansion modes and listsπ
Template instances can be marked with an expansion mode.
An expansion mode specifies that multiple instances of the given instance are to be created during expansion using the elements of the selected list arguments, i.e., the elements of the list will be the arguments to the instance and not the list itself.
8.1 Listsπ
In stOTTR, a list is written as a comma separated list of elements
enclosed in regular parenthesis ((...)
).
Lists
- This is a list with two IRIs:
( ex:a, ex:b )
- This is a list with three resources:
( "a", ex:b, _:c )
- This is an empty list:
( )
OTTR's type system includes support for lists and non-empty
lists. List<X>
and NEList<X>
is respectively the type for a list
of elements of type X
and a non-empty list of elements of type
X
, where X
is any legal type.
List types
List<xsd:integer>
is the type for (possibly empty) lists ofxsd:integer
's, e.g.,(1, 2, 3, 4)
.NEList<ottr:IRI>
is the type for non-empty lists of IRIs, e.g.,( ex:A, ex:B, <http://example.com#C>)
.List<List<List<xsd:string>>>
is the type for lists of lists of lists of strings, e.g.,((("a"), ("b")), (("c")), (("d, "e")))
8.2 Expansion modesπ
Expansion modes can only be used on instances that have arguments
which are lists. The lists that the expansion mode is applied to
must be marked in the instance. To compute the set of instances
an expansion mode generates, all arguments are temporarily treated
as lists: lists marked for list expansion are kept as is, while the
other arguments are treated as singleton lists. The expansion modes
are cross
, zipMin
and zipMax
. These behave differently when
multiple list arguments are in play. The expansion mode cross
gives one instance per element in the cross-product of the lists
marked for expansion. zipMin
gives one instance per element in
the zip of the lists marked for expansion, but shortens all lists to
the length of the smallest list; and zipMax
is similar to
zipMin
, except that it extends all lists with none
until all
lists are as long as the longest list. This means that all
expansion modes behave the same if applied to only one list, and
zipMin
and zipMax
behave the same if applied to lists of equal
length.
In stOTTR an expansion mode is written by prepending it and a
vertical bar to the instance, e.g., cross | [Instance]
. A list
argument is marked by prepending ++
to the argument: ++?argument
Expansion modes demonstrated
The template ex:A
below takes two lists as input, one list of IRIs
and one list of resources, i.e., any type of element, and applies an
expansion mode to the instance ottr:NullableTriple
on both lists.
See how the three different expansion modes behave by changing the expansion mode on the pattern instance.
With cross
, every element in the first list is ex:predicate
related to every element in the second list.
With zipMin
, the i'th element in the first list is related with the
i'th element in second list, for all i-positions in the shortest
list. Hence, note that ex:o4
and ex:o5
does not appear in the
expansion result.
With zipMax
, the i'th element in the first list is related with the
i'th element in second list, for all i-positions in the longest
list. For i-positions that go beyond the size of smaller lists, a
none
value is used. Hence, note that ex:o4
and ex:o5
are related
to none
values. (The use of ottr:NullableTriple
makes it possible
to output RDF triples that contain null
values.)
Using expansion modes
The template ex:Types
below can be used to express that an IRI
has multiple classes as types. This is done by marking the instance
ex:Type
in the pattern of ex:Types
with an expansion mode. The
result of expanding the instance below is the following:
@prefix ex: <http://example.com/ns#> . @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . ex:ann a ex:Person , ex:Employee .
The expansion mode specifies that an instance of
ex:Type
is created for each element in the list of the second
argument of ex:Types
. During expansion, what happens is that an instance for
each element in the cross product of all the arguments to ex:Type
is
created, temporarily treating all arguments as lists:
\(\langle ann \rangle \times \langle Person, Employee \rangle
= \{ \langle ann, Person \rangle ,\langle ann, Employee \rangle \}\)
Exercises:
Change the signature of
ex:Types
so that the type of the first parameter is alsoList<ottr:IRI>
and mark the argument?inst
in the pattern with++
. Now change the instance in the input box toex:Types((ex:ann, ex:bob, ex:cindy, ex:david), (ex:Person, ex:Employee))
and see what this expands to. Can you explain what happened?
- Keep the setup as in 1., but now change the expansion mode to
zipMin
and see what happens to the expansion results. - Now change the expansion mode to
zipMax
and see what happens.
Solutionπ
Exploiting expansion modes
Make a template ex:Friends
with the signature below so that
the the instances given in the form produces the following, i.e., everybody
knows everybody.
@prefix ex: <http://example.com/ns#> . @prefix foaf: <http://xmlns.com/foaf/0.1/> . ex:carl foaf:knows ex:ann , ex:bob , ex:carl . ex:bob foaf:knows ex:ann , ex:carl , ex:bob . ex:ann foaf:knows ex:carl , ex:bob , ex:ann .
Solutionπ
9 More exercisesπ
Specifying relationship between organisation and persons
Make a new template ex:Member
that takes three arguments:
?org
: the IRI of an organisation,?person
: the IRI of a person,?relation
: the IRI of the relationship between the organisation and the person (e.g.foaf:member
,ex:employee
,ex:associate
). It should default tofoaf:member
.
A skeleton template is given in the form below.
Add types and other necessary flags to make the template
correct. The pattern should contain a single triple instance
stating that the ?org
is ?relation
related to ?person
, so
that the following instances expands to:
@prefix ex: <http://example.com/ns#> . @prefix foaf: <http://xmlns.com/foaf/0.1/> . ex:busAZ ex:employee ex:bob . ex:united_nations foaf:member ex:norway .
Solutionπ
Setting expansion modes
Make a new template ex:Members
that takes an organisation, a
list of individuals (given as IRIs), and a relation as argument
and produces a ex:Member
instance between the organization and
each of the persons in the list. The instances given in the form should expand
to:
@prefix ex: <http://example.com/ns#> . @prefix foaf: <http://xmlns.com/foaf/0.1/> . ex:united_nations foaf:member ex:norway , ex:germany , ex:france , ex:usa . ex:fast ex:employee ex:bob , ex:carl , ex:ann .
Note the use of optional flag in the signature of ex:Members
so that a none
value gets passed on to the ex:Member
template, which then uses
the default value foaf:member
.
Solutionπ
NamedPizza
The NamedPizza template, published at http://tpl.ottr.xyz/pizza/0.1/NamedPizza, uses lists both with and without expansion modes. The list of toppings is used to create a union of classes using the http://tpl.ottr.xyz/owl/restriction/0.1/ObjectUnionOf template, and to create a instance of http://tpl.ottr.xyz/owl/axiom/0.1/SubObjectSomeValuesFrom for each topping in the list.
Try and make new pizzas and see the results.
10 Referencesπ
- mOTTR: Concepts and Abstract Model for Reasonable Ontology Templates http://spec.ottr.xyz/mOTTR/0.1/
- rOTTR: Adapting Reasonable Ontology Templates to RDF http://spec.ottr.xyz/rOTTR/0.2/
- stOTTR: Terse Syntax for Reasonable Ontology Templates http://spec.ottr.xyz/stOTTR/0.1/
- wOTTR: Web Reasonable Ontology Templates http://spec.ottr.xyz/wOTTR/0.4/
11 Appendixπ
11.1 WebLutraπ
The web application that drives the interactive examples in this primer, called WebLutra, uses Lutra, the reference application for OTTR. Both applications are open source and available at http://gitlab.com/ottr/lutra/lutra. If you experience errors or have suggestions for improvements, please take a look at existing issues or file a new issue: http://gitlab.com/ottr/lutra/lutra/issues