SHACL (Shapes Constraint Language) is an RDF vocabulary for describing RDF graph structures. The accompanying primer introduces shapes. This document describes an implementation of SHACL using SPARQL functional properties and SPIN rules, including extensions defined in SPARQL to be applied to focus nodes.

This document also describes a standard RDF structure for reporting constraint violations. This can be triggred by failures encountered while matching a shape against a focus node, or by global constraints which are additional SPARQL queries invoked at validation time.

Proposal to RDF Data Shapes WG

SPIN templates provide a functional language in the form of labeled RDF rules. It allows one to:

Additionally, this specification leverages functional properties (AKA property functions, magic properties), such as those implemented in Jena, to provide functionality such as recursion not defined in SPARQL.

Extension to SHACL Core

A SHACL shape includes an optional set of extension conditions. The SPARQL extension to SHACL defines one such extension, with the extension language name sh:sparql.

General Shape Constraints (sh:constraint)

The property sh:constraint provides the most general mechanism to associate a constraint with a shape. The values of this property must be local constraints, i.e. they MUST reference a focus node. Note that the property sh:property SHOULD be used instead of sh:constraint if the constraint is a sh:PropertyConstraint. The property sh:inverseProperty SHOULD be used instead of sh:constraint if the constraint is a sh:InversePropertyConstraint.

SHACL supports two types of general shape constraints:

The following example assumes that there is a high-level template called myt:DisjointPropertiesConstraint that takes two arguments myt:property1 and myt:property2. The intent of that example is to state that the values of the properties ex:father and ex:mother must be disjoint.

@prefix myt: <http://example.org/myTemplates#> .

ex:GeneralTemplateConstraintExampleShape
	a sh:Shape ;
	sh:constraint [
		a myt:DisjointPropertiesConstraint ;
		myt:property1 ex:father ;
		myt:property2 ex:mother ;
	] .

The following example illustrates the definition of a local constraint based on a SPARQL query. The property sh:sparql is used to point at a SELECT query as explained in a later section. Note that the variable ?this is used to reference the focus node.

ex:GeneralSPARQLConstraintExampleShape
	a sh:Shape ;
	sh:constraint [
		sh:message "The value of property2 cannot be smaller than the value of property1." ;
		sh:predicate ex:property2 ;
		sh:sparql """
			SELECT ?this (?this AS ?subject) (?value2 AS ?object)
			WHERE {
				?this ex:property1 ?value1 .
				?this ex:property2 ?value2 .
				FILTER (?value2 < ?value1) .
			}
			""" ;
	] .

In the example above, SPARQL is provided as the only native executable. However, additional executables such as JavaScript may be provided based on other sets of properties like ex:javaScript.

Templates

Templates can be used to encapsulate and parameterize executable bodies based on arguments. Templates can be instantiated anywhere where a native constraint may appear (for example, at sh:constraint). SHACL includes several templates that were deemed to be of general use, including the property constraint templates. Such templates form a high-level vocabulary that may be directly interpreted ("hard-coded") without reliance on their executable bodies.

Constraint templates are represented as IRI nodes that are instances of the class sh:ConstraintTemplate. SHACL also includes a more general superclass sh:Template that may be used for other kinds of templates (rules, stored queries etc). Well-defined, non-abstract templates MUST provide at least one executable body property using sh:sparql. The following example illustrates the definition of a local constraint template based on a SPARQL query.

ex:ExampleTemplate
	a sh:ConstraintTemplate ;
	rdfs:label "Example Template" ;
	rdfs:comment "Verifies that the given focus node (?this) has at least one value for the argument property (?argProperty)." ;
	sh:argument [
		sh:predicate ex:argProperty ;
		sh:valueType rdf:Property ;
	] ;
	sh:labelTemplate "The property {?argProperty} must have at least one value" ;
	sh:sparql """
		SELECT ?this (?this AS ?subject) (?argProperty AS ?predicate) 
		WHERE {
			FILTER NOT EXISTS { ?this ?argProperty ?anyValue }
		}
		""" .

