Navigation: OWL ontology checker · OWL ontology publishing guide · API docs
A checklist for publishing OWL ontologies. It explains askwol’s checks and additional publishing practices.
Two tags mark where a rule comes from, and two colored boxes flag extra context:
Spec what an OWL, RDF, RDFS, or other W3C/IETF specification defines or requires.
TDCC guideline a recommendation from the TDCC ontology engineers that goes beyond what any specification mandates. A W3C Note (such as Cool URIs, cited below) is informative, not normative, so guidance drawn from one counts as a TDCC guideline here too.
Every finding in an askwol report carries one of three severity levels. The report counts individual findings, not checks: ten classes without a label are ten recommendations.
✗ Error a parsing failure or a logical or structural problem (for example an inconsistent individual, an unsatisfiable class, or a property whose domain or range is of the wrong kind). An unsatisfiable class does not make the ontology as a whole inconsistent, but nothing can be an instance of it.
⚠ Warning a likely mistake or a serious
interoperability problem (for example a namespace or import that does not
resolve, a reused term that does not exist in its vocabulary, mixed
http/https IRIs, an undefined internal term,
or an unrecognised datatype).
💡 Recommendation ontology publishing best practice (for example ontology metadata, an open licence, labels and comments, or naming conventions).
Give the ontology itself good metadata
Your ontology is itself a published research object. It should say what it is, who made it, which version it is, and under which licence it can be reused.
Spec rdf:type owl:Ontology and
owl:versionIRI/owl:versionInfo come from OWL 2;
dcterms:title, dcterms:description,
dcterms:creator, dcterms:created,
dcterms:modified, and dcterms:publisher are
defined by the
DCMI Metadata Terms
vocabulary, not OWL itself. Licensing gets its own dedicated check; see
Open licence below.
TDCC guideline Neither spec says any of these properties is mandatory on an ontology header. The core / additional grouping below is this guide’s own editorial judgement of what a well-published ontology needs. askwol reports every missing property, in either group, as a recommendation.
askwol evaluates SHACL shapes for the ontology header and checks these properties:
rdf:type owl:Ontology,
dcterms:title (or rdfs:label, or the legacy
dc:title), dcterms:description (or
rdfs:comment, or the legacy dc:description),
dcterms:creator (or dc:creator), and
owl:versionInfo or owl:versionIRI.dcterms:created
(or dcterms:issued, or dc:date),
dcterms:modified (or dc:date), and
dcterms:publisher (or dc:publisher).Pre-2010 ontologies (e.g. FOAF, OWL-Time) often use the older
Dublin Core Elements
(dc:) properties instead of DCMI Terms; askwol accepts
either, since they carry the same meaning. One nuance: Elements 1.1’s
single, generic dc:date property doesn’t distinguish created
from modified, so askwol accepts it for either (or both) of the two
additional date checks above.
Version information is part of good ontology metadata.
Spec OWL 2 defines
owl:versionIRI
to identify a particular release, and
owl:versionInfo
to hold “a string that describes the IRI’s version,” with no
format required.
TDCC guideline This guide recommends
Semantic Versioning
(MAJOR.MINOR.PATCH) as a practical convention, not an OWL
requirement: bump major when you remove or redefine a
term, minor when you add terms without breaking existing
ones, and patch for fixes such as corrected labels or
comments.
<http://example.org/my-ontology> a owl:Ontology ;
owl:versionIRI <http://example.org/my-ontology/2.0.0> ;
owl:versionInfo "2.0.0" .
Some ontologies version by date instead, especially W3C
specifications on a fixed release schedule: PROV-O’s
owl:versionIRI is
http://www.w3.org/ns/prov-o-20130430. A date is simpler than
semver but only says when something changed, not whether it is
safe to upgrade. Pick one scheme per ontology and stick to it.
Spec To include another ontology’s
axioms in yours, use
OWL 2
owl:imports in the ontology header. Merely referencing a
vocabulary’s terms does not require an import:
<https://example.org/my-ontology> a owl:Ontology ;
owl:imports <http://xmlns.com/foaf/0.1/> .
This tells reasoners and tools where your external terms are defined, so they can load the imported ontology and reason over it together with yours.
TDCC guideline Deciding which
vocabularies deserve a formal import is a modelling judgement call askwol
does not second-guess. What it does check is whether every
owl:imports target you already declared is actually
reachable and provides parseable RDF. This check is askwol’s own
addition; OWL 2 does not require import targets to be checked at
authoring time.
What askwol checks: every term defined inside your
ontology’s own namespace is classified as either hash style
(http://example.org/ont#Person) or slash style
(http://example.org/ont/Person), per declared
owl:Ontology base IRI. A base IRI whose defined terms all use
the same pattern is fine; one that mixes both is reported as a
warning. An ontology
that legitimately bundles more than one base IRI (a rare pattern, e.g.
the W3C PROV family) may use a different, consistent style for each
without being flagged.
/Person is the same term
as #Person.TDCC guideline Neither RDF nor OWL requires hash or slash IRIs; both are valid (the W3C “Cool URIs for the Semantic Web” Interest Group Note describes both). They differ in how the identifier behaves over HTTP and how the vocabulary scales.
ont#Person.
The fragment is stripped before the HTTP request, so terms sharing the
same base IRI are retrieved through one document. This is simple to host,
but clients may need to download the whole vocabulary to look up one
term. Used by OWL and RDF Schema.ont/Person.
Each term is its own HTTP resource, typically served via a
303 See Other redirect per the W3C TAG’s
httpRange-14
resolution (2005). More flexible for large or growing vocabularies,
at the cost of server-side redirect rules and content negotiation. Used
by FOAF, Schema.org, Dublin Core, and DBpedia.TDCC guideline If in doubt, go with slash: it scales. Use hash only for a vocabulary you know will stay small. The Cool URIs note concludes:
“Hash URIs should be preferred for rather small and stable sets of resources that evolve together. The ideal case are RDF Schema vocabularies and OWL ontologies. […] 303 URIs may also be used for [large] data sets, making neater-looking URIs.”
Either way, pick one per base IRI and don’t mix styles within it. Use a domain you control, or a persistent ID service like w3id.org or purl.org, so your IRIs survive domain changes.
Use http or https, but be consistent per namespace
What askwol checks: every IRI used in the ontology
(in subject, predicate, or object position, plus every bound namespace)
is grouped by namespace (the base IRI up to the last / or
#), not just by host, so two unrelated vocabularies that
happen to share a host are never compared to each other. A namespace
that appears under exactly one URI scheme is fine; one referenced
under both http:// and https:// is reported as a
warning. The report
lists the conflicting namespaces with examples of each scheme so you can
pick one canonical form and migrate the others.
Spec http://example.org/ont/Person
and https://example.org/ont/Person are
different IRIs: RDF compares IRIs by their exact strings,
per RDF 1.1 Concepts.
Mixing schemes can break joins that rely on
exact IRI matches, including SPARQL and any tool that does string
comparison on URIs.
Most foundational vocabularies were minted before HTTPS was ubiquitous.
OWL, RDFS, FOAF, Dublin Core, SKOS and PROV-O all use
http://. Changing them would break billions of existing
triples, so they stay on http.
http://xmlns.com/foaf/0.1/name to https://.
You would be creating a different IRI that matches nothing in
other people’s data.https:// is fine and recommended.
Schema.org switched to https as its canonical scheme.http://, use http://.http → https), so both resolve, but always
use the canonical form in your RDF.Adopt an open licence
TDCC guideline Your ontology should be released under an open licence; this guide recommends the DCMI property dcterms:license. To meet the Linked Open Data principles, the licence must satisfy the Open Definition: “anyone can freely access, use, modify, and share [the ontology] for any purpose (subject, at most, to requirements that preserve provenance and openness).”
A licence is open if it’s equivalent to the public domain, or at most adds attribution or share-alike restrictions; non-commercial or no-derivatives clauses are not open. For maximum reuse, this guide recommends one of the two Creative Commons licences below.
https://creativecommons.org/publicdomain/zero/1.0/
https://creativecommons.org/licenses/by/4.0/
askwol also recognises other licences that meet the Open Definition but are less suitable for ontologies, for the reasons below.
https://creativecommons.org/licenses/by-sa/4.0/; too restrictive due to the share-alike.
http://opendatacommons.org/licenses/pddl/1.0/; designed for databases and their contents.
http://opendatacommons.org/licenses/by/1.0/; covers rights in the database; individual contents may need separate licences.
http://opendatacommons.org/licenses/odbl/1.0/; too restrictive due to the share-alike.
Declare it with dcterms:license in the ontology header:
<https://example.org/my-ontology> a owl:Ontology ;
dcterms:license <https://creativecommons.org/publicdomain/zero/1.0/> .
dcterms:license and schema:license values on ontology headers against known licences. A missing, unrecognised, non-open, non-preferred or multiple licence declaration is a recommendation. Unrecognised means openness could not be established; it does not mean non-open.A namespace is the URI that a prefix expands to. In
@prefix foaf: <http://xmlns.com/foaf/0.1/> the prefix is
foaf and the namespace is
http://xmlns.com/foaf/0.1/. This check looks at those namespace
URIs; the short prefix aliases themselves are covered by
Unused prefixes below.
TDCC guideline Every namespace URI should return something useful when fetched with HTTP. Ideally it returns RDF (content-negotiated), so tools can discover term definitions automatically. Neither RDF nor OWL requires a namespace to be dereferenceable; this expectation comes from the Linked Data principles and the W3C Note linked below.
http://xmlns.com/foaf/0.1/ returns RDF when asked with
Accept: application/rdf+xml.If you host your own ontology, configure your server to support content negotiation, serving RDF to machines and HTML to browsers; see Server configuration below for the details. askwol reports a namespace that does not resolve as a warning.
Keep your prefixes clean
Spec Each
@prefix
line binds a short prefix to a namespace URI.
TDCC guideline Turtle itself does not
forbid declaring a prefix you never use; this check is about good
hygiene: only declare prefixes you actually use. Leftover
@prefix declarations clutter the file and confuse readers;
they suggest a dependency that doesn’t exist.
@prefix dct: <http://purl.org/dc/terms/> . # used below @prefix geo: <http://www.opengis.net/ont/geosparql#> . # unused, remove it
Make sure reused terms actually exist
TDCC guideline Don’t reinvent the wheel. Before defining a new term, check if an established vocabulary already covers it. No spec requires reuse, but the wider Semantic Web interoperates far better when ontologies share terms:
foaf:nme instead
of foaf:name breaks interoperability.foaf:nme, made-up terms like
owl:MadeUpClass, and namespace hijacking
(asserting a brand-new term such as foaf:MadeUpConcept under
someone else’s namespace instead of your own). Terms from your own
namespace are checked separately (see
Internal term definitions).owl:deprecated is an
OWL 2
annotation property, and
owl:DeprecatedClass/owl:DeprecatedProperty come
from the
OWL 1 Reference
(used by e.g. VIVO).
TDCC guideline A
vs:term_status of “deprecated”/“archaic”
is a community convention documented in an
editor’s draft
and used by e.g. FOAF.
askwol checks for all three and flags a deprecated reused term
as a warning, so you don’t quietly build on a term the source
vocabulary is phasing out.Define every term you use in your own namespace
TDCC guideline Every term you use from your own namespace should also be defined there. Don’t just use a term; define it. RDF’s open-world assumption actually permits referencing an IRI with no triples about it at all; askwol still flags it, because within your own namespace an undefined term is almost always an authoring mistake, not an intentional stub.
<#Person> a owl:Class ;
rdfs:label "Person"@en ;
rdfs:comment "A human being."@en .
ex:Persom but
never define it, that’s probably a typo. askwol catches these.rdfs:label a owl:AnnotationProperty, as PROV-O and FOAF do).
askwol correctly recognises this as reuse of an existing term, keeping
your own namespace scoped to what you actually define. New terms always
belong in your own namespace: the
External term definitions check confirms
that anything asserted under an external prefix, like
foaf:MadeUpConcept, genuinely exists there already, catching
namespace hijacking along the way.Categorise your terms and name them consistently
Spec OWL 2 defines six entity types:
classes, datatypes,
object properties, data properties,
annotation properties, and named individuals.
askwol lists each internal term with the
category it detected, so you can spot a term that was never typed
(rdf:type missing) or typed as the wrong kind of thing.
<#Person> a owl:Class . <#hasParent> a owl:ObjectProperty . <#birthDate> a owl:DatatypeProperty .
TDCC guideline Capitalisation is a
community convention, not an OWL or RDFS rule; nothing stops you from
naming a class person or a property HasName.
Consistent casing helps distinguish classes from properties. askwol
reports a mismatch as a recommendation.
Person, Dataset, Organisation.hasParent, birthDate, title.Some vocabularies use stable, coded identifiers instead: CIDOC CRM’s
properties look like P2_has_type (the number is the permanent
identifier; the wording after it can change between versions), and
Wikidata’s are fully opaque, like P19, deliberately avoiding
any one language’s naming bias. askwol recognises this pattern, an
uppercase letter directly followed by a digit, and does not flag it.
hasWife,
wifeOf, lovedBy. This is a readability convention,
not something askwol enforces; askwol only checks the case of the first
letter, via SHACL shapes.person, or an uppercase property like HasName,
with no digit following the capital) makes an ontology harder to read and
to reuse.Give properties a domain and a range
Spec An
rdfs:domain
says what kind of subject a property applies to; an
rdfs:range
says what kind of value it takes.
TDCC guideline RDFS does not require
either one; declaring both is this guide’s recommendation because it
makes a property self-documenting and lets tools reason about it.
<#hasParent> a owl:ObjectProperty ;
rdfs:domain <#Person> ;
rdfs:range <#Person> . # a class
<#birthDate> a owl:DatatypeProperty ;
rdfs:domain <#Person> ;
rdfs:range xsd:date . # a datatype
Spec In OWL 2 DL, an object property ranges over classes and a datatype property over datatypes. Getting that wrong puts the ontology outside OWL 2 DL, so askwol reports it as an error. A domain or range that is simply missing is only a recommendation.
rdfs:domain :Person on :birthDate tells a reasoner
that anything with a :birthDate is a :Person. Pick
domains and ranges that are actually true of every use.rdfs:domain and
rdfs:range declared directly on a property, not ones
inherited from a super-property. A reasoner does follow that inheritance,
so this check can occasionally flag something a reasoner would treat as
fine. Kind checks use selected named class/datatype evidence; anonymous
expressions are not evaluated. Checked against SHACL shapes.
Deprecated properties (see
External term definitions) are exempt.Spec RDF typed literals use datatype
IRIs, commonly from
XSD
built-ins (xsd:string, xsd:integer,
xsd:date, xsd:boolean, …)
or rdf:langString. A datatype property can range over
rdfs:Literal
or a specific datatype. Custom datatypes can be declared with
rdfs:Datatype.
RDF itself places no closed list on datatype IRIs; any IRI is legal there.
Spec OWL 2 has a specific
datatype map
and restrictions on datatype definitions; recognising an IRI or finding
a declaration alone does not establish OWL 2 DL conformance.
askwol checks datatype IRIs against its built-in list and local
declarations, reporting unrecognised IRIs as warnings.
It does not validate literal values or establish OWL profile conformance.
<#age> rdfs:range xsd:nonNegativeInteger . <#born> rdfs:range xsd:date . "42"^^xsd:integer
xsd:stirng,
xsd:dateTiem) is treated as a brand-new, unknown datatype.
Filters and validators that expect the real datatype then skip your
values. askwol lists every datatype it sees and flags the ones it does not
recognise.Keep concept schemes separate from the schema
TDCC guideline An OWL ontology can contain both schema definitions and named individuals. Most named individuals are fine to keep in the same file. SKOS concepts, the members of a controlled vocabulary or thesaurus, are the one case worth pulling out. A concept scheme is typically much larger than the schema and grows on its own schedule: new terms get added without ever touching a class or property definition. This guide recommends keeping SKOS concepts in their own SKOS concept scheme, separate from the ontology file, so schema and data can each evolve and be reused independently. Mixing OWL and SKOS is valid; separation is a TDCC organisation preference.
<#Dataset> a owl:Class . # schema, belongs here <#biology> a skos:Concept . # concept, belongs in a SKOS scheme <#Monday> a <#DayOfWeek> . # named individual, fine to keep here
skos:Concept instances defined
in your own namespace, as recommendations; a full concept scheme has usually outgrown the schema
file and is better managed on its own. Named individuals are left alone:
many ontologies deliberately define a small, fixed set of them alongside
their schema (days of week, units of measure, as OWL-Time does), a
legitimate modelling pattern rather than accidental instance data. External
terms are ignored either way. Checked against SHACL shapes.Give every class and property a human-readable label
TDCC guideline Every class and
property you define should carry a human-readable
rdfs:label:
a short name a person can read. RDFS defines what the property means but
does not require any resource to have one; this guide recommends adding
one to everything you define.
<#hasMother> a owl:ObjectProperty ;
rdfs:label "has mother"@en ;
rdfs:domain <#Person> ;
rdfs:range <#Person> .
@en, @de)
to support multilingual ontologies. Consider
skos:prefLabel and skos:altLabel for richer
labelling.rdfs:label. Reused external vocabulary terms, and terms you
have marked deprecated yourself, are ignored. A missing label is reported
as a recommendation.Give every class and property a clear description
TDCC guideline Every class and
property you define should also carry an
rdfs:comment:
a brief description of what it means. As with labels, RDFS defines the
property but does not require you to use it; this guide recommends it for
every term you define.
<#hasMother> a owl:ObjectProperty ;
rdfs:label "has mother"@en ;
rdfs:comment "Relates a person to their biological mother."@en ;
rdfs:domain <#Person> ;
rdfs:range <#Person> .
rdfs:comment. Reused external vocabulary terms, and terms you
have marked deprecated yourself, are ignored. A missing comment is reported
as a recommendation.owl:inverseOf) doesn’t need its own comment when its
partner already has one: the relationship is documented either way.Use language tags consistently
TDCC guideline If your ontology includes
human-readable labels and descriptions, tag every literal that carries
natural-language text with a
BCP 47 language tag
(@en, @nl, @de, …),
producing an RDF 1.1
language-tagged string.
:Person a owl:Class ;
rdfs:label "person"@en ,
"persoon"@nl ;
rdfs:comment "A human being."@en ,
"Een menselijk wezen."@nl .
TDCC guideline Neither RDF nor BCP 47 requires every subject to carry the same set of languages; askwol checks for it anyway, because an inconsistency here is usually a missed translation, not a deliberate choice:
rdfs:label uses @en on most subjects but one
subject has a plain "My label" without a tag, that’s
inconsistent.@en and @nl labels on most classes, every
class should have both. A missing @nl on one subject
is probably an oversight.FILTER(LANG(?label) = "en") won’t match it. The triple
is still in your data, but any app or query that filters by language will
skip it, as if it doesn’t exist.rdfs:label, rdfs:comment,
skos:prefLabel, skos:definition, and other
standard annotation properties for tag consistency on terms defined in
your own namespace. Reused external vocabulary terms, and terms you have
marked deprecated yourself, are ignored.Check logical consistency
Spec OWL is a logical language. OWL 2 Direct Semantics formally defines when an ontology is consistent and when a class is satisfiable; a reasoner can derive consequences from your axioms and detect contradictions you didn’t intend. askwol displays a summary and two types of logical finding in the Reasoner checks section of the report:
owl:Nothing or as incompatible
owl:disjointWith classes. Each offending individual is
listed by IRI so you can locate the contradiction.owl:Nothing (e.g. via disjoint
superclasses). The class is syntactically valid but can never have
instances. This does not make the ontology as a whole inconsistent.A functional object property with two object IRIs may imply that they name the same individual. It is a contradiction only if the objects must be different. For a functional datatype property, two unequal data values contradict functionality. askwol does not check all these cases.
Each inconsistent individual and each unsatisfiable class is reported as an error.
owl:imports. This is an implementation
tradeoff, not a spec requirement. The results cover selected class
membership and named-class satisfiability patterns, not all logical
contradictions. RDF-based rules can differ from OWL Direct Semantics for
class/individual punning.
For deeper checks (against imports, with HermiT or Pellet), use
a desktop tool like Protégé.Run askwol on your ontology during development, not just before release.
askwol check my-ontology.ttlaskwol stops at the first blocking parse error; ontology checks are not run. Check that the selected format matches the file contents. A reported location marks where the parser stopped; the cause may be earlier. Correct the error and try again. Further errors may then appear.
For syntax feedback while editing:
| Format | Tools |
|---|---|
| Turtle | Turtle Language Server for VS Code. |
| RDF/XML | XML Language Support by Red Hat for VS Code checks XML syntax, not all RDF/XML rules. |
| JSON-LD | A strict JSON editor, then the JSON-LD Playground. Valid JSON is not necessarily valid JSON-LD. |
| N-Triples / N3 | Mentor for VS Code checks syntax as you edit. |
These tools may also stop at a blocking error. askwol does not repair the file or collect all syntax errors.
Once published, your ontology’s IRI should resolve: a client that dereferences it must get the RDF back. Two server-side settings make that work.
text/turtle, RDF/XML as application/rdf+xml,
JSON-LD as application/ld+json. A file served as
text/plain or application/octet-stream does not
identify RDF; some tools need a format hint or a filename-based fallback.Accept header: return RDF to tools that ask for it, and an
HTML documentation page to browsers. A common pattern is one term IRI
(https://example.org/onto#Term) that redirects
(303 See Other) to either the .ttl or an HTML view
depending on Accept.GitHub file pages and raw files. A GitHub
/blob/ URL opens a file viewer that returns HTML, even when
its path ends in .owl or .ttl. Ontology tools need
the file contents. Open the file on GitHub, select
Raw,
and copy its URL. A filename extension alone does not establish what a
URL returns. Elsewhere, a published ontology IRI may legitimately show
HTML in a browser while serving RDF to tools through content negotiation.
A raw file URL is a retrieval location. Keep the ontology, namespace, and term IRIs published by the vocabulary owner; do not replace these identifiers with a GitHub download URL.
Relative identifiers need a base IRI. A term such as
<#Person> resolves against the document’s base.
Declare @base in Turtle or xml:base in RDF/XML,
or supply the intended base through the upload settings, API
base_uri, or CLI --base-uri. Without a declared
base, a URL uses its final retrieval location; an uploaded or local file
can produce file:// identifiers tied to that file location.
Choose the intended identifiers explicitly before publishing.
Some tools discover RDF through links in HTML pages or known alternative
locations. Other tools may not follow those links. Ask Wol discloses this
discovery and warns when an owl:imports target relies on it.
Configure the declared import IRI to serve RDF directly, through content
negotiation, or through an HTTP redirect.
https://lod-4tu.tudelft.nl/dataset#, and
dereferencing https://lod-4tu.tudelft.nl/dataset (no fragment)
returns the ontology itself, directly or via redirect.text/plain
for .ttl. Set the MIME type explicitly in your web server or
reverse proxy so tools can reliably recognise the RDF.Generate human-readable documentation
Good rdfs:label and rdfs:comment annotations pay
off once turned into a browsable HTML page: a documentation generator reads
your Turtle file and produces one, ready to serve alongside the RDF via
content negotiation.
pyLODE is a lightweight Python tool: a single command turns a Turtle file into one static HTML page that needs no server or JavaScript to view (example output).
python3 -m venv .venv && source .venv/bin/activate python -m pip install pylode pylode my-ontology.ttl -o my-ontology.html
WIDOCO
is a Java-based documentation generator that produces a multi-page bundle:
metadata extraction, an optional WebVOWL diagram, and a ready-to-deploy
.htaccess for content negotiation.
java -jar widoco.jar -ontFile my-ontology.ttl -outFolder docs \
-getOntologyMetadata -rewriteAll -uniteSections -webVowl -htaccess
python3 -m http.server 8080) rather than from the
file system.For W3C specification-style output, ReSpec renders technical documents in the browser, and OntoReSpec generates the markup it needs from an RDF ontology or data model (example). OntoReSpec is early-stage, with no stable release yet.