I am trying to write a SHACL constraint for a date comparison where the start date must be less than or equal to an end date. When the dates are attached to the same node using the :beginDate
and :endDate
predicates, the constraint is straight forward:
:StartEndRuleShape a :PropertyShape ;
sh:path :beginDate ;
sh:lessThanOrEquals :endDate ;
sh:message "Begin Date is after End Date." .
The real world model is more complex. In the attached diagram, note how an :AnimalSubject
hasReferenceInterval
. ReferenceInterval IRIs have a :ReferenceBegin
and a :ReferenceEnd
, which are in turn assigned the date value using the time:inXSDDate
predicate. How can I apply the constraint in this case to ensure the ReferenceBegin value is equal to or less than ReferenceEnd value? Is this a case for using SHACL-SPARQL, or sequencePath ? I've been unable to find good examples of either.
Cheers!
I tested the following SHACL-SPARQL on data that violates the constraint: ReferenceBegin = "2016-12-07", ReferenceEnd = "2016-12-06", but the Validation Report does not detect the violation. If I run the SPARQL on its own, it does pick out the observation. Any thoughts on why? I am using Stardog/Stardog Studio and have also posted on their user support platform.
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix time: <http://www.w3.org/2006/time#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix : <http://foo.bar.org/> .
:IntervalShape a sh:NodeShape ;
sh:targetClass :ReferenceInterval ;
sh:sparql [
a sh:SPARQLConstraint ;
sh:message "End Date must be greater than or equal to Begin Date";
sh:prefixes [
sh:declare [
sh:prefix "time" ;
sh:namespace "http://www.w3.org/2006/time#"^^xsd:anyURI ;
]
] ;
sh:select
"""SELECT $this (?beginDate AS ?intervalStart) (?endDate AS ?intervalEnd)
WHERE {
$this :hasReferenceInterval ?interval .
?interval :ReferenceBegin ?beginIRI ;
:ReferenceEnd ?endIRI .
?beginIRI time:inXSDDate ?beginDate .
?endIRI time:inXSDDate ?endDate .
FILTER (! (?endDate >= ?beginDate ))
}""" ;
] .