SHACL Core: Node Shapes and Property Shapes

SHACL Core: Node Shapes and Property Shapes

Introduction to SHACL Core

While Web Ontology Language (OWL) excels at inferring new knowledge under the Open World Assumption (OWA), it is fundamentally ill-suited for structural data validation. If an OWL restriction states a Person must have exactly one birth date, and a specific Person instance in your graph has none, an OWL reasoner does not throw an error. Instead, it assumes the birth date exists but is currently unknown.

The Shapes Constraint Language (SHACL) was designed to solve this exact problem. Operating under the Closed World Assumption (CWA), SHACL evaluates the data graph exactly as it is. If a required property is missing, SHACL flags a validation violation. At the heart of this validation framework are two primary constructs: Node Shapes and Property Shapes.

Node Shapes vs. Property Shapes

In SHACL, validation rules are grouped into “shapes” that are evaluated against “focus nodes” in your data graph.

  • Node Shapes (sh:NodeShape): Define constraints directly on the focus node itself. For example, you might use a Node Shape to assert that a specific node must be an IRI, or that its URI must match a specific regular expression pattern.
  • Property Shapes (sh:PropertyShape): Define constraints on the values reached by following a specific path (usually a predicate) from the focus node. Property shapes are typically nested within or linked to Node Shapes using the sh:property predicate.

Consider the following Turtle example defining a basic shape for a Person:

@prefix sh: .

@prefix ex: .

@prefix xsd: .

ex:PersonShape

a sh:NodeShape ;

sh:targetClass ex:Person ;

sh:property [

sh:path ex:age ;

sh:datatype xsd:integer ;

sh:minCount 1 ;

] .

In this snippet, ex:PersonShape is the Node Shape. The blank node [ sh:path ex:age ... ] is the Property Shape, dictating the rules for the ex:age property when attached to a Person.

Targeting Mechanisms

Before SHACL can validate a node, it needs to know which nodes to look at. SHACL Core provides four built-in targeting mechanisms (sh:target...) to select focus nodes:

  1. sh:targetNode: Targets specific, explicitly named individual RDF terms (IRIs or literals). Useful for validating a single, highly critical resource.
  2. sh:targetClass: Targets all instances of a specified class, including instances of its subclasses. This is the most common targeting mechanism in enterprise ontologies.
  3. sh:targetSubjectsOf: Targets any node that acts as a subject in a triple with the specified predicate, regardless of its rdf:type.
  4. sh:targetObjectsOf: Targets any node that acts as an object in a triple with the specified predicate.

Property Constraints: Cardinality and Value Restrictions

Once a focus node is targeted, Property Shapes define what the outgoing data must look like.

Cardinality and the “Missing Property Trap”

Cardinality is controlled via sh:minCount and sh:maxCount. A critical caveat for knowledge engineers learning SHACL is the “Missing Property Trap.”

If you define a property shape with sh:datatype xsd:string but the focus node simply does not have that property, the validation will pass. SHACL evaluates value constraints only on existing value nodes. To make a property mandatory, you must explicitly declare sh:minCount 1.

Value Types: sh:datatype vs. sh:class

A remarkably common syntax error in SHACL modeling is confusing datatypes with classes.

  • sh:datatype restricts literal values to specific XML Schema types (e.g., xsd:string, xsd:integer). Never use this for IRIs.
  • sh:class restricts values to instances of a specific RDF/OWL class (e.g., ex:Organization). Never use this for literals.
  • sh:nodeKind restricts the fundamental node type (e.g., sh:IRI, sh:Literal, sh:BlankNode).

Value Ranges and Enumerations

SHACL allows fine-grained restrictions on the actual data values:

  • Numeric Ranges: sh:minInclusive, sh:maxInclusive, sh:minExclusive, and sh:maxExclusive restrict numeric boundaries.
  • Enumerations: sh:in restricts values to a specific RDF list of allowed terms (e.g., a predefined list of status codes).
  • String Patterns: sh:pattern enforces regular expressions on string representations, which is invaluable for validating formats like emails, phone numbers, or standardized identifiers.

Closed Shapes and Strict Validation

By default, SHACL validation is “open.” It ignores any properties on a focus node that are not explicitly declared in the shape. However, in strict enterprise environments, you often want to ensure that only approved properties are used.

Setting sh:closed true on a sh:NodeShape triggers a violation if the focus node has any properties not defined in the shape’s sh:property paths.

When closing a shape, you must account for standard metadata properties. For instance, every instance has an rdf:type, but you rarely define a property shape for it. You must explicitly whitelist these using sh:ignoredProperties:

ex:StrictPersonShape

a sh:NodeShape ;

sh:targetClass ex:Person ;

sh:closed true ;

sh:ignoredProperties ( rdf:type ) ;

sh:property [

sh:path ex:name ;

sh:datatype xsd:string ;

] .

The Subclass Pollution Caveat

Be highly cautious when combining sh:closed true with sh:targetClass. Because sh:targetClass automatically targets subclasses, a closed shape defined on a superclass will trigger validation failures on subclass instances if those subclasses introduce their own valid properties. For example, if Employee (a subclass of Person) adds ex:employeeId, validating an Employee against the closed PersonShape will fail because ex:employeeId is not defined on the PersonShape.

Validation vs. Inference Environments

Finally, remember that SHACL validates the active data graph exactly as it is fed to the engine. If your data relies heavily on OWL reasoning (e.g., relying on rdfs:subPropertyOf to group predicates, or transitive properties), SHACL will fail to validate those relationships unless an inference engine is run before validation.

When using triple stores like GraphDB or frameworks like Apache Jena, you must ensure that the validation context either includes the materialized inferred triples or that the SHACL engine is explicitly configured to query the inferred graph rather than just the base graph. SHACL itself does not infer new triples; it strictly enforces the rules of your semantic model.