The following sections introduce details of the properties that such templates may have.

Template Arguments

The arguments of a template are attached via the property sh:argument. Each argument must be an instance of sh:Argument. The rdf:type triple of the argument can be omitted if it is a blank node with an incoming sh:argument triple.

Each sh:Argument MUST have exactly one value for the property sh:predicate. The values of sh:predicate must be IRIs. The local name of a IRI is defined as the longest NCNAME at the end of the IRI, not immediately preceeded by the first colon in the IRI. The local names of the values of sh:predicate must match the following conditions (to ensure a correct mapping from arguments into SPARQL variables is possible):

An sh:Argument may have its property sh:optional set to true to indicate that the argument is not mandatory.

An sh:Argument may declare a default value via sh:defaultValue. For non-optional arguments, the engine must use the declared default value for template instances that do not define a value for this argument.

An sh:Argument may declare one value for the property sh:valueType. This can be used to communicate the expected value type of the argument in template instances. Some implementations MAY use this information to prevent the execution of a template with invalid arguments, and to signal errors.

sh:labelTemplate

The property sh:labelTemplate can be used to suggest how instances of the template shall be rendered to humans. The sh:labelTemplate must be a string that can reference the arguments using the syntax {?varName}, where varName is the name of the SPARQL variable that corresponds to the argument. These {?...} blocks SHOULD be substituted with the actual values used in the template instance. In SPARQL-based systems, the function sh:label may be used to expand those label templates into consumable strings.

Profiles

A Profile is a set of shape templates. Profiles can be used to define controlled sub-dialects of SHACL, e.g. with desirable complexity. Tools may decide to only support certain profiles, for example so that they can hard-code and optimize certain algorithms. Since Profiles are entirely based on templates, native constraints such as those in SPARQL are outside of their expressivity.

The class sh:Profile is used to represent SHACL profiles. The property sh:member links a sh:Profile with the templates that are in the profile. The following example defines a profile consisting of the two SHACL templates for min/max cardinality and value shape, as well as their shared superclass (which defines the sh:predicate property) and their shared subclass sh:PropertyConstraint that is directly instantiated.

ex:MyProfile
	a sh:Profile ;
	sh:member sh:AbstractPropertyConstraint ;
	sh:member sh:AbstractCountPropertyConstraint ;
	sh:member sh:AbstractValueShapePropertyConstraint ;
	sh:member sh:PropertyConstraint .

In the example above, the profile includes only the properties from the enumerated template classes. Sibling template classes such as sh:AbstractAllowedValuesPropertyConstraint are outside of the profile, which means that sh:allowedValues would be out of scope for this profile.

SHACL includes a profile called sh:CoreProfile that includes all property constraint templates as well as disjunctive constraints.

Global Constraints

While Shapes define constraints centered around focus nodes, global constraints may define arbitrary graph-level restrictions. SHACL can represent two kinds of global constraints:

Global Native Constraints

Similar to native general shape constraints, native global constraints must have at least one executable body that instructs execution engines how to compute constraint violations. The current version of SHACL only includes one such language, SPARQL, identified by the property sh:sparql. Details of the evaluation rules for SPARQL are defined in its corresponding section.

The following example illustrates the syntax for a global native constraint based on SPARQL.

ex:ExampleGlobalSPARQLConstraint
	a sh:GlobalNativeConstraint ;
	sh:message "There needs to be at least one instance of ex:SomeClass." ;
	sh:sparql """
		SELECT (ex:SomeClass AS ?root)
		WHERE {
			FILTER NOT EXISTS { ?any rdf:type ex:SomeClass } .
		}
		""" .

Global Template Constraints

Global constraints can be expressed as instances of the class sh:ConstraintTemplate that are also subclass of sh:GlobalConstraint. While this version of the SHACL vocabulary does not include any pre-defined global constraint templates, anyone can define and publish such templates with a given IRI.

