Turtle & OWL Correspondence
Dolfin is a source language for OWL ontologies. Compiling a package produces a single Turtle document (plus a companion N3 file for rules, and a companion SPARQL file for queries). The reverse is also supported: an OWL/RDF graph can be recovered back into a Dolfin package. This chapter describes the mapping in both directions.
Two conversions exist:
- Dolfin → Turtle: compile a
.dlfpackage to an OWL graph. - Turtle → Dolfin: reconstruct a
.dlfpackage from an OWL graph.
The mapping is defined at the level of triples, not text. A round trip
Dolfin → Turtle → Dolfin preserves the ontology’s meaning; it does not
guarantee a byte-identical source file (see Round trips).
How IRIs are named
Every concept, property, and individual gets an IRI. IRIs are built from three ingredients:
- a base IRI (the package identity),
- the file path of the declaration inside the package,
- the local name of the entity.
The base IRI
The base IRI comes from the package declaration in package.dlf:
package <http://example.com/animals>:
dolfin_version "1"
version "0.1.0"
If the package is declared with an absolute IRI (<http://…>), that IRI is
the base directly. If it is declared with a bare name (package animals:),
the base is <compiler-base-iri>/animals, where the compiler base IRI is
supplied at compile time (default http://example.org/).
File path → namespace segment
Each ontology file contributes a namespace segment derived from its path
relative to the package root. A file named mammals.dlf produces the namespace
IRI:
http://example.com/animals/mammals#
The filename (without .dlf) becomes the last path segment, and a # fragment
terminator is appended. Nested files nest on disk and in the IRI: a file at
vertebrates/mammals.dlf yields …/animals/vertebrates/mammals#.
The base namespace (declarations that belong to the package root rather
than a sub-file) uses the base IRI directly with no extra path segment. On the
way back, base-namespace entities are written to main.dlf.
Local names and prefix labels
An entity’s local name is its Dolfin name, joined to its namespace IRI with the
# fragment separator:
| Dolfin | IRI |
|---|---|
concept Mammal in mammals.dlf | http://example.com/animals/mammals#Mammal |
concept Animal in the root file | http://example.com/animals#Animal |
In the emitted Turtle, entities are referenced with a prefix label taken
from the filename. Mammal in mammals.dlf is written mammals:Mammal;
entities in the base namespace use the empty prefix, :Animal. Each file’s
namespace IRI is bound with an @prefix declaration at the top of the document.
Overriding the IRI with @iri_name
The @iri_name annotation overrides the derived IRI. It has three forms:
# Absolute: replaces the whole namespace IRI for this file
@iri_name <http://animals.kingdom/Mammalian>
# Local segment: replaces only the last path segment
@iri_name "Mammalian" # → http://example.com/animals/Mammalian#
# On a single concept: overrides just that concept's IRI
concept Mammal:
@iri_name <http://animals.kingdom/Mammals>
@iri_name affects only the IRI. The prefix label used to reference the
entity is still derived from the filename, and sibling files and sibling
concepts are unaffected.
File resources (rdfs:isDefinedBy)
To make files (and @iri_name overrides) recoverable, every emitted entity
carries an rdfs:isDefinedBy triple pointing at its file resource — the
file’s canonical, path-derived namespace IRI with no trailing terminator and
no @iri_name override applied:
mammals:Mammal rdf:type rdfs:Class
; skos:prefLabel "Mammal"
; rdfs:isDefinedBy <http://example.com/animals/mammals> .
Each non-base file also declares its file resource and links it to the package ontology, so the package’s file set is explicit:
<http://example.com/animals/mammals> rdfs:isDefinedBy <http://example.com/animals> .
Base-namespace entities are defined by the package IRI itself (their file
resource equals the owl:Ontology subject), so no self-loop is emitted.
Because the file resource is override-free, the reverse direction uses it to
(1) assign each entity to its real file even when @iri_name rewrote the entity
IRIs, and (2) detect that an override was used — by comparing the entity’s
actual IRI against <file-resource>#<local>.
Declaration correspondence
The following table summarises the core mapping from Dolfin declarations to OWL triples.
| Dolfin | OWL / RDF |
|---|---|
concept C | C rdf:type rdfs:Class |
concept C: sub P | C rdfs:subClassOf P |
has p: T (T primitive) | p rdf:type owl:DatatypeProperty ; rdfs:domain C ; rdfs:range xsd:… |
has p: T (T a concept) | p rdf:type owl:ObjectProperty ; rdfs:domain C ; rdfs:range T |
enum / one of (a, b, …) | owl:equivalentClass [ owl:oneOf ( … ) ] + one owl:NamedIndividual per variant |
fact block | owl:NamedIndividual with rdf:type and property-value triples (the ABox) |
Package metadata
| Dolfin manifest field | OWL triple on the owl:Ontology node |
|---|---|
version | owl:versionInfo |
description | rdfs:comment |
author | dc:creator (dc: = http://purl.org/dc/elements/1.1/) |
Primitive types
| Dolfin | XSD datatype |
|---|---|
string | xsd:string |
int | xsd:integer |
float | xsd:double |
boolean | xsd:boolean |
date | xsd:date |
date_time | xsd:dateTime |
time | xsd:time |
duration | xsd:duration |
Quantities
A quantity(...) value is not a primitive type. It compiles to a typed literal
whose datatype is a canonical unit IRI ("45"^^<https://dolfin.dev/unit/kg>),
accompanied by a once-per-unit definition block that states the unit’s
coefficient, dimension, and symbol with dq: predicates. See
Units & Quantities for the full mapping.
Comments and labels
The name and comment attached to a declaration become SKOS annotations:
| Source | OWL / SKOS |
|---|---|
| declaration name | skos:prefLabel |
| leading comment text | skos:definition |
| annotated alternate label | skos:altLabel |
| annotated scope note | skos:scopeNote |
Cardinality
A has field’s cardinality becomes an OWL restriction on the owning class:
| Dolfin cardinality | OWL restriction on the class |
|---|---|
one | owl:equivalentClass [ owl:cardinality 1 ], property is owl:FunctionalProperty |
optional | owl:equivalentClass [ owl:maxCardinality 1 ], property is owl:FunctionalProperty |
some | owl:subClassOf [ owl:minCardinality 1 ] |
exactly n | owl:subClassOf [ owl:cardinality n ] |
n to m | owl:subClassOf [ owl:minCardinality n ; owl:maxCardinality m ] |
any (default) | no restriction |
Property axioms
Axioms declared on a property map to OWL property characteristics:
| Dolfin | OWL |
|---|---|
symmetric | rdf:type owl:SymmetricProperty |
reflexive | rdf:type owl:ReflexiveProperty |
transitive | rdf:type owl:TransitiveProperty |
sub q | rdfs:subPropertyOf q |
inverse of q | owl:inverseOf q |
equivalent to q | owl:equivalentProperty q |
equivalent to ^q | owl:equivalentProperty [ owl:inverseOf q ] |
equivalent to a . b (chain) | owl:propertyChainAxiom ( a b ) via an rdfs:subPropertyOf node |
equivalent to q+ | transitive + propertyChainAxiom ( q self ) |
equivalent to q* | transitive + reflexive + propertyChainAxiom ( q self ) |
Rules
Rules do not fit the OWL description-logic fragment. They compile to N3
(Notation3) { … } => { … } implications, written to a companion N3 document
alongside the Turtle. The N3 file shares the same @prefix bindings as the
Turtle so the two are consistent.
Round trips
Reconstructing Dolfin from an OWL graph works at the triple level: it reads the
owl:Ontology node, the classes, properties, restrictions, individuals, and
SKOS/dc/rdfs metadata, and rebuilds the package layout from rdfs:isDefinedBy
(falling back to the entity IRIs when it is absent).
A Dolfin → Turtle → Dolfin round trip preserves meaning but normalises
form. Keep in mind:
- Files are rebuilt from
rdfs:isDefinedBy. Each entity’s file resource names its file (…/animals/mammals→mammals.dlf); base-namespace entities land inmain.dlf. Turtle that carries nordfs:isDefinedBy(e.g. graphs not produced by this compiler) falls back to deriving the file from the entity IRI structure. @iri_nameoverrides are reconstructed. When an entity’s IRI deviates from its file resource, the override is recovered: a file-wide, uniform deviation becomes a file-level@iri_name <ns>; an isolated one becomes a concept-level@iri_name <iri>. The recovered directive uses the absolute form (a@iri_name "segment"is recovered as the equivalent absolute IRI).- Entities outside the package base are dropped. Only entities defined by
the package (via
rdfs:isDefinedBy, or IRI-under-base in the fallback) are reconstructed. Imported/external vocabulary is treated as external and skipped. dolfin_versionis not carried in the graph and defaults to"1"on the way back.- Comments and formatting are not preserved. Only the structured
annotations that became triples (
rdfs:comment, SKOS labels,dc:creator) are recovered.