SHACL
Generate SHACL shapes, serialized as N-Triples or Turtle.
ohi get w3c/prov-oohi linkml to shacl --open --to prov-o.shacl.ttl prov-o.linkml.yamlimport ohi_linkml
with ohi_linkml.load_file("prov-o.linkml.yaml") as schema: output = schema.shacl(open=True)import { readFileSync } from "node:fs";import { LinkML } from "@neverblink/linkml";
const yaml = readFileSync("prov-o.linkml.yaml", "utf8");const { view, report } = LinkML.loadFromString(yaml, {});if (!view) throw new Error(JSON.stringify(report));const output = view.shacl({ open: true });import eu.neverblink.linkml.generator.options.ShaclGeneratorOptionsimport eu.neverblink.linkml.generator.shacl.ShaclGeneratorimport eu.neverblink.linkml.schemaview.{SchemaIssues, SchemaView}
val loaded = SchemaView.loadSchemaViewFromUri("prov-o.linkml.yaml")given SchemaView = SchemaIssues.orThrow(loaded)val output = ShaclGenerator().serialize( ShaclGeneratorOptions(open = true),)#include <stddef.h>#include "ohi_linkml.h"
linkml_init_threads();char *report = NULL, *error = NULL;long long schema = linkml_load_file("prov-o.linkml.yaml", NULL, &report, &error);char *output = linkml_shacl(schema, "{\"open\": true}", &error);linkml_free(output);linkml_free(report);linkml_free(error);linkml_close(schema);Options
Section titled “Options”formatRdfFormatdefault ttl--formatThe RDF serialization of the output.
ttlTurtle, with prefixes and pretty-printed.ntN-Triples, one statement per line.
only_classes_from_root_schemabooleandefault false--only-classes-from-root-schemaScala onlyClassesFromRootSchemaWhether to include only the classes and enums of the root schema. This is useful for one output file per schema file, without the imported classes in each.
openbooleandefault false--openWhether every shape is open, allowing properties beyond the ones in the schema. Shapes of classes whose extra_slots allows them are open anyway.
Class hierarchy
Section titled “Class hierarchy”The SHACL generator gives a slot whose range is a class an sh:class constraint with that class.
SHACL checks sh:class and sh:targetClass with the rdfs:subClassOf triples in the data graph.
So for a value typed with a subclass to conform, add the class hierarchy to the data graph, for example the output of the RDFS generator:
pyshacl -s shapes.ttl -e schema-rdfs.ttl data.ttlSubclasses from other schemas are accepted this way too.
Type designators
Section titled “Type designators”In RDF, rdf:type holds the type designator, so the SHACL generator emits no property shape for the designator slot.
A slot whose range has a type designator gets sh:class with that class, like any other class range.
Open shapes for classes with subclasses
Section titled “Open shapes for classes with subclasses”With the class hierarchy in the data graph, the shape of a class also checks the instances of its subclasses, which can have more slots.
So the shape of a class with subclasses is open (sh:closed false).
Limitations
Section titled “Limitations”A subclass can’t accept data that the shape of its parent class or mixin rejects. For example, if a subclass makes a slot multivalued, its instances with more than one value fail the shape of the parent, where the slot is single-valued.