The following example illustrates the syntax for a global template constraint and the template that it instantiates. Note that the constraint does not need to have the explicit type sh:GlobalConstraint because it is an instance of the template ex:ExampleGlobalConstraintTemplate which is declared as a subclass of sh:GlobalTemplateConstraint.

ex:ExampleGlobalTemplateConstraint
	a ex:ExampleGlobalConstraintTemplate ;
	ex:exampleArgument ex:SomeClass .
	
ex:ExampleGlobalConstraintTemplate
	a sh:ConstraintTemplate ;
	rdfs:subClassOf sh:GlobalTemplateConstraint ;
	sh:argument [
		sh:predicate ex:exampleArgument ;
		sh:valueType rdfs:Class ;
		rdfs:label "The class that needs to have at least one instance." ;
	] ;
	sh:message "There needs to be at least one instance of the given class" ;
	...

Supported Operations

This section enumerates the basic operations that complete SHACL engines SHOULD support. The specification does not prescribe how these operations are exposed to the user of a SHACL system. The following table provides an overview of the operations and how they depend on each other.

Operation Depends On Description
validateConstraint Validates a single constraint
validateNodeAgainstShape validateConstraint Validates a given node against a given shape
validateNode validateNodeAgainstShape Validates a given node against the shapes derived from the graph
validateGraph validateNode, validateConstraint Validates all nodes in a graph, including global constraints

All operations produce constraint violations. For the sake of this specification, we assume that the constraint violations are represented as instances of sh:ConstraintViolation that are added to a result graph that is known to each operation for the duration of its execution. Actual implementations may use different data structures and result formats and input and output to these operations.

All operations have an implicit argument, which is a data set with a default named graph. Details of this need to be fleshed out, pending design decisions on general graph management.

Shape Selection

Some operations on SHACL graphs, such as validateNode and validateGraph rely on in-graph information to determine which nodes need to be evaluated against which shapes. This section describes the two currently supported shape selection properties.

There are multiple proposals on how to associate resources with their shapes, in particular based on rdf:type or sh:nodeShape. The WG may chose to:
  • Only support one of these patterns
  • Always support both of these patterns
  • Support both of these patterns, allowing them to be switched on or off individually
  • Support a more general mechanism that allows arbitrary selectors
Also we need to agree on terminology, e.g. Shape Selection vs Shape Mapping

Shape Selection based on rdf:type

RDF Schema and OWL provide a well-established framework to model domains in terms of classes and instances. A lot of existing data is already represented using these languages. In this shape selector, the IRIs of classes double as shape definitions, i.e. it is possible to directly attach constraints at the IRI of a class. The property rdf:type is used to determine which shapes a given node needs to fulfill. Specialization between shapes is expressed via rdfs:subClassOf. This pattern is illustrated in the following example.

ex:ExampleClass
	a rdfs:Class ;
	sh:constraint [
		...
	] .

ex:ExampleInstance
	rdf:type ex:ExampleClass .

Shape Selection based on sh:nodeShape

In some application scenarios, there may be unwanted interactions between existing RDFS models and shapes. For example, an application may want to ensure that there is no interaction between shapes and RDFS/OWL inferencing. In those cases, users can declare shapes as instances of sh:Shape and use sh:nodeShape to point from a node to its shape(s). This pattern is illustrated in the following example.

ex:ExampleShape
	a sh:Shape ;
	sh:constraint [
		...
	] .

ex:ExampleInstance
	sh:nodeShape ex:ExampleShape .

validateConstraint

This operation evaluates a single constraint and produces constraint violations.

Argument Type Description
?constraint sh:Constraint The constraint to evalate
?focusNode rdfs:Resource (Optional) The focus node, if present.

This operation assumes that the ?constraint is either a native constraint or a template constraint.

validateNodeAgainstShape

