# baseURI: http://www.w3.org/ns/shacl # SHACL - Shapes Constraint Language # Draft last edited on 2015-09-04 # Created by the W3C RDF Data Shapes Working Group # Editor: Holger Knublauch @prefix rdf: . @prefix rdfs: . @prefix sh: . @prefix xsd: . a sh:Graph ; rdfs:label "SHACL Vocabulary" ; rdfs:comment "The vocabulary defining the Shapes Constraint Language (SHACL)." ; . # Declaration of the required RDFS terms -------------------------------------- rdfs:Resource a rdfs:Class ; rdfs:label "Resource" ; . sh:Shape a sh:ShapeClass ; rdfs:subClassOf rdfs:Resource ; rdfs:label "Shape" ; rdfs:comment "The class of shapes." ; sh:property [ sh:predicate sh:constraint ; sh:valueClass sh:Constraint ; rdfs:label "constraint" ; rdfs:comment "Defines arbitrary constraints on the matching resources. Use sh:property for structural property declarations." ; ] ; sh:property [ sh:predicate sh:property ; sh:valueClass sh:PropertyConstraint ; rdfs:label "property" ; rdfs:comment "Declares that a given property is relevant for matching resources." ; ] ; sh:property [ sh:predicate sh:inverseProperty ; sh:valueClass sh:InversePropertyConstraint ; rdfs:label "inverse property" ; rdfs:comment "Declares that a given incoming reference property is relevant for matching resources." ; ] ; sh:property [ sh:predicate sh:filterShape ; sh:valueClass sh:Shape ; rdfs:label "filter shape" ; rdfs:comment "Links a Shape to other Shapes that the tested nodes need to fulfill before the constraints of the shape are evaluated." ; ] ; sh:property [ sh:predicate sh:scope ; sh:valueClass sh:Scope ; rdfs:label "scope" ; rdfs:comment "Links a Shape to Scopes that produce the focus nodes that the shape applies to." ; ] ; sh:property [ sh:predicate sh:scopeClass ; sh:valueClass rdfs:Class ; rdfs:label "scope class" ; rdfs:comment "Links a Shape to a class, establishing that all instances of that class are expected to have this shape." ; ] ; . sh:ShapeClass a rdfs:Class ; rdfs:subClassOf rdfs:Class ; rdfs:subClassOf sh:Shape ; rdfs:label "Shape class" ; rdfs:comment "The metaclass for classes that are also shapes." ; . rdfs:Class a sh:ShapeClass ; rdfs:subClassOf rdfs:Resource ; rdfs:label "Class" ; rdfs:comment "The class of classes." ; sh:property [ sh:predicate sh:abstract ; sh:datatype xsd:boolean ; sh:maxCount 1 ; rdfs:label "abstract" ; rdfs:comment "True to indicate that this class is not expected to have direct instances." ; ] ; sh:property [ sh:predicate sh:private ; sh:datatype xsd:boolean ; sh:maxCount 1 ; rdfs:label "private" ; rdfs:comment "True to indicate that this class is only meant to be used inside of the graph that it has been defined in. This is often used to discourage instantiation outside of controlled scenarios. User interfaces may hide private classes from selection widgets." ; ] ; . rdfs:Datatype a rdfs:Class ; rdfs:subClassOf rdfs:Class ; rdfs:label "Datatype" ; rdfs:comment "The class of RDF datatypes." ; . rdfs:Literal a rdfs:Class ; rdfs:subClassOf rdfs:Resource ; rdfs:label "Literal" ; rdfs:comment "The class of literal values, eg. textual strings and integers." ; . rdf:List a rdfs:Class ; rdfs:subClassOf rdfs:Resource ; rdfs:label "List" ; rdfs:comment "The class of RDF Lists." ; . rdf:Property a rdfs:Class ; rdfs:subClassOf rdfs:Resource ; rdfs:label "Property" ; rdfs:comment "The class of RDF properties." ; . sh:text a rdfs:Datatype ; rdfs:subClassOf rdfs:Literal ; rdfs:label "text" ; rdfs:comment "The union of xsd:string and rdf:langString, to be used in cases where a property can either be a string or a string with a language tag. This type should never be used directly as the type of literals." ; . # Just a suggestion of commonly used datatypes - more should be added xsd:boolean a rdfs:Datatype ; rdfs:subClassOf rdfs:Literal ; rdfs:label "boolean" . xsd:date a rdfs:Datatype ; rdfs:subClassOf rdfs:Literal ; rdfs:label "date" . xsd:dateTime a rdfs:Datatype ; rdfs:subClassOf rdfs:Literal ; rdfs:label "dateTime" . xsd:decimal a rdfs:Datatype ; rdfs:subClassOf rdfs:Literal ; rdfs:label "decimal" . xsd:float a rdfs:Datatype ; rdfs:subClassOf rdfs:Literal ; rdfs:label "float" . xsd:integer a rdfs:Datatype ; rdfs:subClassOf rdfs:Literal ; rdfs:label "integer" . xsd:string a rdfs:Datatype ; rdfs:subClassOf rdfs:Literal ; rdfs:label "string" . xsd:time a rdfs:Datatype ; rdfs:subClassOf rdfs:Literal ; rdfs:label "time" . # Graph management ------------------------------------------------------------ sh:Graph a sh:ShapeClass ; rdfs:subClassOf rdfs:Resource ; rdfs:label "Graph" ; rdfs:comment "A collection of RDF triples identified by a URI. In a Linked Data scenario, a graph should be accessible from its URI via content negotiation in formats such as Turtle and JSON-LD." ; sh:property [ sh:predicate sh:entailment ; sh:valueClass rdfs:Resource ; sh:nodeKind sh:IRI ; rdfs:label "entailment" ; rdfs:comment "Links a graph with an entailment regime that its shape definitions shall be evaluated with." ; ] ; sh:property [ sh:predicate sh:include ; sh:valueClass sh:Graph ; rdfs:label "include" ; rdfs:comment "Links a graph with other graphs that shall be included into the query graph over which constraints are validated. This is a transitive property, i.e. includes of includes are also added." ; ] ; sh:property [ sh:predicate sh:shapesGraph ; sh:valueClass rdfs:Resource ; rdfs:label "shapes graph" ; rdfs:comment "Links a graph with other graphs that shall be included into the shapes graph that includes shape and template definitions as well as the SHACL metamodel." ; ] ; . # Node kind vocabulary -------------------------------------------------------- sh:NodeKind a rdfs:Class ; rdfs:subClassOf rdfs:Resource ; rdfs:label "Node kind" ; rdfs:comment "The class of RDF node kinds: literals, blank nodes and IRIs." ; # TODO: Maybe specify that this is an enumerated class (ISSUE-84) . sh:BlankNode a sh:NodeKind ; rdfs:label "Blank node" ; rdfs:comment "The node kind of all blank nodes."; . sh:IRI a sh:NodeKind ; rdfs:label "IRI" ; rdfs:comment "The node kind of all IRIs."; . sh:Literal a sh:NodeKind ; rdfs:label "Literal" ; rdfs:comment "The node kind of all literals."; . # Macros meta-model ----------------------------------------------------------- # This is the meta model for Templates and Functions - encapsulated reusable # queries that can take arguments. sh:Macro a sh:ShapeClass ; rdfs:subClassOf sh:ShapeClass ; rdfs:label "Macro" ; rdfs:comment "Abstract superclass of macro components of a SHACL library, especially Functions and Templates. Macros can take arguments, which are constraints that are different from PropertyConstraints in that they can only have at most one value." ; sh:abstract true; sh:property [ sh:predicate sh:argument ; sh:valueClass sh:Argument ; rdfs:label "argument" ; rdfs:comment "Declares the argument(s) of this macro." ; ] ; sh:constraint [ rdfs:comment "The same predicate can only be used once at all Arguments." ; sh:message "Duplicate Argument for the same predicate {?argPredicate}" ; sh:predicate sh:argument ; sh:sparql """ SELECT ?this (?this AS ?subject) (?predicate AS ?argPredicate) (?argument1 AS ?object) WHERE { ?this rdfs:subClassOf* ?class1 . ?class1 sh:argument ?argument1 . ?argument1 sh:predicate ?predicate . ?this rdfs:subClassOf* ?class2 . ?class2 sh:argument ?argument2 . FILTER (?argument1 != ?argument2) . ?argument2 sh:predicate ?predicate . } """ ; ] ; . sh:Function a sh:ShapeClass ; rdfs:subClassOf sh:SPARQLExecutable ; rdfs:subClassOf sh:Macro ; rdfs:label "Function" ; rdfs:comment "A macro implementing a SPARQL function, backed by a SPARQL ASK or SELECT query." ; sh:property [ sh:predicate sh:cachable ; sh:datatype xsd:boolean ; sh:maxCount 1 ; rdfs:label "cachable" ; rdfs:comment "True to indicate that this function will always return the same values for the same combination of arguments, regardless of the query graphs. Engines can use this information to cache and reuse previous function calls." ; ] ; . sh:ValidationFunctions a sh:Function ; rdfs:subClassOf rdfs:Resource ; sh:abstract true ; rdfs:label "Validation functions" ; rdfs:comment "The recommended abstract superclass for all validation functions that take a value as an argument and return a boolean result (true if the value is OK)." ; sh:argument [ sh:index 0 ; sh:predicate sh:value ; rdfs:comment "The value to validate." ; ] ; . sh:Template a sh:ShapeClass ; rdfs:subClassOf sh:Macro ; rdfs:subClassOf sh:SPARQLExecutable ; rdfs:label "Template" ; rdfs:comment "A macro that acts as an abstraction of a (reusable) SPARQL query. The query can be parameterized by the supplied arguments." ; sh:abstract true ; sh:property [ sh:predicate sh:labelTemplate ; sh:datatype sh:text ; rdfs:label "label template" ; rdfs:comment "Outlines how human-readable labels of instances of this template class shall be produced. The values must be strings that can contain {?argName} as placeholders for the actual values of the given argument. There may be multiple values, for different languages." ; ] ; . sh:Profile a sh:ShapeClass ; rdfs:subClassOf rdfs:Resource ; rdfs:label "Profile" ; rdfs:comment "A profile is a collection of constraint templates and scope templates. Profiles can be used to group together templates with similar complexity. Tools can indicate that they support specific profiles only." ; sh:property [ sh:predicate sh:constraintTemplate ; sh:valueClass sh:ConstraintTemplate ; rdfs:label "constraint template" ; rdfs:comment "A constraint template supported by the profile." ; ] ; sh:property [ sh:predicate sh:scopeTemplate ; sh:valueClass sh:ScopeTemplate ; rdfs:label "scope template" ; rdfs:comment "A scope template supported by the profile." ; ] ; sh:property [ sh:predicate sh:extends ; sh:valueClass sh:Profile ; rdfs:label "extends" ; rdfs:comment "Points at another profile that forms a sub-set of this profile." ; ] ; . # Results vocabulary ---------------------------------------------------------- # This vocabulary describes the output of constraint validation sh:ResultClass a rdfs:Class ; rdfs:subClassOf sh:ShapeClass ; rdfs:label "Result class" ; rdfs:comment "The meta-class of result types that can be instantiated to represent validation results." ; . sh:Result a sh:ShapeClass ; rdfs:subClassOf rdfs:Resource ; rdfs:label "Result" ; rdfs:comment "Instances of subclasses of this class can be constructed during constraint validation, to represent a single validation result." ; sh:abstract true ; sh:property [ sh:predicate sh:detail ; sh:valueClass sh:Result ; rdfs:label "detail" ; rdfs:comment "Can link a result with other results that provide more details. This is especially useful to describe violations against nested patterns or shapes." ; ] ; sh:property [ sh:predicate sh:message ; sh:datatype sh:text ; rdfs:label "message" ; rdfs:comment "A human-readable message explaining the cause of the result. Multiple values are possible assuming they have different languages." ; ] ; sh:property [ sh:predicate sh:subject ; sh:valueClass rdfs:Resource ; sh:maxCount 1 ; rdfs:label "subject" ; rdfs:comment "The subject of triples involved in this result." ; ] ; sh:property [ sh:predicate sh:predicate ; sh:valueClass rdf:Property ; sh:maxCount 1 ; rdfs:label "predicate" ; rdfs:comment "The predicate of triples involved in this result." ; ] ; sh:property [ sh:predicate sh:object ; sh:maxCount 1 ; rdfs:label "object" ; rdfs:comment "The object of triples involved in this result." ; ] ; sh:property [ sh:predicate sh:focusNode ; sh:valueClass rdfs:Resource ; sh:maxCount 1 ; rdfs:label "focus node" ; rdfs:comment "The focus node evaluated when the result was produced." ; ] ; sh:property [ sh:predicate sh:sourceConstraint ; sh:valueClass sh:Constraint ; sh:maxCount 1 ; rdfs:label "source constraint" ; rdfs:comment "The Constraint that caused this result." ; ] ; sh:property [ sh:predicate sh:sourceShape ; sh:valueClass sh:Shape ; sh:maxCount 1 ; rdfs:label "source shape" ; rdfs:comment "The Shape that caused this result." ; ] ; . sh:ConstraintViolation a sh:ShapeClass ; rdfs:subClassOf sh:Result ; rdfs:label "Constraint Violation" ; rdfs:comment "A validation result representing a constraint violation." ; sh:abstract true ; . sh:Info a sh:ResultClass ; rdfs:subClassOf sh:Result ; rdfs:label "Info" ; rdfs:comment "An INFO-level validation result." ; . sh:Warning a sh:ResultClass ; rdfs:subClassOf sh:ConstraintViolation ; rdfs:label "Warning" ; rdfs:comment "A non-critical constraint violation indicating a warning." ; . sh:Error a sh:ResultClass ; rdfs:subClassOf sh:ConstraintViolation ; rdfs:label "Error" ; rdfs:comment "A constraint violation indicating an error." ; . sh:FatalError a sh:ResultClass ; rdfs:subClassOf sh:Error ; rdfs:label "Fatal Error" ; rdfs:comment "An error that cannot be recovered and further evaluation may terminate immediately. Engines may decide to perform the validation of potentially fatal constraints first." ; . sh:ResultAnnotation a sh:ShapeClass ; rdfs:subClassOf rdfs:Resource ; rdfs:label "Result annotation" ; rdfs:comment "Defines the rules to derive the values of a given annotation property as extra values for a constraint violation." ; sh:property [ sh:predicate sh:annotationProperty ; rdfs:label "annotation property" ; rdfs:comment "The annotation property that shall be set." ; sh:minCount 1 ; sh:maxCount 1 ; sh:valueClass rdf:Property ; ] ; # TODO: Add constraint that sh:annotationProperty is not from SHACL namespace sh:property [ sh:predicate sh:annotationValue ; rdfs:label "annotation value" ; rdfs:comment "The values of the annotation property." ; sh:maxCount 1 ; ] ; sh:property [ sh:predicate sh:annotationVarName ; rdfs:label "annotation variable name" ; rdfs:comment "The name of the SPARQL variable from the SELECT clause that shall be used for the values." ; sh:maxCount 1 ; sh:datatype xsd:string ; ] ; . # Execution Support ----------------------------------------------------------- sh:SPARQLExecutable a sh:ShapeClass ; rdfs:subClassOf rdfs:Class ; sh:property [ sh:predicate sh:sparql ; sh:datatype xsd:string ; sh:maxCount 1 ; rdfs:label "SPARQL" ; rdfs:comment "The SPARQL query to execute." ; ] ; . # Scope vocabulary ------------------------------------------------------------ sh:Scope a rdfs:Class ; rdfs:subClassOf rdfs:Resource ; rdfs:label "Scope" ; rdfs:comment "An abstract superclass of scopes. Scopes are either template calls or native scopes with an executable body." ; sh:abstract true ; . sh:NativeScope a sh:ShapeClass ; rdfs:subClassOf sh:Scope ; rdfs:subClassOf sh:SPARQLExecutable ; rdfs:label "Native scope" ; rdfs:comment "A scope that has a native executable body attached to it." ; . sh:ScopeTemplate a sh:ShapeClass ; rdfs:subClassOf sh:Template ; rdfs:label "Scope template" ; rdfs:comment "A template that is used to compute a scope." ; . sh:TemplateScope a sh:ScopeTemplate ; rdfs:subClassOf sh:Scope ; rdfs:label "Scope constraint" ; rdfs:comment "A scope that is instantiating a template." ; sh:abstract true ; . sh:AllObjectsScope a sh:ScopeTemplate ; rdfs:subClassOf sh:TemplateScope ; rdfs:label "All objects scope" ; rdfs:comment "A scope that includes all objects in the graph, except literals." ; sh:sparql """ SELECT DISTINCT ?this WHERE { ?anySubject ?anyPredicate ?this . FILTER (!isLiteral(?this)) . } """ ; . sh:AllSubjectsScope a sh:ScopeTemplate ; rdfs:subClassOf sh:TemplateScope ; rdfs:label "All subjects scope" ; rdfs:comment "A scope that includes all subjects in the graph." ; sh:sparql """ SELECT DISTINCT ?this WHERE { ?this ?anyPredicate ?anyObject . } """ ; . sh:InversePropertyScope a sh:ScopeTemplate ; rdfs:subClassOf sh:TemplateScope ; rdfs:label "Inverse property scope" ; rdfs:comment "A scope that includes all objects that have at least one value for a given predicate." ; sh:argument [ sh:predicate sh:predicate ; sh:valueClass rdf:Property ; rdfs:label "predicate" ; rdfs:comment "The property to look for." ; ] ; sh:sparql """ SELECT DISTINCT ?this WHERE { ?any ?predicate ?this . } """ ; . sh:PropertyScope a sh:ScopeTemplate ; rdfs:subClassOf sh:TemplateScope ; rdfs:label "Property scope" ; rdfs:comment "A scope that includes all subjects that have at least one value for a given predicate." ; sh:argument [ sh:predicate sh:predicate ; sh:valueClass rdf:Property ; rdfs:label "predicate" ; rdfs:comment "The Property to look for." ; ] ; sh:sparql """ SELECT DISTINCT ?this WHERE { ?this ?predicate ?any . } """ ; . # Constraint vocabulary ------------------------------------------------------- sh:Constraint a sh:ShapeClass ; rdfs:subClassOf rdfs:Resource ; rdfs:label "Constraint" ; rdfs:comment "An abstract superclass of constraints. Constraints are either template calls or \"native\" constraints with an executable body." ; sh:abstract true ; sh:property [ sh:predicate sh:filterShape ; sh:valueClass sh:Shape ; rdfs:label "filter shape" ; rdfs:comment "Links a constraint to Shapes that the tested nodes need to fulfill before the constraint is evaluated." ; ] ; sh:property [ sh:predicate sh:severity ; sh:maxCount 1 ; sh:valueClass sh:ResultClass ; rdfs:label "severity" ; rdfs:comment "Specifies the severity to use for any constraint violation produced by this constraint. Defaults to sh:Error for native constraints. For template constraints it uses the severity of the template by default." ; ] ; . sh:NativeConstraint a sh:ShapeClass ; rdfs:subClassOf sh:Constraint ; rdfs:subClassOf sh:SPARQLExecutable ; rdfs:label "Native constraint" ; rdfs:comment "A constraint that has a native executable body attached with it." ; sh:property [ sh:predicate sh:message ; sh:datatype sh:text ; rdfs:label "message" ; rdfs:comment "Specifies the default sh:message(s) to produce for any constraint violation. May have multiple values for different languages." ; ] ; sh:property [ sh:predicate sh:predicate ; sh:maxCount 1 ; sh:valueClass rdf:Property ; rdfs:label "predicate" ; rdfs:comment "Specifies the default sh:predicate to produce for any constraint violation." ; ] ; sh:property [ sh:predicate rdfs:comment ; sh:datatype sh:text ; rdfs:label "comment" ; rdfs:comment "A human-readable explanation of this constraint. May have multiple values for different languages." ; ] ; sh:property [ sh:predicate sh:resultAnnotation ; sh:valueClass sh:ResultAnnotation ; rdfs:label "result annotation" ; rdfs:comment "Result annotations provide information about additional properties that the constructed constraint violations shall have." ; ] ; . sh:ConstraintTemplate a sh:ShapeClass ; rdfs:subClassOf sh:Template ; rdfs:label "Constraint template" ; rdfs:comment "A template that is used for constraint validation." ; sh:property [ sh:predicate sh:severity ; sh:maxCount 1 ; sh:valueClass sh:ResultClass ; rdfs:label "severity" ; rdfs:comment "Specifies the default rdf:type to produce for any constraint violation." ; ] ; sh:property [ sh:predicate sh:message ; sh:datatype sh:text ; rdfs:label "message" ; rdfs:comment "Specifies the default sh:message(s) to produce for any constraint violation. May have multiple values for different languages." ; ] ; sh:property [ sh:predicate sh:predicate ; sh:maxCount 1 ; sh:valueClass rdf:Property ; rdfs:label "predicate" ; rdfs:comment "Specifies the default sh:predicate to produce for any constraint violation." ; ] ; sh:property [ sh:predicate sh:resultAnnotation ; sh:valueClass sh:ResultAnnotation ; rdfs:label "result annotation" ; rdfs:comment "Result annotations provide information about additional properties that the constructed constraint violations shall have." ; ] ; . sh:AbstractValueConstraintTemplate a sh:ShapeClass ; rdfs:subClassOf sh:ConstraintTemplate ; rdfs:label "Abstract value constraint template" ; rdfs:comment "A constraint template that points to a function that validates one given value at a time." ; sh:property [ sh:predicate sh:validationFunction ; sh:maxCount 1 ; sh:minCount 1 ; sh:valueClass sh:Function ; rdfs:label "validation function" ; rdfs:comment "A boolean function that takes a given value as its first argument. Additional arguments are passed into the function if their predicate matches the template's arguments. If the function returns true then the value is valid." ; ] ; sh:abstract true ; . sh:PropertyValueConstraintTemplate a sh:ShapeClass ; rdfs:subClassOf sh:AbstractValueConstraintTemplate ; rdfs:label "Property value constraint template" ; rdfs:comment "A value constraint template that validates all objects of triples that have the given focus node as subject and the given predicate." ; . sh:InversePropertyValueConstraintTemplate a sh:ShapeClass ; rdfs:subClassOf sh:AbstractValueConstraintTemplate ; rdfs:label "Inverse property value constraint template" ; rdfs:comment "A value constraint template that validates all subjects of triples that have the given focus node as object and the given predicate." ; . # TODO: This name is easy to confuse with sh:ConstraintTemplate sh:TemplateConstraint a sh:ConstraintTemplate ; rdfs:subClassOf sh:Constraint ; rdfs:label "Template constraint" ; rdfs:comment "A constraint that is instantiating a template." ; sh:abstract true ; . # Property templating sub-system ---------------------------------------------- # The following templates cover frequently needed data modeling patterns. # They have in common that they are about one specific rdf:Property (predicate). # These templates are part of the core standard so that engines may decide to # hard-code them without requiring a full SPARQL implementation. sh:AbstractPropertyConstraint a sh:ConstraintTemplate ; rdfs:subClassOf sh:TemplateConstraint ; rdfs:label "Abstract property constraint" ; rdfs:comment "Shared superclass for templates that take a predicate as one of their arguments." ; sh:abstract true ; sh:argument [ sh:predicate sh:predicate ; sh:valueClass rdf:Property ; rdfs:label "predicate" ; rdfs:comment "The Property being constrained." ; ] ; sh:property [ sh:predicate rdfs:label ; sh:datatype sh:text ; rdfs:label "label" ; rdfs:comment "A display label for input forms etc. By default, the global rdfs:label of the predicate should be used. Multiple values (for different languages) are supported." ; ] ; sh:property [ sh:predicate rdfs:comment ; sh:datatype sh:text ; rdfs:label "comment" ; rdfs:comment "A description of the role of the predicate to users. Multiple values (for different languages) are supported." ; ] ; . # Arguments ------------------------------------------------------------------- sh:AbstractArgumentDatatypeConstraint a sh:PropertyValueConstraintTemplate ; rdfs:subClassOf sh:AbstractPropertyConstraint ; rdfs:label "Abstract argument datatype constraint" ; rdfs:comment "Enforces a constraint that the value of an argument must be a literal of a certain datatype. sh:text is recommended if the values shall be either strings or string with language tags." ; sh:abstract true ; sh:argument [ sh:predicate sh:datatype ; sh:optionalWhenInherited true ; sh:nodeKind sh:IRI ; sh:valueClass rdfs:Datatype ; rdfs:label "datatype" ; rdfs:comment "The datatype that all values of the property must have." ; ] ; sh:message "Values must have datatype {?datatype}" ; sh:validationFunction sh:hasDatatype ; . sh:AbstractArgumentMaxCountConstraint a sh:ConstraintTemplate ; rdfs:subClassOf sh:AbstractPropertyConstraint ; rdfs:label "Abstract argument max count constraint" ; sh:abstract true ; sh:message "Arguments cannot have more than one value." ; sh:sparql """ SELECT ?this (?this AS ?subject) ?predicate WHERE { FILTER EXISTS { ?this ?predicate ?value1 . ?this ?predicate ?value2 . FILTER (?value1 != ?value2) . } } """ ; . sh:AbstractArgumentValueClassConstraint a sh:PropertyValueConstraintTemplate ; rdfs:subClassOf sh:AbstractPropertyConstraint ; rdfs:label "Abstract argument value class constraint" ; rdfs:comment "Enforces a constraint that the value of an argument must be of a certain type. This will accept instances of subclasses." ; sh:abstract true ; sh:argument [ sh:predicate sh:valueClass ; sh:optionalWhenInherited true ; sh:nodeKind sh:IRI ; sh:valueClass rdfs:Class ; rdfs:label "value class" ; rdfs:comment "The type that all values of the property must have, based on the semantics defined by the function sh:hasValueClass." ; ] ; sh:message "Values must be instances of {?valueClass}" ; sh:validationFunction sh:hasValueClass ; . sh:AbstractOptionalArgumentConstraint a sh:ConstraintTemplate ; rdfs:subClassOf sh:AbstractPropertyConstraint ; rdfs:label "Abstract optional argument constraint" ; rdfs:comment "Enforces a constraint that a non-optional argument must have a value, similar to minCount = 1, unless it has been declared optional, or a sh:defaultValue exists." ; sh:abstract true ; sh:argument [ sh:predicate sh:defaultValue ; sh:optional true; rdfs:label "default value" ; rdfs:comment "The default value of this argument, to be used if no other value has been specified." ; ] ; sh:argument [ sh:predicate sh:optional ; sh:defaultValue false ; sh:datatype xsd:boolean ; rdfs:label "optional" ; rdfs:comment "True to indicate that the property does not require a value. By default, the value is required." ; ] ; sh:argument [ sh:predicate sh:optionalWhenInherited ; sh:defaultValue false ; sh:datatype xsd:boolean ; rdfs:label "optional when inherited" ; rdfs:comment "True to indicate that the property does not require a value when used by a subclass template. If set to true, then instances of subclasses do not need to fill in all required arguments - incomplete templates will simply not be executed. By default, the value is required." ; ] ; sh:message "Missing value for required argument" ; sh:sparql """ SELECT ?this (?this AS ?subject) ?predicate WHERE { FILTER (!bound(?defaultValue) && !?optional && !?optionalWhenInherited && NOT EXISTS { ?this ?predicate ?any }) . } """ ; . sh:Argument a sh:ConstraintTemplate ; rdfs:subClassOf sh:AbstractOptionalArgumentConstraint ; rdfs:subClassOf sh:AbstractArgumentDatatypeConstraint ; rdfs:subClassOf sh:AbstractArgumentMaxCountConstraint ; rdfs:subClassOf sh:AbstractArgumentValueClassConstraint ; # TODO: Should we support node kinds here too? rdfs:label "Argument" ; rdfs:comment "Declares an argument that gets mapped to a variable in the parameterized SPARQL query." ; sh:labelTemplate "Argument {?predicate} : {?datatype}{?valueClass}" ; sh:property [ sh:predicate sh:index ; rdfs:label "index" ; rdfs:comment "The index of this argument, especially to determine the order of arguments in a function call. Values should be 0, 1, 2 etc. The default index for sh:arg1 is 0 etc." ; sh:datatype xsd:integer ; sh:minInclusive 0 ; sh:maxCount 1 ; ] ; sh:constraint [ sh:message "Arguments cannot have both ?datatype and ?valueClass." ; sh:predicate sh:datatype ; sh:sparql """ SELECT * WHERE { FILTER EXISTS { ?this sh:datatype ?value1 . ?this sh:valueClass ?value2 . } } """ ; ] ; . # Property constraints -------------------------------------------------------- sh:AbstractAllowedValuesPropertyConstraint a sh:PropertyValueConstraintTemplate ; rdfs:subClassOf sh:AbstractPropertyConstraint ; rdfs:label "Abstract allowed values property constraint" ; rdfs:comment "Specifies the allowed values for a property by pointing to a List of nodes." ; sh:abstract true ; sh:argument [ sh:predicate sh:allowedValues ; sh:optionalWhenInherited true ; sh:valueClass rdf:List ; rdfs:label "allowed values" ; rdfs:comment "The rdf:List containing the allowed values of the property." ; ] ; sh:message "Value is not one of the allowed values" ; sh:validationFunction sh:isAllowedValue ; . sh:AbstractCountPropertyConstraint a sh:ConstraintTemplate ; rdfs:subClassOf sh:AbstractPropertyConstraint ; rdfs:label "Abstract count property constraint" ; rdfs:comment "Enforces a constraint on the cardinality of the property using minCount and maxCount. By default, a property may have 0 to unlimited number of values." ; sh:abstract true ; sh:argument [ sh:predicate sh:minCount ; sh:defaultValue 0 ; sh:optional true ; sh:datatype xsd:integer ; rdfs:label "min count" ; rdfs:comment "The minimum number of values that the property must have. Defaults to 0." ; ] ; sh:argument [ sh:predicate sh:maxCount ; sh:optional true ; sh:datatype xsd:integer ; rdfs:label "max count" ; rdfs:comment "The maximum number of values that the property must have. Defaults to unlimited." ; ] ; sh:message "Required value count [{?minCount}..{?maxCount}] but found {?count}" ; sh:sparql """ SELECT ?this (?this AS ?subject) ?predicate ?count WHERE { BIND (sh:valueCount(?this, ?predicate) AS ?count) . FILTER ((?count < ?minCount) || (bound(?maxCount) && (?count > ?maxCount))) . } """ ; . sh:AbstractDatatypePropertyConstraint a sh:PropertyValueConstraintTemplate ; rdfs:subClassOf sh:AbstractPropertyConstraint ; rdfs:label "Abstract datatype property constraint" ; rdfs:comment "Enforces a constraint that all values of the property must be literals of a certain datatype. This will accept strings with language tags instead of xsd:string." ; sh:abstract true ; sh:argument [ sh:predicate sh:datatype ; sh:optionalWhenInherited true ; sh:nodeKind sh:IRI ; sh:valueClass rdfs:Datatype ; rdfs:label "datatype" ; rdfs:comment "The datatype that all values of the property must have. sh:text is recommended if the values shall be either strings or string with language tags." ; ] ; sh:message "Values must have datatype {?datatype}" ; sh:validationFunction sh:hasDatatype ; . sh:AbstractDirectValueTypePropertyConstraint a sh:PropertyValueConstraintTemplate ; rdfs:subClassOf sh:AbstractPropertyConstraint ; rdfs:label "Abstract direct value type property constraint" ; rdfs:comment "Enforces a constraint that all values of the property must be of a certain (direct) type. In contrast to sh:valueClass this does not include instances of subclasses." ; sh:abstract true ; sh:argument [ sh:predicate sh:directValueType ; sh:optionalWhenInherited true ; sh:nodeKind sh:IRI ; sh:valueClass rdfs:Class ; rdfs:label "direct value type" ; rdfs:comment "The type that all values of the property must have, excluding subclasses." ; ] ; sh:message "Values must be direct instances of {?directValueType}" ; sh:validationFunction sh:hasDirectValueType ; . sh:AbstractHasValuePropertyConstraint a sh:ConstraintTemplate ; rdfs:subClassOf sh:AbstractPropertyConstraint ; rdfs:label "Abstract has value property constraint" ; rdfs:comment "Specifies that the given property must have the specified value (it may also have others)." ; sh:abstract true ; sh:argument [ sh:predicate sh:hasValue ; sh:optionalWhenInherited true ; rdfs:label "has value" ; rdfs:comment "The required value of the property." ; ] ; sh:message "Missing expected value {?hasValue}" ; sh:sparql """ SELECT ?this (?this AS ?subject) ?predicate ?hasValue WHERE { FILTER NOT EXISTS { ?this ?predicate ?hasValue } } """ ; . sh:AbstractNodeKindPropertyConstraint a sh:PropertyValueConstraintTemplate ; rdfs:subClassOf sh:AbstractPropertyConstraint ; rdfs:label "Abstract node kind property constraint" ; rdfs:comment "Specifies the valid node kind of a property." ; sh:abstract true ; sh:argument [ sh:predicate sh:nodeKind ; sh:optionalWhenInherited true ; sh:valueClass sh:NodeKind ; rdfs:label "node kind" ; rdfs:comment "The node kind that all values of the property must be of." ; ] ; sh:message "Values must be of kind {?nodeKind}" ; sh:validationFunction sh:hasNodeKind ; . sh:AbstractQualifiedValueShapePropertyConstraint a sh:ConstraintTemplate ; rdfs:subClassOf sh:AbstractPropertyConstraint ; rdfs:label "Abstract qualified value shape property constraint" ; rdfs:comment "Enforces a constraint that a certain number of values of the property must have a certain shape." ; sh:abstract true ; sh:argument [ sh:predicate sh:qualifiedValueShape ; sh:optionalWhenInherited true ; sh:valueClass sh:Shape ; rdfs:label "qualified value shape" ; rdfs:comment "The shape that the values must have." ; ] ; sh:argument [ sh:predicate sh:qualifiedMinCount ; sh:optionalWhenInherited true ; sh:datatype xsd:integer ; sh:defaultValue 0 ; rdfs:label "qualified min count" ; rdfs:comment "The minimum number of values that must have the shape." ; ] ; sh:argument [ sh:predicate sh:qualifiedMaxCount ; sh:optionalWhenInherited true ; sh:datatype xsd:integer ; rdfs:label "qualified max count" ; rdfs:comment "The maximum number of values that must have the shape." ; ] ; sh:message "Violation of qualified value shape constraint {?qualifiedValueShape}: expected [{?qualifiedMinCount}..{?qualifiedMaxCount}], found {?count}" ; sh:sparql """ SELECT ?this (?this AS ?subject) ?predicate ?qualifiedValueShape ?qualifiedMinCount ?qualifiedMaxCount ?count ?error WHERE { BIND (sh:valuesWithShapeCount(?this, ?predicate, ?qualifiedValueShape, ?shapesGraph) AS ?count) . BIND (!bound(?count) AS ?error) . FILTER IF(?error, true, ((?count < ?qualifiedMinCount) || (bound(?qualifiedMaxCount) && (?count > ?qualifiedMaxCount)))) . } """ ; . sh:AbstractValueClassPropertyConstraint a sh:PropertyValueConstraintTemplate ; rdfs:subClassOf sh:AbstractPropertyConstraint ; rdfs:label "Abstract value class property constraint" ; rdfs:comment "Enforces a constraint that all values of the property must be of a certain type. For resources this will accept instances of subclasses. Untyped blank nodes are allowed if a defaultValueType has been specified." ; sh:abstract true ; sh:argument [ sh:predicate sh:valueClass ; sh:optionalWhenInherited true ; sh:nodeKind sh:IRI ; sh:valueClass rdfs:Class ; rdfs:label "value class" ; rdfs:comment "The type that all values of the property must have, based on the semantics defined by the function sh:hasValueClass." ; ] ; sh:message "Values must be instances of {?valueClass}" ; sh:validationFunction sh:hasValueClass ; . sh:AbstractValueShapePropertyConstraint a sh:ConstraintTemplate ; rdfs:subClassOf sh:AbstractPropertyConstraint ; rdfs:label "Abstract value shape property constraint" ; rdfs:comment "Enforces a constraint that all values of the property must have a certain shape." ; sh:abstract true ; sh:argument [ sh:predicate sh:valueShape ; sh:optionalWhenInherited true ; sh:valueClass sh:Shape ; rdfs:label "value shape" ; rdfs:comment "The shape that the values must have." ; ] ; sh:message "Value does not fulfill the constraints of shape {?valueShape}" ; sh:sparql """ SELECT ?this (?this AS ?subject) ?predicate ?object ?valueShape ?error WHERE { ?this ?predicate ?object . BIND (sh:hasShape(?object, ?valueShape, ?shapesGraph) AS ?hasShape) . BIND (!bound(?hasShape) AS ?error) . FILTER (?error || !?hasShape) . } """ ; . sh:AbstractLengthPropertyConstraint a sh:PropertyValueConstraintTemplate ; rdfs:subClassOf sh:AbstractPropertyConstraint ; rdfs:label "Abstract length property constraint" ; rdfs:comment "Specifies the minimum and maximum string length of values." ; sh:abstract true ; sh:argument [ sh:predicate sh:minLength ; sh:optional true ; sh:optionalWhenInherited true ; sh:datatype xsd:integer ; rdfs:label "min length" ; rdfs:comment "The minimum string length permitted for values of this property." ; ] ; sh:argument [ sh:predicate sh:maxLength ; sh:optional true ; sh:optionalWhenInherited true ; sh:datatype xsd:integer ; rdfs:label "max length" ; rdfs:comment "The maximum string length permitted for values of this property." ; ] ; sh:message "Invalid string length." ; sh:validationFunction sh:hasLength ; . sh:AbstractMaxExclusivePropertyConstraint a sh:PropertyValueConstraintTemplate ; rdfs:subClassOf sh:AbstractPropertyConstraint ; rdfs:label "Abstract max exclusive property constraint" ; rdfs:comment "Specifies an (exclusive) maximum value for literal values." ; sh:abstract true ; sh:argument [ sh:predicate sh:maxExclusive ; sh:optionalWhenInherited true ; sh:nodeKind sh:Literal ; rdfs:label "max exclusive" ; rdfs:comment "The exclusive maximum value permitted for this property: ?value < ?maxExclusive" ; ] ; sh:message "Values must be less than {?maxExclusive}" ; sh:validationFunction sh:hasMaxExclusive ; . sh:AbstractMaxInclusivePropertyConstraint a sh:PropertyValueConstraintTemplate ; rdfs:subClassOf sh:AbstractPropertyConstraint ; rdfs:label "Abstract max inclusive property constraint" ; rdfs:comment "Specifies an (inclusive) maximum value for literal values." ; sh:abstract true ; sh:argument [ sh:predicate sh:maxInclusive ; sh:optionalWhenInherited true ; sh:nodeKind sh:Literal ; rdfs:label "max inclusive" ; rdfs:comment "The inclusive maximum value permitted for this property: ?value <= ?maxInclusive" ; ] ; sh:message "Values must be less than or equal to {?maxInclusive}" ; sh:validationFunction sh:hasMaxInclusive ; . sh:AbstractMinExclusivePropertyConstraint a sh:PropertyValueConstraintTemplate ; rdfs:subClassOf sh:AbstractPropertyConstraint ; rdfs:label "Abstract min exclusive property constraint" ; rdfs:comment "Specifies an (exclusive) minimum value for literal values." ; sh:abstract true ; sh:argument [ sh:predicate sh:minExclusive ; sh:optionalWhenInherited true ; sh:nodeKind sh:Literal ; rdfs:label "min exclusive" ; rdfs:comment "The exclusive minimum value permitted for this property: ?value > ?minExclusive" ; ] ; sh:message "Values must be greater than {?minExclusive}" ; sh:validationFunction sh:hasMinExclusive ; . sh:AbstractMinInclusivePropertyConstraint a sh:PropertyValueConstraintTemplate ; rdfs:subClassOf sh:AbstractPropertyConstraint ; rdfs:label "Abstract min inclusive property constraint" ; rdfs:comment "Specifies an (inclusive) minimum value for literal values." ; sh:abstract true ; sh:argument [ sh:predicate sh:minInclusive ; sh:optionalWhenInherited true ; sh:nodeKind sh:Literal ; rdfs:label "min inclusive" ; rdfs:comment "The inclusive minimum value permitted for this property: ?value >= ?minInclusive" ; ] ; sh:message "Values must be greater than or equal to {?minInclusive}" ; sh:validationFunction sh:hasMinInclusive ; . sh:AbstractPatternPropertyConstraint a sh:PropertyValueConstraintTemplate ; rdfs:subClassOf sh:AbstractPropertyConstraint ; rdfs:label "Abstract pattern property constraint" ; rdfs:comment "Specifies a regular expression that all values of the property need to match." ; sh:abstract true ; sh:argument [ sh:predicate sh:pattern ; sh:optionalWhenInherited true ; sh:datatype xsd:string ; rdfs:label "pattern" ; rdfs:comment "The (regular expression) pattern for values of this property." ; ] ; sh:message "Values must match the pattern {?pattern}" ; sh:validationFunction sh:hasPattern ; . sh:PropertyConstraint a sh:ConstraintTemplate ; rdfs:subClassOf sh:AbstractAllowedValuesPropertyConstraint ; rdfs:subClassOf sh:AbstractCountPropertyConstraint ; rdfs:subClassOf sh:AbstractDatatypePropertyConstraint ; rdfs:subClassOf sh:AbstractDirectValueTypePropertyConstraint ; rdfs:subClassOf sh:AbstractHasValuePropertyConstraint ; rdfs:subClassOf sh:AbstractLengthPropertyConstraint ; rdfs:subClassOf sh:AbstractMaxExclusivePropertyConstraint ; rdfs:subClassOf sh:AbstractMaxInclusivePropertyConstraint ; rdfs:subClassOf sh:AbstractMinExclusivePropertyConstraint ; rdfs:subClassOf sh:AbstractMinInclusivePropertyConstraint ; rdfs:subClassOf sh:AbstractNodeKindPropertyConstraint ; rdfs:subClassOf sh:AbstractPatternPropertyConstraint ; rdfs:subClassOf sh:AbstractQualifiedValueShapePropertyConstraint ; rdfs:subClassOf sh:AbstractValueClassPropertyConstraint ; rdfs:subClassOf sh:AbstractValueShapePropertyConstraint ; rdfs:label "Property constraint" ; rdfs:comment "Declares the structural constraints for a property at the associated class. The supported arguments are inherited from the superclasses." ; sh:labelTemplate "Property {?predicate} : {?datatype}{?valueClass} [{?minCount}..{?maxCount}]" ; sh:property [ sh:predicate sh:defaultValue ; sh:maxCount 1 ; rdfs:label "default value" ; rdfs:comment "A default value that could be used to pre-populate input forms etc. This has no formal meaning otherwise." ; ] ; sh:constraint [ sh:message "Property constraints cannot have both datatype and valueClass or directValueType." ; sh:predicate sh:datatype ; sh:sparql """ SELECT ?this WHERE { FILTER EXISTS { ?this sh:datatype ?datatype . ?this sh:valueClass|sh:directValueType ?any . } } """ ] ; . # Inverse property constraints ------------------------------------------------ sh:AbstractAllowedValuesInversePropertyConstraint a sh:InversePropertyValueConstraintTemplate ; rdfs:subClassOf sh:AbstractPropertyConstraint ; rdfs:label "Abstract allowed values inverse property constraint" ; rdfs:comment "Specifies the allowed values for an inverse property by pointing to a List of nodes." ; sh:abstract true ; sh:argument [ sh:predicate sh:allowedValues ; sh:optionalWhenInherited true ; sh:valueClass rdf:List ; rdfs:label "allowed values" ; rdfs:comment "The rdf:List containing the allowed values of the inverse property." ; ] ; sh:message "Value is not one of the allowed values" ; sh:validationFunction sh:isAllowedValue ; . sh:AbstractCountInversePropertyConstraint a sh:ConstraintTemplate ; rdfs:subClassOf sh:AbstractPropertyConstraint ; rdfs:label "Abstract count inverse property constraint" ; rdfs:comment "Enforces a constraint on the cardinality of an incoming property using minCount and maxCount. By default, an inverse property may have 0 to unlimited number of values." ; sh:abstract true ; sh:argument [ sh:predicate sh:minCount ; sh:defaultValue 0 ; sh:optional true ; sh:datatype xsd:integer ; rdfs:label "min count" ; rdfs:comment "The minimum number of values that the inverse property must have. Defaults to 0." ; ] ; sh:argument [ sh:predicate sh:maxCount ; sh:optional true ; sh:datatype xsd:integer ; rdfs:label "max count" ; rdfs:comment "The maximum number of values that the inverse property must have. Defaults to unlimited." ; ] ; sh:message "Inverse property must have [{?minCount}..{?maxCount}] values, but found {?count}" ; sh:sparql """ SELECT ?this (?this AS ?object) ?predicate ?minCount ?maxCount ?count WHERE { BIND (sh:inverseValueCount(?this, ?predicate) AS ?count) . FILTER ((?count < ?minCount) || (bound(?maxCount) && (?count > ?maxCount))) . } """ ; . sh:AbstractValueClassInversePropertyConstraint a sh:InversePropertyValueConstraintTemplate ; rdfs:subClassOf sh:AbstractPropertyConstraint ; rdfs:label "Abstract value class inverse property constraint" ; rdfs:comment "Enforces a constraint that all incoming values of the property must be of a certain type. This will accept instances of subclasses.." ; sh:abstract true ; sh:argument [ sh:predicate sh:valueClass ; sh:optionalWhenInherited true ; sh:valueClass rdfs:Class ; rdfs:label "value class" ; rdfs:comment "The type that all values of the inverse property must have, based on the semantics defined by the function sh:hasValueClass." ; ] ; sh:constraint [ sh:message "The values of sh:valueClass cannot be blank nodes." ; sh:predicate sh:valueClass ; sh:sparql """ SELECT ?this (?this AS ?subject) (?valueClass AS ?object) WHERE { ?this sh:valueClass ?valueClass . FILTER isBlank(?valueClass) . } """ ; ] ; sh:message "Inverse values must be instances of {?valueClass}" ; sh:validationFunction sh:hasValueClass ; . sh:AbstractValueShapeInversePropertyConstraint a sh:ConstraintTemplate ; rdfs:subClassOf sh:AbstractPropertyConstraint ; rdfs:label "Abstract value shape inverse property constraint" ; rdfs:comment "Enforces a constraint that all inverse values of the property must have a certain shape." ; sh:abstract true ; sh:argument [ sh:predicate sh:valueShape ; sh:optionalWhenInherited true ; sh:valueClass sh:Shape ; rdfs:label "value shape" ; rdfs:comment "The shape that the inverse values must have." ; ] ; sh:message "Inverse value does not fulfill the constraints of shape {?valueShape}" ; sh:sparql """ SELECT ?this (?this AS ?object) ?predicate ?subject ?valueShape ?error WHERE { ?subject ?predicate ?this . BIND (sh:hasShape(?subject, ?valueShape, ?shapesGraph) AS ?hasShape) . BIND (!bound(?hasShape) AS ?error) . FILTER (?error || !?hasShape) . } """ ; . sh:InversePropertyConstraint a sh:ConstraintTemplate ; rdfs:subClassOf sh:AbstractAllowedValuesInversePropertyConstraint ; rdfs:subClassOf sh:AbstractCountInversePropertyConstraint ; rdfs:subClassOf sh:AbstractValueClassInversePropertyConstraint ; rdfs:subClassOf sh:AbstractValueShapeInversePropertyConstraint ; rdfs:label "Inverse property constraint" ; rdfs:comment "Declares the structural constraints for an incoming property at the associated class. The supported arguments are inherited from the superclasses." ; sh:labelTemplate "Inverse property {?predicate} : {?valueClass} [{?minCount}..{?maxCount}]" ; . # Other Constraint Templates -------------------------------------------------- sh:ClosedShapeConstraint a sh:ConstraintTemplate ; rdfs:subClassOf sh:TemplateConstraint ; rdfs:label "Closed shape constraint" ; rdfs:comment "Triggers an error for each triple of the focus node that has a predicate that is not explicitly enumerated using sh:property in the surrounding shape." ; sh:labelTemplate "Closed shape" ; sh:message "Invalid triple for closed shape" ; sh:argument [ sh:predicate sh:ignoredProperties ; sh:valueClass rdf:List ; sh:optional true ; rdfs:label "ignored properties" ; rdfs:comment "A List of predicates that are permitted regardless of whether they have been declared as sh:property. Could be used to allow sh:nodeShape or rdf:type." ; ] ; sh:sparql """ SELECT ?this (?this AS ?subject) ?predicate ?object WHERE { ?this ?predicate ?object . FILTER (NOT EXISTS { GRAPH ?shapesGraph { ?currentShape sh:property/sh:predicate ?predicate . } } && (!bound(?ignoredProperties) || NOT EXISTS { GRAPH ?shapesGraph { ?ignoredProperties rdf:rest*/rdf:first ?predicate . } })) } """ ; . sh:ClosedShape a sh:ClosedShapeConstraint ; rdfs:label "Closed shape" ; rdfs:comment "A singleton instance of sh:ClosedShapeConstraint that can be shared between multiple shape definitions." ; . sh:NotConstraint a sh:ConstraintTemplate ; rdfs:subClassOf sh:TemplateConstraint ; rdfs:label "Not constraint" ; rdfs:comment "Enforces a constraint that the focus node must not have a given shape, essentially negating the conditions represented by the shape." ; sh:argument [ sh:predicate sh:shape ; sh:valueClass sh:Shape ; rdfs:label "shape" ; rdfs:comment "The shape to negate." ; ] ; sh:labelTemplate "Not constraint: {?shapes}" ; sh:message "Violation of NOT constraint" ; sh:sparql """ SELECT ?this ?error WHERE { BIND (sh:hasShape(?this, ?shape, ?shapesGraph, true) AS ?hasShape) . BIND (!bound(?hasShape) AS ?error) . FILTER (?error || ?hasShape) . } """ ; . sh:AndConstraint a sh:ConstraintTemplate ; rdfs:subClassOf sh:TemplateConstraint ; rdfs:label "And constraint" ; rdfs:comment "Enforces a constraint that all of the provided shapes must be valid for the focus resource." ; sh:argument [ sh:predicate sh:shapes ; sh:valueClass rdf:List ; rdfs:label "shapes" ; rdfs:comment "A list of shapes that will be validated." ; ] ; sh:labelTemplate "And constraint: {?shapes}" ; sh:message "Violation of AND constraint" ; sh:sparql """ SELECT ?this ?error WHERE { BIND (sh:walkShapesList(?shapes, false, ?this, ?shapesGraph) AS ?result) . BIND (!bound(?result) AS ?error) . FILTER COALESCE(?result, true) . } """ ; . sh:OrConstraint a sh:ConstraintTemplate ; rdfs:subClassOf sh:TemplateConstraint ; rdfs:label "Or constraint" ; rdfs:comment "Enforces a constraint that at least one of several provided shapes must be valid for the focus resource." ; sh:argument [ sh:predicate sh:shapes ; sh:valueClass rdf:List ; rdfs:label "shapes" ; rdfs:comment "A list of shapes that will be validated." ; ] ; sh:labelTemplate "Or constraint: {?shapes}" ; sh:message "Violation of OR constraint" ; sh:sparql """ SELECT ?this ?error WHERE { BIND (sh:walkShapesList(?shapes, true, ?this, ?shapesGraph) AS ?result) . BIND (!bound(?result) AS ?error) . FILTER COALESCE(!?result, true) . } """ ; . sh:XorConstraint a sh:ConstraintTemplate ; rdfs:subClassOf sh:TemplateConstraint ; rdfs:label "Xor constraint" ; rdfs:comment "Enforces a constraint that exactly one of multiple provided shapes must be valid for the focus resource." ; sh:argument [ sh:predicate sh:shapes ; sh:valueClass rdf:List ; rdfs:label "shapes" ; rdfs:comment "A list of shapes that will be validated." ; ] ; sh:labelTemplate "Xor constraint: {?shapes}" ; sh:message "Violation of XOR constraint" ; sh:sparql """ SELECT ?this ?error WHERE { BIND (sh:validShapeCount(?this, ?shapes, ?shapesGraph) AS ?count) BIND (!bound(?count) AS ?error) . FILTER IF(?error, true, ?count != 1) . } """ ; . # Built-in Functions ---------------------------------------------------------- sh:hasDatatype a sh:Function ; rdfs:subClassOf sh:ValidationFunctions ; rdfs:label "has datatype" ; rdfs:comment "Checks whether a given node (?value) is a literal with a given datatype (?datatype). If the datatype is sh:text, then the function will either accept xsd:string or rdf:langString." ; sh:argument [ sh:predicate sh:datatype ; sh:valueClass rdfs:Datatype ; rdfs:comment "The datatype that the node must have." ; ] ; sh:returnType xsd:boolean ; sh:sparql """ ASK { { FILTER isLiteral(?value) . } . BIND (datatype(?value) AS ?realDatatype) . FILTER ((?realDatatype = ?datatype) || (?datatype = sh:text && ?realDatatype IN (rdf:langString, xsd:string))) . } """ ; . sh:hasDirectValueType a sh:Function ; rdfs:subClassOf sh:ValidationFunctions ; rdfs:label "has direct value type" ; rdfs:comment "Checks whether a given node (?value) has a given class (?directValueType) as its rdf:type." ; sh:argument [ sh:predicate sh:directValueType ; sh:optionalWhenInherited true ; sh:nodeKind sh:IRI ; sh:valueClass rdfs:Class ; rdfs:label "direct value type" ; rdfs:comment "The type that all value must have, excluding subclasses." ; ] ; sh:returnType xsd:boolean ; sh:sparql """ ASK { ?value a ?directValueType . } """ ; . sh:hasLength a sh:Function ; rdfs:subClassOf sh:ValidationFunctions ; rdfs:label "has length" ; rdfs:comment "Checks whether a given string (?value) has a length within a given minimum and maximum string length." ; sh:argument [ sh:predicate sh:minLength ; sh:index 1 ; sh:optional true ; sh:datatype xsd:integer ; rdfs:label "min length" ; rdfs:comment "The minimum string length (defaults to 0 if unspecified)." ; ] ; sh:argument [ sh:predicate sh:maxLength ; sh:index 2 ; sh:optional true ; sh:datatype xsd:integer ; rdfs:label "max length" ; rdfs:comment "The maximum string length (defaults to unlimited)." ; ] ; sh:returnType xsd:boolean ; sh:sparql """ ASK { BIND (STRLEN(str(?value)) AS ?valueLength) . FILTER (bound(?valueLength) && (?valueLength >= COALESCE(?minLength, 0)) && (!bound(?maxLength) || ?valueLength <= ?maxLength)) . } """ ; . sh:hasMaxExclusive a sh:Function ; rdfs:subClassOf sh:ValidationFunctions ; rdfs:label "has max exclusive" ; rdfs:comment "Checks whether a given node (?value) has value less than (<) the provided ?maxExclusive. Returns false if this cannot be determined, e.g. because values do not have comparable types." ; sh:argument [ sh:predicate sh:maxExclusive ; sh:nodeKind sh:Literal ; rdfs:label "max exclusive" ; rdfs:comment "The permitted exclusive maximum value" ; ] ; sh:returnType xsd:boolean ; sh:sparql "ASK { FILTER (?value < ?maxExclusive) }" . sh:hasMaxInclusive a sh:Function ; rdfs:subClassOf sh:ValidationFunctions ; rdfs:label "has max inclusive" ; rdfs:comment "Checks whether a given node (?value) has value less than or equal to (<=) the provided ?maxInclusive. Returns false if this cannot be determined, e.g. because values do not have comparable types." ; sh:argument [ sh:predicate sh:maxInclusive ; sh:nodeKind sh:Literal ; rdfs:label "max inclusive" ; rdfs:comment "The permitted inclusive maximum value" ; ] ; sh:returnType xsd:boolean ; sh:sparql "ASK { FILTER (?value <= ?maxInclusive) }" . sh:hasMinExclusive a sh:Function ; rdfs:subClassOf sh:ValidationFunctions ; rdfs:label "has min exclusive" ; rdfs:comment "Checks whether a given node (?value) has value greater than (>) the provided ?minExclusive. Returns false if this cannot be determined, e.g. because values do not have comparable types." ; sh:argument [ sh:predicate sh:minExclusive ; sh:nodeKind sh:Literal ; rdfs:label "min exclusive" ; rdfs:comment "The permitted exclusive minimum value" ; ] ; sh:returnType xsd:boolean ; sh:sparql "ASK { FILTER (?value > ?minExclusive) }" . sh:hasMinInclusive a sh:Function ; rdfs:subClassOf sh:ValidationFunctions ; rdfs:label "has min inclusive" ; rdfs:comment "Checks whether a given node (?value) has value greater than or equal to (>=) the provided ?minInclusive. Returns false if this cannot be determined, e.g. because values do not have comparable types." ; sh:argument [ sh:predicate sh:minInclusive ; sh:nodeKind sh:Literal ; rdfs:label "min inclusive" ; rdfs:comment "The permitted inclusive minimum value" ; ] ; sh:returnType xsd:boolean ; sh:sparql "ASK { FILTER (?value >= ?minInclusive) }" . sh:hasNodeKind a sh:Function ; rdfs:subClassOf sh:ValidationFunctions ; rdfs:label "has node kind" ; rdfs:comment "Checks whether a given node (?value) has a given sh:NodeKind (?nodeKind). For example, sh:hasNodeKind(42, sh:Literal) = true." ; sh:argument [ sh:index 1 ; sh:predicate sh:nodeKind ; sh:valueClass sh:NodeKind ; rdfs:comment "The node kind that the node must have." ; ] ; sh:returnType xsd:boolean ; sh:sparql """ ASK { FILTER ((isIRI(?value) && ?nodeKind = sh:IRI) || (isLiteral(?value) && ?nodeKind = sh:Literal) || (isBlank(?value) && ?nodeKind = sh:BlankNode)) . } """ ; . sh:hasPattern a sh:Function ; rdfs:subClassOf sh:ValidationFunctions ; rdfs:label "has pattern" ; rdfs:comment "Checks whether the string representation of a given node (?value) matches a given regular expression (?pattern). Returns false if the value is a blank node." ; sh:argument [ sh:index 1 ; sh:predicate sh:pattern ; sh:datatype xsd:string ; rdfs:comment "The regular expression to match." ; ] ; sh:returnType xsd:boolean ; sh:sparql "ASK { FILTER (!isBlank(?value) && regex(str(?value), ?pattern)) }" ; . sh:hasShape a sh:Function ; rdfs:label "has shape" ; rdfs:comment "Validates whether a given resource (?arg1) fulfills all error-level constraints defined for a given shape (?arg2). This creates a (possibly recursive) constraint validator equivalent to the validateNodeAgainstShape operation. The function returns an error, i.e. no result, if the validation could not be completed, e.g. due to an unsupported recursion or an unsupported extension language. Therefore the function should not be called inside of FILTER statements directly, but rather with BIND." ; sh:argument [ sh:predicate sh:arg1 ; sh:valueClass rdfs:Resource ; rdfs:comment "The resource to validate." ; ] ; sh:argument [ sh:predicate sh:arg2 ; sh:valueClass sh:Shape ; rdfs:comment "The shape containing the constraints that need to be validated." ; ] ; sh:argument [ sh:predicate sh:arg3 ; sh:valueClass sh:Graph ; rdfs:comment "The graph containing the shape definitions." ; ] ; sh:argument [ sh:predicate sh:arg4 ; sh:datatype xsd:boolean ; sh:optional true ; rdfs:comment "If set to true then any recursive occurrence of the same resource against the same shape will fail (result=undefined)." ; ] ; sh:returnType xsd:boolean ; . sh:hasValueClass a sh:Function ; rdfs:subClassOf sh:ValidationFunctions ; rdfs:label "has value class" ; rdfs:comment "Checks whether a given node (?value) is an instance of a given class (?valueClass) or its subclasses. If ?valueClass is rdf:Property then the function returns true if ?value is an untyped IRI." ; sh:argument [ sh:index 1 ; sh:predicate sh:valueClass ; sh:valueClass rdfs:Class ; rdfs:comment "The type that the node must have." ; ] ; sh:returnType xsd:boolean ; sh:sparql """ ASK { { { FILTER (isIRI(?value) || isBlank(?value)) . } . ?class (rdfs:subClassOf)* ?valueClass . ?value a ?class . } UNION { # Allow untyped resources for rdfs:Resource and rdf:Property FILTER ((isIRI(?value) || isBlank(?value)) && (?valueClass = rdfs:Resource || ?valueClass = rdf:Property) && NOT EXISTS { ?value a ?any }) . } UNION { # Allow untyped blank nodes with rdf:first if expected type is rdf:List FILTER (?valueClass = rdf:List && isBlank(?value) && EXISTS { ?value rdf:first ?any }) . } } """ ; . sh:inverseValueCount a sh:Function ; rdfs:label "inverse value count" ; rdfs:comment "Gets the number of values of a given property (?arg2) at a given object (?arg1). The result is the number of matches of (?subject, ?arg2, ?arg1)." ; sh:argument [ sh:predicate sh:arg1 ; sh:valueClass rdfs:Resource ; rdfs:comment "The object resource." ; ] ; sh:argument [ sh:predicate sh:arg2 ; sh:valueClass rdf:Property ; rdfs:comment "The property to get the value count of." ; ] ; sh:returnType xsd:integer ; sh:sparql """ SELECT ((COUNT(?subject)) AS ?result) WHERE { ?subject ?arg2 ?arg1 . } """ ; . sh:isAllowedValue a sh:Function ; rdfs:subClassOf sh:ValidationFunctions ; sh:argument [ sh:index 1 ; sh:predicate sh:allowedValues ; sh:valueClass rdf:List ; rdfs:label "allowed values" ; rdfs:comment "The rdf:List containing the allowed values." ; ] ; sh:argument [ sh:index 2 ; sh:predicate sh:shapesGraph ; sh:valueClass sh:Graph ; rdfs:label "shapes graph" ; rdfs:comment "The graph containing the rdf:List." ; ] ; sh:returnType xsd:boolean ; sh:sparql """ ASK { FILTER EXISTS { GRAPH ?shapesGraph { ?allowedValues (rdf:rest*)/rdf:first ?value . } } } """ ; . sh:propertyValue a sh:Function ; rdfs:label "property value" ; rdfs:comment "Gets the 'first' value of a given property (?arg2) at a given subject (?arg1). The behavior is arbitrary if multiple values are present." ; sh:argument [ sh:predicate sh:arg1 ; sh:valueClass rdfs:Resource ; rdfs:comment "The subject resource." ; ] ; sh:argument [ sh:predicate sh:arg2 ; sh:valueClass rdf:Property ; rdfs:comment "The property to get the value of." ; ] ; sh:sparql """ SELECT ?object WHERE { ?arg1 ?arg2 ?object . } """ ; . sh:validShapeCount a sh:Function ; rdfs:label "valid shape count" ; rdfs:comment "Counts the number of shapes from a given rdf:List (?arg2) defined in a given shapes graph (?arg3) where a given focus node (?arg1) returns no error-level constraint violations. The function produces an error if one of the shapes validated to a fatal error." ; sh:argument [ sh:predicate sh:arg1 ; sh:valueClass rdfs:Resource ; rdfs:comment "The focus node." ; ] ; sh:argument [ sh:predicate sh:arg2 ; sh:valueClass rdf:List ; rdfs:comment "The list of shapes to walk through." ; ] ; sh:argument [ sh:predicate sh:arg3 ; sh:valueClass rdfs:Resource ; rdfs:comment "The shapes graph." ; ] ; sh:returnType xsd:integer ; sh:sparql """ # The SUM will fail with an error if one of the operands is not a number # (this mechanism is used to propagate errors from sh:hasShape calls) SELECT (SUM(?s) AS ?result) WHERE { GRAPH ?arg3 { ?arg2 rdf:rest*/rdf:first ?shape . } BIND (sh:hasShape(?arg1, ?shape, ?arg3, true) AS ?hasShape) . BIND (IF(bound(?hasShape), IF(?hasShape, 1, 0), 'error') AS ?s) . } """ ; . sh:valueCount a sh:Function ; rdfs:label "value count" ; rdfs:comment "Gets the number of values of a given property (?arg2) at a given subject (?arg1). The result is the number of matches of (?arg1, ?arg2, ?object)." ; sh:argument [ sh:predicate sh:arg1 ; sh:valueClass rdfs:Resource ; rdfs:comment "The subject resource." ; ] ; sh:argument [ sh:predicate sh:arg2 ; sh:valueClass rdf:Property ; rdfs:comment "The property to get the value count of." ; ] ; sh:returnType xsd:integer ; sh:sparql """ SELECT ((COUNT(?object)) AS ?result) WHERE { ?arg1 ?arg2 ?object . } """ ; . sh:valuesWithShapeCount a sh:Function ; rdfs:label "values with shape count" ; rdfs:comment "Counts the number of values from a given subject (?arg1) / predicate (?arg2) combination that do not produce any error-level constraint violations for a given shape (?arg3) in a given shapes graph (?arg4). The function produces an error if one of the shapes validated to a fatal error." ; sh:argument [ sh:predicate sh:arg1 ; sh:valueClass rdfs:Resource ; rdfs:comment "The subject to count the values of." ; ] ; sh:argument [ sh:predicate sh:arg2 ; sh:valueClass rdf:Property ; rdfs:comment "The property to count the values of." ; ] ; sh:argument [ sh:predicate sh:arg3 ; sh:valueClass sh:Shape ; rdfs:comment "The shape to validate." ; ] ; sh:argument [ sh:predicate sh:arg4 ; sh:valueClass rdfs:Resource ; rdfs:comment "The shapes graph." ; ] ; sh:returnType xsd:integer ; sh:sparql """ # The SUM will fail with an error if one of the operands is not a number # (this mechanism is used to propagate errors from sh:hasShape calls) SELECT (SUM(?s) AS ?result) WHERE { ?arg1 ?arg2 ?value . BIND (sh:hasShape(?value, ?arg3, ?arg4, true) AS ?hasShape) . BIND (IF(bound(?hasShape), IF(?hasShape, 1, 0), 'error') AS ?s) . } """ ; . sh:walkShapesList a sh:Function ; rdfs:label "walk shapes list" ; rdfs:comment "Walks a given rdf:List of shapes (?arg1) recursively until it encounters a shape where sh:hasShape returns a provide boolean value (?arg2) for a given focus node (?arg3) using the given shapes graph (?arg4). Returns true if the list has reached such a node, false if it has reached the end of the list. Returns an error if one of the calls to sh:hasShape has produced a fatal error." ; sh:argument [ sh:predicate sh:arg1 ; sh:valueClass rdf:List ; rdfs:comment "The current rdf:List node in the recursion." ; ] ; sh:argument [ sh:predicate sh:arg2 ; sh:datatype xsd:boolean ; rdfs:comment "The value to match sh:hasShape against." ; ] ; sh:argument [ sh:predicate sh:arg3 ; sh:valueClass rdfs:Resource ; rdfs:comment "The focus node to validate." ; ] ; sh:argument [ sh:predicate sh:arg4 ; sh:valueClass rdfs:Resource ; rdfs:comment "The shapes graph." ; ] ; sh:returnType xsd:boolean ; sh:sparql """ SELECT ?result WHERE { GRAPH ?arg4 { OPTIONAL { ?arg1 rdf:first ?shape . ?arg1 rdf:rest ?rest . } } BIND (IF(bound(?shape), sh:hasShape(?arg3, ?shape, ?arg4, true), !?arg2) AS ?hasShape) . BIND (IF(?hasShape = ?arg2, true, IF(bound(?rest), sh:walkShapesList(?rest, ?arg2, ?arg3, ?arg4), false)) AS ?result) . } """ ; . # Declarations of sh:defaultValueType ----------------------------------------- sh:argument sh:defaultValueType sh:Argument . sh:constraint sh:defaultValueType sh:NativeConstraint . sh:filterShape sh:defaultValueType sh:Shape . sh:inverseProperty sh:defaultValueType sh:InversePropertyConstraint . sh:property sh:defaultValueType sh:PropertyConstraint . sh:qualifiedValueShape sh:defaultValueType sh:Shape . sh:scope sh:defaultValueType sh:NativeScope . sh:shape sh:defaultValueType sh:Shape . sh:valueShape sh:defaultValueType sh:Shape . sh:DefaultValueTypeRule a sh:Template ; rdfs:label "default value type inference rule" ; rdfs:comment "A template encapsulating a query that can be used to construct rdf:type triples for certain untyped blank nodes that are an object in a triple where the predicate has a sh:defaultValueType. This can be used as a pre-processor for shape graphs before they are validated." ; sh:sparql """ CONSTRUCT { ?node a ?defaultValueType . } WHERE { ?predicate sh:defaultValueType ?defaultValueType . ?anySubject ?predicate ?node . FILTER (NOT EXISTS { ?node a ?anyType }) . } """ ; . # System Property declarations ------------------------------------------------ # sh:nodeShape could alternatively be attached via sh:property to rdfs:Resource, # if validation is required. However this would make it show up on all forms etc, # leading to a lot of extra filtering work. sh:nodeShape a rdf:Property ; rdfs:label "node shape" ; rdfs:comment "Links a resource with the shapes that it is supposed to have. All values of this property must be IRI nodes." ; rdfs:range sh:Shape ; . rdf:type a rdf:Property ; rdfs:label "type" . rdfs:comment a rdf:Property ; rdfs:label "comment" . rdfs:label a rdf:Property ; rdfs:label "label" . rdfs:subClassOf a rdf:Property ; rdfs:label "subClassOf" . sh:abstract a rdf:Property ; rdfs:label "abstract" . sh:allowedValues a rdf:Property ; rdfs:label "allowed values" . sh:annotationProperty a rdf:Property ; rdfs:label "annotation property" . sh:annotationVarName a rdf:Property ; rdfs:label "annotation var name" . sh:annotationValue a rdf:Property ; rdfs:label "annotation value" . sh:arg1 a rdf:Property ; rdfs:label "arg1" . sh:arg2 a rdf:Property ; rdfs:label "arg2" . sh:arg3 a rdf:Property ; rdfs:label "arg3" . sh:arg4 a rdf:Property ; rdfs:label "arg4" . sh:arg5 a rdf:Property ; rdfs:label "arg5" . sh:arg6 a rdf:Property ; rdfs:label "arg6" . sh:arg7 a rdf:Property ; rdfs:label "arg7" . sh:arg8 a rdf:Property ; rdfs:label "arg8" . sh:arg9 a rdf:Property ; rdfs:label "arg9" . sh:argument a rdf:Property ; rdfs:label "argument" . sh:cachable a rdf:Property ; rdfs:label "cachable" . sh:constraint a rdf:Property ; rdfs:label "constraint" . sh:constraintTemplate a rdf:Property ; rdfs:label "constraint template" . sh:datatype a rdf:Property ; rdfs:label "datatype" . sh:defaultValue a rdf:Property ; rdfs:label "default value" . sh:defaultValueType a rdf:Property ; rdfs:label "default value type" . sh:directValueType a rdf:Property ; rdfs:label "direct value type" . sh:detail a rdf:Property ; rdfs:label "detail" . sh:entailment a rdf:Property ; rdfs:label "entailment" . sh:extends a rdf:Property ; rdfs:label "extends" . sh:filterShape a rdf:Property ; rdfs:label "filter shape" . sh:focusNode a rdf:Property ; rdfs:label "focus node" . sh:hasValue a rdf:Property ; rdfs:label "has value" . sh:ignoredProperties a rdf:Property ; rdfs:label "ignored properties" . sh:include a rdf:Property ; rdfs:label "include" . sh:index a rdf:Property ; rdfs:label "index" . sh:inverseProperty a rdf:Property ; rdfs:label "inverse property" . sh:labelTemplate a rdf:Property ; rdfs:label "label template" . sh:maxCount a rdf:Property ; rdfs:label "max count" . sh:maxExclusive a rdf:Property ; rdfs:label "max exclusive" . sh:maxLength a rdf:Property ; rdfs:label "max length" . sh:maxInclusive a rdf:Property ; rdfs:label "max inclusive" . sh:member a rdf:Property ; rdfs:label "member" . sh:message a rdf:Property ; rdfs:label "message" . sh:minCount a rdf:Property ; rdfs:label "min count" . sh:minLength a rdf:Property ; rdfs:label "min length" . sh:minExclusive a rdf:Property ; rdfs:label "min exclusive" . sh:minInclusive a rdf:Property ; rdfs:label "min inclusive" . sh:nodeKind a rdf:Property ; rdfs:label "node kind" . sh:object a rdf:Property ; rdfs:label "object" . sh:optional a rdf:Property ; rdfs:label "optional" . sh:optionalWhenInherited a rdf:Property ; rdfs:label "optional when inherited" . sh:pattern a rdf:Property ; rdfs:label "pattern" . sh:predicate a rdf:Property ; rdfs:label "predicate" . sh:private a rdf:Property ; rdfs:label "private" . sh:property a rdf:Property ; rdfs:label "property" . sh:qualifiedMaxCount a rdf:Property ; rdfs:label "qualified max count" . sh:qualifiedMinCount a rdf:Property ; rdfs:label "qualified min count" . sh:qualifiedValueShape a rdf:Property ; rdfs:label "qualified value shape" . sh:resultAnnotation a rdf:Property ; rdfs:label "result annotation" . sh:returnType a rdf:Property ; rdfs:label "return type" . sh:scope a rdf:Property ; rdfs:label "scope" . sh:scopeClass a rdf:Property ; rdfs:label "scope class" . sh:scopeTemplate a rdf:Property ; rdfs:label "scope template" . sh:severity a rdf:Property ; rdfs:label "severity" . sh:shape a rdf:Property ; rdfs:label "shape" . sh:shapes a rdf:Property ; rdfs:label "shapes" . sh:shapesGraph a rdf:Property ; rdfs:label "shapes graph" . sh:sourceConstraint a rdf:Property ; rdfs:label "source constraint" . sh:sourceShape a rdf:Property ; rdfs:label "source shape" . sh:sparql a rdf:Property ; rdfs:label "SPARQL" . sh:subject a rdf:Property ; rdfs:label "subject" . sh:valueClass a rdf:Property ; rdfs:label "value class" . sh:valueShape a rdf:Property ; rdfs:label "value shape" . sh:value a rdf:Property ; rdfs:label "value" . sh:validationFunction a rdf:Property ; rdfs:label "validation function" .