SHACL Validation and OWL Generation in Semantica: Technical Implementation Guide

Semantica's ontology subsystem provides integrated SHACL validation through the OntologyValidator class and flexible OWL generation via OWLGenerator, enabling automated structural validation and RDF serialization with optional rdflib integration and string-templating fallbacks.

The semantica-agi/semantica repository implements a comprehensive ontology management system that bridges raw Python data structures with semantic web standards. This article examines how the library handles SHACL validation and OWL generation through dedicated modules that parse, validate, and serialize ontology structures using intermediate dictionary representations.

SHACL Validation Architecture

The validation layer enforces structural constraints on ontology graphs using the W3C SHACL standard.

Building RDF and SHACL Graphs

In semantica/ontology/ontology_validator.py, the OntologyValidator class orchestrates the validation workflow. The _run_pyshacl method (lines 48‑73) uses rdflib to parse both the data graph (your ontology instance) and the shapes graph (constraint definitions).

You can supply custom SHACL shapes or rely on the internal SHACLGenerator class to derive constraints automatically from the ontology schema. The validator loads graphs via rdflib.Graph().parse and invokes pyshacl.validate to execute the conformance check.

Parsing Validation Results

Result extraction occurs in lines 106‑141, where the engine iterates over results_graph.subjects(SH.ValidationResult) to identify violations. For each result, the parser extracts:

  • Focus node and path (the specific property or individual in violation)
  • Severity level (violation, warning, or info)
  • Human-readable message and offending value

Lines 150‑165 fetch real constraint parameters—such as minCount, maxCount, datatype, and class—from the shapes graph to enrich the violation context.

Structured Violation Reports

The SHACLValidationReport class (lines 60‑77) aggregates validation outcomes into three categorized lists:

  • violations: Critical constraint failures
  • warnings: Non-critical issues
  • infos: Advisory notices

Each entry is a SHACLViolation object containing structured metadata. The explain_violations method (lines 82‑123) generates templated English explanations—such as "Node is missing required property "—populating the explanation field for human-readable output.

For convenience, the validate_ontology() function (lines 269‑288) wraps instantiation and execution, returning a plain dictionary summarizing validity, consistency, satisfiability, and collected messages.

OWL Generation Pipeline

The OWL module transforms Python ontology dictionaries into standard RDF serializations.

Rdflib Integration and Fallback Mechanisms

The OWLGenerator class in semantica/ontology/owl_generator.py detects rdflib availability at import time using the HAS_RDFLIB flag (lines 39‑46). If rdflib is absent, the module logs a warning (lines 90‑94) and falls back to lightweight string templating.

The generator provides two implementation paths:

  • _generate_with_rdflib (lines 110‑180): Full-featured graph construction using rdflib’s Graph API
  • _generate_basic (lines 300‑375): Pure Python string concatenation producing valid Turtle syntax

Namespace and IRI Management

The _get_generation_namespace_manager method (lines 77‑86) constructs a NamespaceManager anchored to the ontology’s base URI. This manager mints IRIs via generate_class_iri and generate_property_iri, ensuring consistent identifier generation across both OWL and SHACL generation workflows.

Class and Property Emission

When using rdflib, the generator emits standard OWL/RDFS triples:

  • Classes: rdf:type owl:Class, optional rdfs:label, rdfs:comment, and rdfs:subClassOf relationships
  • Object Properties: rdf:type owl:ObjectProperty with rdfs:domain and rdfs:range
  • Datatype Properties: rdf:type owl:DatatypeProperty linked to XSD or custom datatypes

The fallback implementation reproduces these triples using deterministic string formatting for environments without heavy dependencies.

Serialization and Export

The generate_owl method supports multiple RDF formats: Turtle, RDF/XML, JSON-LD, N-Triples, and N3. It returns either a serialized string or an rdflib.Graph object (lines 218‑229) depending on the format parameter.

For file output, export_owl (lines 315‑362) handles directory creation via ensure_directory and writes the serialized content to disk, making it suitable for build pipelines or deployment workflows.

Integration in the Generation Pipeline

The high-level OntologyGenerator class (in semantica/ontology/ontology_generator.py) orchestrates a six-stage pipeline that concludes with validation. At lines 197‑210, after constructing class and property structures, it invokes:

validation_result = self.validator.validate(ontology)
ontology["validation"] = {
    "valid": validation_result.valid,
    "consistent": validation_result.consistent,
    "satisfiable": validation_result.satisfiable,
    "errors": validation_result.errors,
    "warnings": validation_result.warnings,
}

This ensures every generated ontology undergoes both SHACL structural validation and symbolic consistency checking (via HermiT/Pellet placeholders) before export to downstream formats.

Practical Code Examples

Validating an Ontology with SHACL

from semantica.ontology import OntologyValidator

my_ontology = {
    "uri": "https://example.org/ontology/",
    "classes": [{"name": "Person", "uri": "https://example.org/ontology/Person"}],
    "properties": [
        {
            "name": "age",
            "type": "datatype",
            "range": "xsd:integer",
            "domain": ["Person"],
            "required": True,
        }
    ],
}

validator = OntologyValidator()
report = validator.validate(my_ontology)

# Access structured violations

print(report.summary())
report.explain_violations()
for v in report.violations:
    print(v.explanation)

Generating OWL Turtle Output

from semantica.ontology import OWLGenerator

owl_gen = OWLGenerator()

# Generate Turtle string

turtle_str = owl_gen.generate_owl(my_ontology, format="turtle")

# Or obtain rdflib Graph for manipulation

g = owl_gen.generate_owl(my_ontology)  # Returns Graph object

g.serialize(destination="ontology.ttl", format="turtle")

Complete Pipeline: Generation to Export

from semantica.ontology import OntologyGenerator, OWLGenerator

# 1. Generate from raw data

generator = OntologyGenerator(base_uri="https://example.org/ontology/")
raw_data = {
    "entities": [{"type": "Person", "name": "Alice"}],
    "relationships": [{"type": "hasFriend", "source": "Alice", "target": "Bob"}],
}
ontology = generator.generate_ontology(raw_data)

# 2. Validate (SHACL + symbolic)

validation = generator.validator.validate(ontology)
print("Valid?", validation.valid)

# 3. Export OWL

owl_gen = OWLGenerator()
owl_gen.export_owl(ontology, "output/ontology.ttl")

Summary

  • SHACL validation occurs in ontology_validator.py using OntologyValidator, which leverages pyshacl and rdflib to check conformance against shapes graphs, producing structured SHACLValidationReport objects with human-readable explanations.

  • OWL generation is handled by OWLGenerator in owl_generator.py, which supports multiple RDF serialization formats through rdflib or a lightweight string-templating fallback when dependencies are unavailable.

  • Namespace management is centralized via _get_generation_namespace_manager, ensuring consistent IRI generation for both validation and export workflows.

  • Pipeline integration means every ontology created through OntologyGenerator automatically undergoes SHACL validation and consistency checking before serialization, ensuring quality at the point of generation.

Frequently Asked Questions

How does Semantica handle missing rdflib dependencies?

When rdflib is not installed, OWLGenerator detects this via the HAS_RDFLIB flag (lines 39‑46 of owl_generator.py) and routes execution to _generate_basic (lines 300‑375), which constructs valid Turtle syntax through string concatenation rather than graph manipulation.

What specific constraint parameters does SHACL validation extract?

According to lines 150‑165 of ontology_validator.py, the validator extracts real constraint parameters including minCount, maxCount, datatype, and class from the shapes graph to populate SHACLViolation objects with detailed context for error messages.

Can I validate an ontology without generating OWL output?

Yes. The OntologyValidator class operates independently of the OWLGenerator. You can instantiate OntologyValidator directly and call validate() or _run_pyshacl() on any ontology dictionary conforming to the expected schema, without triggering RDF serialization.

What serialization formats does the OWL generator support?

As implemented in lines 218‑229 of owl_generator.py, the generator supports Turtle, RDF/XML, JSON-LD, N-Triples, and N3 formats. The export_owl method handles file I/O and directory creation automatically.

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 →