This operation validates a single node against all constraints associated with a given shape.

Argument Type Description
?focusNode rdfs:Resource The focus node to validate
?shape sh:Shape The shape that has the constraints.
?minSeverity rdfs:Class The minimum severity class, e.g. sh:Error specifying which constraints to exclude/include.

Algorithm in pseudo-code:

forEach ?s := ?shape and its transitive super-shapes
	forEach ?constraint := (?s sh:constraint|sh:property|sh:inverseProperty|sh:argument ?constraint)
		if (declared sh:severity of ?constraint is at least ?minSeverity)
			validateConstraint(?constraint, ?focusNode)

validateNode

This operation validates a single node against all shapes associated with it, based on in-graph mappings.

Argument Type Description
?focusNode rdfs:Resource The focus node to validate
?minSeverity rdfs:Class The minimum severity class, e.g. sh:Error specifying which constraints to exclude/include.

Algorithm in pseudo-code:

forEach ?shape := (?focusNode sh:nodeShape|rdf:type ?shape)
	validateNodeAgainstShape(?focusNode, ?shape, ?minSeverity)

validateGraph

This operation validates a whole graph against global constraints and all shapes associated with it, based on in-graph mappings.

?minSeverity rdfs:Class The minimum severity class, e.g. sh:Error specifying which constraints to exclude/include.

Algorithm in pseudo-code:

forEach ?focusNode := (?focusNode sh:nodeShape|rdf:type ?anyShape)
	validateNode(?focusNode, ?minSeverity)

forEach ?constraint := instance of sh:GlobalConstraint
	if (declared sh:severity of ?constraint is at least ?minSeverity)
		validateConstraint(?constraint)

Functions

SHACL functions define operations that produce an RDF node based on arguments. Functions can be called within SPARQL queries to encapsulate complex logic of other SPARQL queries, or executable logic in other languages such as JavaScript. However, the general declaration mechanism for SHACL functions is independent from SPARQL.

Functions must be declared as instances of the class sh:Function. Well-defined, non-abstract functions MUST provide at least one executable body property using sh:sparql. The following example illustrates the definition of a function based on a SPARQL query.

# Example call: ex:exampleFunction(4, 3) returns 7
ex:exampleFunction
	a sh:Function ;
	rdfs:comment "Computes the sum of its two arguments ?arg1 and ?arg2." ;
	sh:returnType xsd:integer ;
	sh:argument [
		sh:predicate sh:arg1 ;
		sh:datatype xsd:integer ;
		rdfs:comment "The first operand" ;
	] ;
	sh:argument [
		sh:predicate sh:arg2 ;
		sh:datatype xsd:integer ;
		rdfs:comment "The second operand" ;
	] ;
	sh:sparql """
		SELECT (?arg1 + ?arg2 AS ?result)
		WHERE {
		}
		""" .

The following sections introduce details of the properties that such functions may have.

Function Arguments

The arguments of a function are attached to its sh:Function via the property sh:argument. Each argument must be an instance of sh:Argument. The rdf:type triple of the argument can be omitted if it is a blank node with an incoming sh:argument triple. Arguments are ordered, corresponding to the notation of function calls in SPARQL such as ex:exampleFunction(?arg1, ?arg2).

Each sh:Argument MUST have exactly one value for the property sh:predicate. The values of sh:predicate must be sh:arg1 for the first argument, sh:arg2 for the second argument, etc. Arguments are "inherited" from the superclasses of the function. For example if a superclass already declares sh:arg1 then subclasses may only define sh:arg2 etc.

Each sh:Argument may have its property sh:optional set to true to indicate that the argument is not mandatory. If an argument has been declared optional, then all succeeding arguments must also be declared optional.

Similar to Property Constraints, each sh:Argument may declare one value for the property sh:datatype or one value for the property sh:valueType. This can be used to communicate the expected value type of the argument in function calls. Some implementations MAY use this information to prevent the execution of a function with invalid arguments, and to signal errors.

