How to Implement SHACL Validation and OWL Ontology Generation in Semantica

Semantica provides a composable pipeline for building SHACL shapes from OWL ontologies, validating RDF graphs against those shapes, and exporting ontologies back to OWL format.

The semantica-agi/semantica repository offers a clean Python API for ontology engineering that bridges SHACL validation and OWL ontology generation through shared data structures. The core workflow uses three primary modules: SHACLGenerator for shape creation, _run_pyshacl for validation, and OWLExporter for ontology serialization.

Understanding the Core Architecture

Semantica separates concerns across three layers:

Layer Module Path Purpose
Shape Generation semantica/ontology/ontology_generator.py Convert ontology dictionaries to SHACL constraints
Validation Engine semantica/ontology/ontology_validator.py Execute SHACL validation against RDF data
Export Utilities semantica/export/owl_exporter.py Serialize ontologies to OWL Turtle

This design ensures that your SHACL shapes and OWL output remain synchronized because both consume the same dictionary-based ontology format.

Generating SHACL Shapes from OWL Ontologies

The SHACLGenerator class in semantica/ontology/ontology_generator.py implements a six-stage pipeline that transforms OWL-style dictionaries into executable SHACL graphs:

  1. Build a fast class index for efficient lookup
  2. Create a NodeShape for every OWL class definition
  3. Attach PropertyShape objects based on property type (literal or object)
  4. Propagate inherited shapes with cycle-safe traversal
  5. Apply a quality tier (basic, standard, or strict)
  6. Serialize to Turtle, JSON-LD, or N-Triples

The generator supports quality tiers that control shape strictness. The strict tier produces closed node shapes (closed=True), preventing graphs from containing properties not explicitly defined in the ontology.

from semantica.ontology.ontology_generator import SHACLGenerator

# Define an ontology as a Python dictionary

ontology = {
    "namespace": {"base_uri": "https://example.org/"},
    "classes": [
        {"name": "Person", "label": "Person"},
        {"name": "Employee", "label": "Employee", "superclass": "Person"},
    ],
    "properties": [
        {
            "name": "name",
            "type": "literal",
            "domain": ["Person"],
            "range": ["xsd:string"],
        },
        {
            "name": "worksFor",
            "type": "object",
            "domain": ["Employee"],
            "range": ["Company"],
        },
    ],
}

# Generate strict SHACL shapes

shacl_gen = SHACLGenerator(quality_tier="strict")
shacl_graph = shacl_gen.generate(ontology)
shacl_turtle = shacl_gen.serialize(shacl_graph, format="turtle")
print(shacl_turtle)

Set include_inherited=True when instantiating SHACLGenerator to automatically expand shapes with constraints from parent classes.

Validating RDF Graphs Against SHACL Shapes

Validation is handled by _run_pyshacl in semantica/ontology/ontology_validator.py. This function wraps the pyshacl library and provides structured error reporting through SHACLViolation and SHACLValidationReport objects.

The _run_pyshacl function:

  • Loads data graphs and SHACL shapes using rdflib
  • Executes pyshacl.validate with inference="none" and abort_on_first=False
  • Parses ValidationResult triples into typed violation objects
  • Aggregates results into a report with conformance status and explanations

If pyshacl is not installed, the function raises an ImportError directing users to install semantica[shacl] extras.

from semantica.ontology.ontology_validator import _run_pyshacl
from semantica.export.rdf_exporter import RDFExporter

# Serialize RDF data for validation

rdf_exporter = RDFExporter()
data_graph = rdf_exporter.export_to_rdf(
    {
        "triples": [
            ("https://example.org/Alice", "rdf:type", "ex:Person"),
            ("https://example.org/Alice", "ex:name", '"Alice"^^xsd:string'),
        ]
    },
    format="turtle",
)

# Validate against previously generated SHACL

report = _run_pyshacl(data_graph, shacl_turtle)
print(report.summary())

if not report.conforms:
    for violation in report.violations:
        print(violation.explanation)

The SHACLValidationReport.summary() method returns conformance status, while each SHACLViolation provides a human-readable explanation of the constraint failure.

Exporting Ontologies to OWL Format

The OWLExporter class in semantica/export/owl_exporter.py converts the same dictionary-based ontologies back to OWL Turtle. Because exporters share namespace handling utilities, your OWL output uses identical prefixes to your SHACL shapes.

from semantica.export.owl_exporter import OWLExporter

# Export the ontology dictionary to OWL

owl_exporter = OWLExporter(ontology_uri="https://example.org/ontology/")
owl_turtle = owl_exporter.export_owl(ontology)
print(owl_turtle)

The ontology_uri parameter establishes the base IRI for the OWL document, ensuring proper identity semantics for imported ontologies.

Complete Integration Workflow

Combine all three components for a round-trip ontology engineering pipeline:

from semantica.ontology.ontology_generator import SHACLGenerator
from semantica.ontology.ontology_validator import _run_pyshacl
from semantica.export.owl_exporter import OWLExporter
from semantica.export.rdf_exporter import RDFExporter

# 1. Define your ontology

ontology = {...}  # Your dictionary specification

# 2. Generate SHACL shapes for governance

generator = SHACLGenerator(quality_tier="strict")
shacl = generator.serialize(generator.generate(ontology), format="turtle")

# 3. Validate incoming data

rdf_exporter = RDFExporter()
data = rdf_exporter.export_to_rdf(data_dict, format="turtle")
report = _run_pyshacl(data, shacl)

# 4. Export canonical OWL for documentation

owl = OWLExporter(ontology_uri="https://example.org/").export_owl(ontology)

Source File Reference

File Lines Contains
semantica/ontology/ontology_generator.py 56-67 SHACLGenerator class definition and pipeline
semantica/ontology/ontology_validator.py 38-84 _run_pyshacl validation implementation
semantica/export/owl_exporter.py 41-57 OWLExporter class and export_owl() method
semantica/export/rdf_exporter.py — RDFExporter for data graph serialization

Summary

  • SHACL shapes are generated from dictionary ontologies using SHACLGenerator with configurable quality_tier settings
  • SHACL validation executes through _run_pyshacl, which parses pyshacl results into structured SHACLViolation objects
  • OWL export uses OWLExporter with shared namespace handling for consistent prefixes
  • All three components consume the same ontology dictionary format, enabling synchronized governance and documentation

Frequently Asked Questions

What dependencies are required for SHACL validation?

Install the optional [shacl] extras to enable validation: pip install semantica[shacl]. This installs pyshacl and rdflib. Without these, _run_pyshacl raises an ImportError with installation instructions.

How do quality tiers affect generated SHACL shapes?

The quality_tier parameter controls shape strictness: basic produces open shapes with minimal constraints, standard adds cardinality and type checks, and strict generates closed node shapes (sh:closed true) that reject undefined properties entirely.

Can I validate large RDF graphs efficiently?

The _run_pyshacl function uses abort_on_first=False by default, collecting all violations rather than failing fast. For large graphs, consider streaming validation or partitioning your data graph, as the current implementation loads the full graph into memory via rdflib.

Does Semantica support OWL-to-SHACL round-tripping?

Yes, but through the dictionary format as intermediary. Feed the same ontology dictionary to both SHACLGenerator and OWLExporter to ensure your shapes and OWL documentation remain synchronized. Direct parsing of external OWL files into the internal dictionary format is not described in the current codebase.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →