Introducing Iolanta ontology
Assignment for MC-1 Fall 2025 © Anatoly Scherbakov
Problem & Use Cases
The semantic web contains vast amounts of machine-readable RDF data, but this data is often difficult for humans to understand and navigate.
- Iolanta is a tool that aims to provide a uniform way to make Linked Data human friendly,
- which capability is underpinned by the Iolanta ontology described in this document.
Use cases we're going to focus on are as follows:
-
Visualize Linked Data
Different output formats require different visualization approaches. Iolanta's facet system adapts rendering based on output datatype, allowing the same data to be rendered as text, HTML, diagrams, or other formats.
-
Browse & Discover Linked Data
Iolanta implements text-based terminal interface to browse Linked Data on the Web.
Serialization: YAML-LD
The Iolanta ontology is implemented using YAML-LD, a human-friendly serialization format for JSON-LD that makes RDF data more readable and maintainable. Each class and property is defined in separate .yamlld files with a shared context, which is provided below.
"@context":
# Use $keywords instead of @keywords in the ontology & data files.
# This will allow to avoid extra quotes.
"@import": https://json-ld.org/contexts/dollar-convenience.jsonld
# Make well known ontologies usable
rdfs: http://www.w3.org/2000/01/rdf-schema#
owl: http://www.w3.org/2002/07/owl#
foaf: http://xmlns.com/foaf/0.1/
schema: https://schema.org/
vann: http://purl.org/vocab/vann/
rdfg: http://www.w3.org/2009/rdfg#
xsd: http://www.w3.org/2001/XMLSchema#
$: rdfs:label
# I have a weakness for Unicode symbols and YAML-LD permits me an indulgence ☺
⊆:
"@type": "@id"
"@id": rdfs:subClassOf
domain:
"@id": rdfs:domain
"@type": "@id"
range:
"@id": rdfs:range
"@type": "@id"
→:
"@id": iolanta:outputs
"@type": "@id"
↦:
"@id": iolanta:matches
Facet class
"@context": context.yamlld
$id: iolanta:Facet
$type: owl:Class
$: Facet
rdfs:comment: |
A Facet is a visualization component that transforms RDF nodes into human-readable formats.
Facets are the core mechanism by which Iolanta makes Linked Data accessible to users.
Each facet is designed to handle specific types of RDF nodes and render them appropriately
for different output formats (terminal, web, etc.).
graph LR
iolanta_Facet("Facet")
click iolanta_Facet "iolanta:Facet"
Literal-0161428b81534d179a220f1d9d9df7f3[["A Facet is a visualization component that transforms RDF nodes into human-readable formats.
Facets are the core mechanism by which Iolanta makes Linked Data accessible to users.
Each facet is designed to handle specific types of RDF nodes and render them appropriately
for different output formats (terminal, web, etc.).
"]]
iolanta_Facet("Facet")
click iolanta_Facet "iolanta:Facet"
http___www_w3_org_2002_07_owl_Class("Class")
click http___www_w3_org_2002_07_owl_Class "http://www.w3.org/2002/07/owl#Class"
iolanta_Facet --- 2bb922d79c97e02dbba10ac960c9ab25(["comment"])--> Literal-0161428b81534d179a220f1d9d9df7f3
click 2bb922d79c97e02dbba10ac960c9ab25 "http://www.w3.org/2000/01/rdf-schema#comment"
class 2bb922d79c97e02dbba10ac960c9ab25 predicate
iolanta_Facet --- 4eb21eeb59bca8c61e953fe9086cf773(["type"])--> http___www_w3_org_2002_07_owl_Class
click 4eb21eeb59bca8c61e953fe9086cf773 "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"
class 4eb21eeb59bca8c61e953fe9086cf773 predicate
classDef predicate fill:transparent,stroke:transparent,stroke-width:0px;
Graph rendering
One of the Facets that Iolanta implements is a Mermaid renderer, which was responsible for generation of the graph above. Below, we will look a bit deeper into how that works.
OutputDatatype class
"@context": context.yamlld
$id: iolanta:OutputDatatype
$type: owl:Class
$: Output Datatype
⊆: rdfs:Datatype
rdfs:comment: |
Output format where visualization applications render their results.
Examples: terminal text, HTML, Mermaid diagrams.
graph LR
iolanta_OutputDatatype("Output Datatype")
click iolanta_OutputDatatype "iolanta:OutputDatatype"
http___www_w3_org_2002_07_owl_Class("Class")
click http___www_w3_org_2002_07_owl_Class "http://www.w3.org/2002/07/owl#Class"
iolanta_OutputDatatype("Output Datatype")
click iolanta_OutputDatatype "iolanta:OutputDatatype"
Literal-53d3f4c1edd701295ec517eb3054c54c[["Output format where visualization applications render their results.
Examples: terminal text, HTML, Mermaid diagrams.
"]]
iolanta_OutputDatatype("Output Datatype")
click iolanta_OutputDatatype "iolanta:OutputDatatype"
http___www_w3_org_2000_01_rdf-schema_Datatype("Datatype")
click http___www_w3_org_2000_01_rdf-schema_Datatype "http://www.w3.org/2000/01/rdf-schema#Datatype"
iolanta_OutputDatatype --- 1612f2e1de4a62cc1e34441428ef79ab(["type"])--> http___www_w3_org_2002_07_owl_Class
click 1612f2e1de4a62cc1e34441428ef79ab "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"
class 1612f2e1de4a62cc1e34441428ef79ab predicate
iolanta_OutputDatatype --- bd834691fbbaf6e925da018a5efe50bb(["comment"])--> Literal-53d3f4c1edd701295ec517eb3054c54c
click bd834691fbbaf6e925da018a5efe50bb "http://www.w3.org/2000/01/rdf-schema#comment"
class bd834691fbbaf6e925da018a5efe50bb predicate
iolanta_OutputDatatype --- 4e687391c7c2b68d411d1c212a7f11b7(["subClassOf"])--> http___www_w3_org_2000_01_rdf-schema_Datatype
click 4e687391c7c2b68d411d1c212a7f11b7 "http://www.w3.org/2000/01/rdf-schema#subClassOf"
class 4e687391c7c2b68d411d1c212a7f11b7 predicate
classDef predicate fill:transparent,stroke:transparent,stroke-width:0px;
SPARQLText class
"@context": context.yamlld
$id: iolanta:SPARQLText
$type: owl:Class
$: SPARQL Text
⊆: rdfs:Datatype
comment: |
Datatype for SPARQL query text.
Must be valid SPARQL syntax.
graph LR
iolanta_SPARQLText("SPARQL Text")
click iolanta_SPARQLText "iolanta:SPARQLText"
http___www_w3_org_2002_07_owl_Class("Class")
click http___www_w3_org_2002_07_owl_Class "http://www.w3.org/2002/07/owl#Class"
iolanta_SPARQLText("SPARQL Text")
click iolanta_SPARQLText "iolanta:SPARQLText"
http___www_w3_org_2000_01_rdf-schema_Datatype("Datatype")
click http___www_w3_org_2000_01_rdf-schema_Datatype "http://www.w3.org/2000/01/rdf-schema#Datatype"
iolanta_SPARQLText --- e14dbc3ccce2751ba5095b045a4d081b(["type"])--> http___www_w3_org_2002_07_owl_Class
click e14dbc3ccce2751ba5095b045a4d081b "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"
class e14dbc3ccce2751ba5095b045a4d081b predicate
iolanta_SPARQLText --- a9df961f619378ade262212fdecdc8f6(["subClassOf"])--> http___www_w3_org_2000_01_rdf-schema_Datatype
click a9df961f619378ade262212fdecdc8f6 "http://www.w3.org/2000/01/rdf-schema#subClassOf"
class a9df961f619378ade262212fdecdc8f6 predicate
classDef predicate fill:transparent,stroke:transparent,stroke-width:0px;
matches datatype property
"@context": context.yamlld
$id: iolanta:matches
$type: owl:DatatypeProperty
$: matches
domain: iolanta:Facet
range: iolanta:SPARQLText
comment: |
Maps a Facet instance to a SPARQL <code>ASK</code>
query pattern that can use <code>$this</code>
bound variable. If the query returns True,
this Facet can visualize the node denoted as
<code>$this</code> in the query.
graph LR
iolanta_matches("matches")
click iolanta_matches "iolanta:matches"
iolanta_Facet("Facet")
click iolanta_Facet "iolanta:Facet"
iolanta_matches("matches")
click iolanta_matches "iolanta:matches"
http___www_w3_org_2002_07_owl_DatatypeProperty("DatatypeProperty")
click http___www_w3_org_2002_07_owl_DatatypeProperty "http://www.w3.org/2002/07/owl#DatatypeProperty"
iolanta_matches("matches")
click iolanta_matches "iolanta:matches"
iolanta_SPARQLText("SPARQL Text")
click iolanta_SPARQLText "iolanta:SPARQLText"
iolanta_matches --- d01f56ff67e48f2ad033fc63dc241b00(["domain"])--> iolanta_Facet
click d01f56ff67e48f2ad033fc63dc241b00 "http://www.w3.org/2000/01/rdf-schema#domain"
class d01f56ff67e48f2ad033fc63dc241b00 predicate
iolanta_matches --- 5f21af5d5eecd093047ed0b0dd4ec0d6(["type"])--> http___www_w3_org_2002_07_owl_DatatypeProperty
click 5f21af5d5eecd093047ed0b0dd4ec0d6 "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"
class 5f21af5d5eecd093047ed0b0dd4ec0d6 predicate
iolanta_matches --- 9d47bc3f4bdb1634fc272168a3f3eeb1(["range"])--> iolanta_SPARQLText
click 9d47bc3f4bdb1634fc272168a3f3eeb1 "http://www.w3.org/2000/01/rdf-schema#range"
class 9d47bc3f4bdb1634fc272168a3f3eeb1 predicate
classDef predicate fill:transparent,stroke:transparent,stroke-width:0px;
outputs object property
"@context": context.yamlld
$id: iolanta:outputs
$type: owl:ObjectProperty
$: outputs
domain: iolanta:Facet
range: iolanta:OutputDatatype
comment: |
Links a facet to its supported output formats.
Examples: terminal, HTML, Mermaid.
graph LR
iolanta_outputs("outputs")
click iolanta_outputs "iolanta:outputs"
iolanta_Facet("Facet")
click iolanta_Facet "iolanta:Facet"
iolanta_outputs("outputs")
click iolanta_outputs "iolanta:outputs"
http___www_w3_org_2002_07_owl_ObjectProperty("ObjectProperty")
click http___www_w3_org_2002_07_owl_ObjectProperty "http://www.w3.org/2002/07/owl#ObjectProperty"
iolanta_outputs("outputs")
click iolanta_outputs "iolanta:outputs"
iolanta_OutputDatatype("Output Datatype")
click iolanta_OutputDatatype "iolanta:OutputDatatype"
iolanta_outputs --- fd722a9993f374578620ab05b9ba1ffd(["domain"])--> iolanta_Facet
click fd722a9993f374578620ab05b9ba1ffd "http://www.w3.org/2000/01/rdf-schema#domain"
class fd722a9993f374578620ab05b9ba1ffd predicate
iolanta_outputs --- 1d35bb3d419b744a5b73ccbdaa04884e(["type"])--> http___www_w3_org_2002_07_owl_ObjectProperty
click 1d35bb3d419b744a5b73ccbdaa04884e "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"
class 1d35bb3d419b744a5b73ccbdaa04884e predicate
iolanta_outputs --- 1dad8eafd900bf48c87f461de56ae589(["range"])--> iolanta_OutputDatatype
click 1dad8eafd900bf48c87f461de56ae589 "http://www.w3.org/2000/01/rdf-schema#range"
class 1dad8eafd900bf48c87f461de56ae589 predicate
classDef predicate fill:transparent,stroke:transparent,stroke-width:0px;
Identifier Strategy
We use slash-terminated URIs under https://iolanta.tech/ so every resource is dereferenceable to its own page.
Facet identifiers with Package URL (purl)
Facets use pkg: URIs per the purl spec.
- Format:
pkg:pypi/<package>#<facet> - Examples:
pkg:pypi/iolanta#mermaid-graphfor Mermaid rendering;pkg:pypi/iolanta#textual-graphfor text user interface graph triple lists;pkg:pypi/iolanta#title-foaf-personfor the name of a person
- Benefits: unique package-scoped IDs; version-agnostic; standards-based
Graph Representation Choice
Since the domain is Linked Data visualization, we use RDF with OWL semantics, and SPARQL as the query language.
- Native URIs and vocabularies; broad reuse and interoperability.
- LPG is out of scope for this document.
Querying the Knowledge Graph & Visualizing it
There are at least two ways to get a Mermaid representation of the Facet class description:
{{ (docs / 'blog/knowledge-graph-assignment/facet.yamlld') | as('mermaid') }}
iolanta docs/blog/knowledge-graph-assignment/facet.yamlld --as mermaid
Stage 0: What is mermaid exactly?
It is a shortened form of https://iolanta.tech/datatypes/mermaid, an instance of OutputDatatype defined as follows:
"@context":
"@import": https://json-ld.org/contexts/dollar-convenience.jsonld
iolanta: https://iolanta.tech/
rdfs: http://www.w3.org/2000/01/rdf-schema#
$: rdfs:label
→:
"@type": "@id"
"@id": iolanta:outputs
↦:
"@id": iolanta:matches
"@type": iolanta:SPARQLText
$id: pkg:pypi/iolanta#mermaid-graph
$: Mermaid Graph
→:
$id: https://iolanta.tech/datatypes/mermaid
$: Mermaid
$type: iolanta:OutputDatatype
↦:
- ASK WHERE { GRAPH $this { ?s ?p ?o } }
- ASK WHERE { $this iolanta:has-sub-graph ?subgraph }
graph LR
https___iolanta_tech_datatypes_mermaid("Mermaid")
click https___iolanta_tech_datatypes_mermaid "https://iolanta.tech/datatypes/mermaid"
https___iolanta_tech_OutputDatatype("iolanta.tech/OutputDatatype")
click https___iolanta_tech_OutputDatatype "https://iolanta.tech/OutputDatatype"
pkg_pypi_iolanta_mermaid-graph("Mermaid Graph")
click pkg_pypi_iolanta_mermaid-graph "pkg:pypi/iolanta#mermaid-graph"
Literal-c68220abab4f6bdf9e5acec73f922900[["ASK WHERE { GRAPH $this { ?s ?p ?o } }"]]
pkg_pypi_iolanta_mermaid-graph("Mermaid Graph")
click pkg_pypi_iolanta_mermaid-graph "pkg:pypi/iolanta#mermaid-graph"
Literal-e6835a48474d4a4a89205cd8b404de41[["ASK WHERE { $this iolanta:has-sub-graph ?subgraph }"]]
pkg_pypi_iolanta_mermaid-graph("Mermaid Graph")
click pkg_pypi_iolanta_mermaid-graph "pkg:pypi/iolanta#mermaid-graph"
https___iolanta_tech_datatypes_mermaid("Mermaid")
click https___iolanta_tech_datatypes_mermaid "https://iolanta.tech/datatypes/mermaid"
https___iolanta_tech_datatypes_mermaid --- 2c41fe73c4bf95cb558aa97c1a8146d7(["type"])--> https___iolanta_tech_OutputDatatype
click 2c41fe73c4bf95cb558aa97c1a8146d7 "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"
class 2c41fe73c4bf95cb558aa97c1a8146d7 predicate
pkg_pypi_iolanta_mermaid-graph --- 8db2148e4e56918908ee4f077007d419(["iolanta.tech/matches"])--> Literal-c68220abab4f6bdf9e5acec73f922900
click 8db2148e4e56918908ee4f077007d419 "https://iolanta.tech/matches"
class 8db2148e4e56918908ee4f077007d419 predicate
pkg_pypi_iolanta_mermaid-graph --- 3238bde1af35c3f73d34849ad4437033(["iolanta.tech/matches"])--> Literal-e6835a48474d4a4a89205cd8b404de41
click 3238bde1af35c3f73d34849ad4437033 "https://iolanta.tech/matches"
class 3238bde1af35c3f73d34849ad4437033 predicate
pkg_pypi_iolanta_mermaid-graph --- 44fc138a211015cfd7132826e6552473(["outputs"])--> https___iolanta_tech_datatypes_mermaid
click 44fc138a211015cfd7132826e6552473 "https://iolanta.tech/outputs"
class 44fc138a211015cfd7132826e6552473 predicate
classDef predicate fill:transparent,stroke:transparent,stroke-width:0px;
Stage 1: Which facets can output a visualization of this iolanta:OutputDatatype?
To ascertain that, Iolanta will execute get-query-to-facet.sparql binding $as_datatype to iolanta:mermaid.
SELECT ?facet ?match WHERE {
?facet
iolanta:matches ?match ;
iolanta:outputs $as_datatype .
}
| facet match |
|---|
pkg:pypi/iolanta#mermaid-graph ASK WHERE { GRAPH $this { ?s ?p ?o } } |
pkg:pypi/iolanta#mermaid-graph ASK WHERE { $this iolanta:has-sub-graph ?subgraph } |
For each facet returned, Iolanta evaluates its ASK pattern binding $this to the target node. The mermaid facet matches with:
ASK WHERE {
GRAPH $this { ?s ?p ?o }
}
⇒ which evaluates to: ✅ True
- This matches because
facet.yamlldis interpreted by Iolanta as an RDF named graph when loading this file; - We won't delve into
iolanta:has-sub-graph, that's rather sketchy right now.
Stage 2: Resolve Facet
We'll not delve into this here, but just to mention:
- The
pkg:URI has a straightforward mapping to a Python object, - which is a Python class addressable as
iolanta.mermaid.facet:Mermaid.
Where from is this class?
This particular class is bundled with Iolanta, but facet classes can also come with other Python packages — Iolanta plugins.
Here's an abridged version of the class:
class Mermaid(Facet[str]):
"""Mermaid diagram."""
# …
def construct_mermaid_for_graph(self, graph: URIRef) -> Iterable[MermaidScalar]:
"""Render graph as mermaid."""
rows = self.stored_query('graph.sparql', this=graph)
# …
def show(self) -> str:
"""Render mermaid diagram."""
# …
return str(Diagram(children=[*direct_children, *subgraphs]))
Full version: see the Mermaid facet.
Now, facet class is able to run arbitrary SPARQL queries against the graph, retrieving the information necessary for the visualization.
Stage 3: Retrieving Graph Data
In particular, the Mermaid facet executes graph.sparql to fetch all triples in the named graph, substituting $this to the URI of facet.yamlld:
SELECT * WHERE {
GRAPH $this {
?s ?p ?o .
}
}
Triples for facet.yamlld (too many of them)
| this s p o |
| --- --- --- --- |
| file:///home/runner/work/iolanta/iolanta/docs/blog/knowledge-graph-assignment/facet.yamlld iolanta:Facet http://www.w3.org/2000/01/rdf-schema#label Facet |
| file:///home/runner/work/iolanta/iolanta/docs/blog/knowledge-graph-assignment/facet.yamlld iolanta:Facet http://www.w3.org/2000/01/rdf-schema#comment A Facet is a visualization component that transforms RDF nodes into human-readable formats.
Facets are the core mechanism by which Iolanta makes Linked Data accessible to users.
Each facet is designed to handle specific types of RDF nodes and render them appropriately
for different output formats (terminal, web, etc.). |
| file:///home/runner/work/iolanta/iolanta/docs/blog/knowledge-graph-assignment/facet.yamlld iolanta:Facet http://www.w3.org/1999/02/22-rdf-syntax-ns#type http://www.w3.org/2002/07/owl#Class |
These triples are formatted as Mermaid nodes and edges by the facet, producing the diagram, which:
- Either gets printed in the console, and you can save it to a file or copy it,
- Or embedded into software which Iolanta is working with.
Other examples
While rendering Linked Data, Iolanta will try to fetch references from the Web to other pieces of Linked Data. Thus, we are trying to get the most complete visualization.
Conclusion
The Iolanta ontology provides a framework for Linked Data visualization and browsing with:
- Clear domain focus on semantic web usability
- Well-structured RDF/OWL implementation
- Professional URI strategy following Linked Data best practices
- Full SPARQL support with real-world applications
- Integration with existing semantic web resources