sh:returnType

A function may declare a single return type via sh:returnType. This information may serve for documentation purposes, only. However, in some execution languages such as JavaScript, the declared sh:returnType may inform the engine how to cast a native value into an RDF value type.

sh:cachable

A sh:Function may have a property sh:cachable set to true. Functions that are marked as cachable MUST always return the same value for the same combination of arguments, regardless of the query graphs. Engines can use this information to cache and reuse previous function calls without repeatedly evaluating their executable body.

SPARQL-based Execution (sh:sparql)

The property sh:sparql is used to link constraints, templates and functions with an executable body in SPARQL. The values of sh:sparql must be string literals that can be parsed into syntactically valid SPARQL queries. Prior to parsing, a SHACL engine MUST add all prefix declarations from the defining graph into the beginning of the string. This means that the values of sh:sparql do not have to explicitly state any @prefix declarations for the prefixes used in the SPARQL query.

The following sections provide details on how sh:sparql is interpreted for constraints, templates and functions.

SPARQL-based Constraints

The SPARQL queries attached to a constraint via sh:sparql must be of the query form SELECT.

Binding the Focus Node in Local SPARQL Constraints (?this)

The SPARQL variable ?this has a special meaning in local constraints. When SPARQL constraints are executed then the variable ?this needs to be pre-bound to the focus node. (Need a pointer to what "pre-binding" means in this context)

Mapping of Result Variables to Constraint Violations

Each row of the result set produced by a SELECT query must be converted into one constraint violation blank node. The properties of those blank nodes are derived by the following rules, through a combination of result variables and by looking at properties attached to the constraint itself. In the following table, the host resource is assumed to be the constraint or template that has the executed sh:sparql query as one of its properties. The production rules are meant to be executed from top to bottom, so that the first bound value will be used.

Property Production Rules
rdf:type
  1. The value of sh:severity of the host resource
  2. sh:Error as default
sh:root
  1. The value of the variable ?root
  2. The value of the variable ?this
  3. The value of sh:root of the host resource
sh:subject
  1. The value of the variable ?subject
sh:predicate
  1. The value of the variable ?predicate
  2. The value of sh:predicate of the host resource
sh:object
  1. The value of the variable ?object
sh:message
  1. The value of the variable ?message
  2. The values of sh:message of the host resource. These values may reference any variable from the SELECT result variables via {?varName}. The {?varName} blocks SHOULD be substituted with suitable string representations of the values of said variables.
sh:source
  1. The host resource

The following example illustrates a constraint that flags warnings for all subjects that have a rdfs:label with the language tag "de".

ex:ExampleGlobalSelectConstraint
	a sh:GlobalNativeConstraint ;
	sh:message "Deutsch is verboten" ;
	sh:predicate rdfs:label ;
	sh:severity sh:Warning ;
	sh:sparql """
		SELECT (?subject AS ?root) ?subject ?object
		WHERE {
			?subject rdfs:label ?object .
			FILTER (lang(?object) = "de") .
		}
		""" .

ex:Resource1
	rdfs:label "Eins"@de ;
	rdfs:label "Zwei"@de ;
	rdfs:label "Trois"@fr .

Output created by the example above would be:

[
	a sh:Warning ;
	sh:subject ex:Resource1 ;
	sh:predicate rdfs:label ;
	sh:object "Eins"@de ;
	sh:message "Deutsch is verboten" ;
	sh:source ex:ExampleGlobalSelectConstraint ;
] .
[
	a sh:Warning ;
	sh:subject ex:Resource1 ;
	sh:predicate rdfs:label ;
	sh:object "Zwei"@de ;
	sh:message "Deutsch is verboten" ;
	sh:source ex:ExampleGlobalSelectConstraint ;
] .

Injecting Annotation Properties into Constraint Violations

It is possible to inject additional annotation properties into the blank nodes created for each row of the SELECT result sets. Any such property needs to be declared via a value of sh:resultAnnotation at the host node. The values of sh:resultAnnotation must be IRIs or blank nodes with the following properties:

Property Value type Count Description
sh:annotationProperty rdf:Property 1 (mandatory) The annotation property that shall be set
sh:annotationVarName xsd:string 0..1 The name of the SPARQL variable to take the values from
sh:annotationValue 0..unlimited Constant nodes that shall be used as values

If a sh:resultAnnotation defines a sh:annotationVarName then the engine must copy the bindings for the given variable into the constructed constraint violations for the same row.

The values of sh:annotationProperty MUST NOT be from the SHACL namespace, to avoid clashes with variables that are already produced by other means.

Here is a slightly complex example, illustrating the use of result annotations.

ex:LocalShapeWithPathViolationExample
	a sh:Shape ;
	sh:constraint [
		sh:resultAnnotation [
			sh:annotationProperty ex:time ;
			sh:annotationVarName "time"
		] ;
		sh:predicate ex:property2 ;
		sh:sparql """
				SELECT ?subject (?first AS ?object) ?message ?time
				WHERE {
					?this ex:property1 ?first .
					?subject ex:property2 ?first .
					FILTER isBlank(?value) .
					BIND (CONCAT("The ", "message.") AS ?message) .
					BIND (NOW() AS ?time) .
				}
			""" ;
	] .
	
ex:ExampleRootResource
	sh:nodeShape ex:LocalShapeWithPathViolationExample ;
	ex:property1 ex:ExampleIntermediateResource .

ex:ExampleValueResource
	ex:property2 ex:ExampleIntermediateResource .

Which produces the following error resource:

[
	a sh:Error ;
	sh:root ex:ExampleRootResource ;
	sh:subject ex:ExampleValueResource ;
	sh:predicate ex:property2 ;
	sh:object ex:ExampleIntermediateResource ;
	sh:message "The message." ;
	sh:source [ the blank node of the sh:constraint above ] ;
	ex:time "2015-03-27T10:58:00"^^xsd:dateTime ;  # Example
] .

SPARQL-based Templates

If a sh:Template has a value for sh:sparql, then the corresponding instances need to follow the same execution rules as outlined for SPARQL-based Constraints. The only difference is that the SPARQL queries need to be executed with additional pre-bound variables, derived from the arguments of the template. The names of those variables must match the local name of the argument predicates, including the arguments defined by any (transitive) superclasses of the template. For example, if an argument is represented with the predicate ex:myArgument then the variable ?myArgument must be pre-bound with the value of the argument in the template instance.

SPARQL-based Functions

If a sh:Function has a value for sh:sparql, then a SPARQL-based execution engine SHOULD execute the provided SPARQL query on the current data set. In this SPARQL query, the engine needs to pre-bind the variables ?arg1, ?arg2 etc based on the provided arguments of the function call. The SPARQL query must be of type ASK or SELECT. For ASK queries, the function's return value is the result of the ASK query execution. For SELECT queries, the function's return value is the first binding of the first result variable in the result set.

Some execution engines may ignore the specified sh:sparql query and rely on an alternative (possibly native) implementation instead, as long as the functions return the same values as the specified sh:sparql query. This can be used to optimize frequently needed functions. Some processors may even use the sh:sparql query to rewrite other SPARQL queries via inlining techniques.

SPARQL Functions in the SHACL Namespace

SPARQL-based SHACL engines MUST implement the following SPARQL functions.

sh:hasDatatype

The function sh:hasDatatype returns true if a given node (?arg1) is a literal that has a datatype that matches a given datatype (?arg2). The return type of this function is xsd:boolean.

Argument Value type Description
?arg1 Any node The node to validate
?arg2 rdfs:Datatype The datatype to match against
SPARQL DEFINITION
ASK {
	{
		FILTER isLiteral(?arg1) .
	} .
	BIND (datatype(?arg1) AS ?datatype) .
	FILTER ((?datatype = ?arg2) || (rdf:langString = ?datatype && ?arg2 = xsd:string)) .
}
sh:hasDatatype(42, xsd:decimal)             # false
sh:hasDatatype(42, rdfs:Literal)            # false
sh:hasDatatype(42, xsd:integer)             # true
sh:hasDatatype("string"@en, rdf:langString) # true
sh:hasDatatype("string"@en, xsd:string)     # true
sh:hasDatatype("string", xsd:string)        # true

sh:hasShape

The function sh:hasShape returns true if a given node (?arg1) matches a given shape (?arg2). The return type of this function is xsd:boolean.

Argument Value type Description
?arg1 Any IRI or blank node The node to validate
?arg2 sh:Shape or rdfs:Class The shape to match against

This function MUST perform constraint validation equivalent to the validateNodeAgainstShape operation. The function MUST return true if the operation returns no error-level constraint violations, false if any error-level constraint violations exist.

sh:hasNodeKind

The function sh:hasNodeKind can be used to verify whether a given node (?arg1) has the provided sh:NodeKind (?arg2). The return type of this function is xsd:boolean.

Argument Value type Description
?arg1 Any The node to test
?arg2 sh:NodeKind The node kind that ?arg1 is expected to have

The following table summarizes the values of the class sh:NodeKind together with their SPARQL definition.

NodeKind SPARQL Expression
sh:BlankNode isBlank(?node)
sh:IRI isIRI(?node)
sh:Literal isLiteral(?node)
SPARQL DEFINITION
ASK {
	FILTER ((isIRI(?arg1) && ?arg2 = sh:IRI) ||
		(isLiteral(?arg1) && ?arg2 = sh:Literal) ||
		(isBlank(?arg1) && ?arg2 = sh:BlankNode))
}
sh:hasNodeKind(42, sh:IRI)                         # false
sh:hasNodeKind(42, sh:Literal)                     # true
sh:hasNodeKind(ex:MyInstance, sh:BlankNode)        # false

sh:inverseValueCount

The function sh:inverseValueCount returns the number of triples that have a given object (?arg1) and a given predicate (?arg2). The return type of this function is xsd:integer.

Argument Value type Description
?arg1 Any node The object node
?arg2 rdf:Property The predicate node
SPARQL DEFINITION
SELECT (COUNT(?subject) AS ?result)
WHERE {
	?subject ?arg2 ?arg1 .
}

sh:label

The function sh:label returns a string representation of a given node ?arg1. This function is the recommended entry point whenever a node shall be displayed to end users, e.g. as part of a constructed sh:message. The output of this function must be an xsd:string literal. Unbound is not a valid result.

Argument Value type Description
?arg1 Any node The node to render

The implementation details of this function are left unspecified. As a guideline, the function MAY use the values of rdfs:label and similar properties for resources. As a fall-back, it may return the qname or full IRI of a resource. For literal values, the function may use the lexical form, but may also render date and time literals in locale-specific strings.

sh:valueCount

The function sh:valueCount returns the number of triples that have a given subject (?arg1) and a given predicate (?arg2). The return type of this function is xsd:integer.

Argument Value type Description
?arg1 Any IRI or blank node The subject node
?arg2 rdf:Property The predicate node
SPARQL DEFINITION
SELECT (COUNT(?object) AS ?result)
WHERE {
	?arg1 ?arg2 ?object .
}

SPARQL Definitions of the SHACL Templates

The following subsections define the semantics of the high-level constraint vocabulary built into SHACL using SPARQL. The SPARQL Definitions use the variable ?this to refer to the focus node. The variable ?shapesGraph is expected to point at the Shapes graph. The variable ?currentShape is expected to point at the currently evaluated shape. Pre-bound variables such are printed such as ?this. SPARQL-based implementations of SHACL may use variations of the provided SPARQL queries, as long as they expose compatible behavior.

Property Constraints

sh:allowedValues

The property sh:allowedValues is defined in the SHACL template sh:AbstractAllowedValuesPropertyConstraint.

SPARQL DEFINITION
SELECT ?this (?this AS ?subject) ?predicate ?object
WHERE {
	?this ?predicate ?object .
	FILTER NOT EXISTS {
		?allowedValues (rdf:rest*)/rdf:first ?object
	}
}

sh:datatype

The property sh:datatype is defined in the SHACL template sh:AbstractDatatypePropertyConstraint.

SPARQL DEFINITION
SELECT ?this (?this AS ?subject) ?predicate ?object
WHERE {
	?this ?predicate ?object .
	FILTER (!sh:hasDatatype(?object, ?datatype)) .
}

sh:hasValue

The property sh:hasValue is defined in the SHACL template sh:AbstractHasValuePropertyConstraint.

SPARQL DEFINITION
SELECT ?this (?this AS ?subject) ?predicate
WHERE {
	FILTER NOT EXISTS {
		?this ?predicate ?hasValue
	}
}

sh:minCount, sh:maxCount

The properties sh:minCount and sh:maxCount are defined in the SHACL template sh:AbstractCountPropertyConstraint.

SPARQL DEFINITION
SELECT ?this (?this AS ?subject) ?predicate
WHERE {
	BIND (sh:valueCount(?this, ?predicate) AS ?count) .
	FILTER ((?count < ?minCount) || (bound(?maxCount) && (?count > ?maxCount))) .
}

sh:nodeKind

The property sh:nodeKind is defined in the SHACL template sh:AbstractNodeKindPropertyConstraint.

SPARQL DEFINITION
SELECT ?this (?this AS ?subject) ?predicate ?object
WHERE {
	?this ?predicate ?object .
	FILTER (!sh:hasNodeKind(?object, ?nodeType)) .
}

sh:valueShape

The property sh:valueShape is defined in the SHACL template sh:AbstractValueShapePropertyConstraint.

SPARQL DEFINITION
SELECT ?this (?this AS ?subject) ?predicate ?object 
WHERE {
	?this ?predicate ?object .
	FILTER (!sh:hasShape(?object, ?valueShape)) .
}

Some WG members have voiced concerns that the definition above requires the sh:hasShape function that may be expensive to implement for SPARQL vendors. An alternative design would be to hard-code the sh:valueShape property into the engine, and do the recursion in the outer layer, outside of SPARQL.

sh:valueType

The property sh:valueType is defined in the SHACL template sh:AbstractValueTypePropertyConstraint.

SPARQL DEFINITION
SELECT ?this (?this AS ?subject) ?predicate ?object
WHERE {
	?this ?predicate ?object .
	FILTER NOT EXISTS {
		?class rdfs:subClassOf* ?valueType .
		?object a ?class .
	}
}

Inverse Property Constraints

TODO

sh:OrConstraint

SPARQL DEFINITION
SELECT *
WHERE {
	FILTER NOT EXISTS {
		?shapes rdf:rest*/rdf:first ?shape .
		FILTER sh:hasShape(?this, ?shape) .
	}
}

sh:ClosedShapeConstraint

The following SPARQL query implements the SHACL template sh:ClosedShapeConstraint. The SHACL system vocabulary includes a resource sh:ClosedShape that is an instance of sh:ClosedShapeConstraint which can be shared among any number of shapes. Only one instance is needed because the template does not take any arguments.

SPARQL DEFINITION
SELECT ?this (?this AS ?subject) ?predicate ?object
WHERE {
	?this ?predicate ?object .
	FILTER (?predicate != rdf:type && ?predicate != sh:nodeShape) .
	FILTER NOT EXISTS {
		GRAPH ?shapesGraph {
			?currentShape sh:property/sh:predicate ?predicate .
		}
	}
}