SHACL 比较两个不同节点上的值?
SHACL to compare values on two different nodes?
我正在尝试为开始日期必须小于或等于结束日期的日期比较编写 SHACL 约束。当使用 :beginDate
和 :endDate
谓词将日期附加到同一节点时,约束是直接的:
:StartEndRuleShape a :PropertyShape ;
sh:path :beginDate ;
sh:lessThanOrEquals :endDate ;
sh:message "Begin Date is after End Date." .
现实世界的模型更为复杂。在附图中,请注意 :AnimalSubject
hasReferenceInterval
的方式。 ReferenceInterval IRI 有一个 :ReferenceBegin
和一个 :ReferenceEnd
,它们依次使用 time:inXSDDate
谓词分配日期值。在这种情况下如何应用约束以确保 ReferenceBegin 值等于或小于 ReferenceEnd 值?这是使用 SHACL-SPARQL 还是 sequencePath 的情况?我一直无法找到任何一个的好例子。
干杯!
我在违反约束的数据上测试了以下 SHACL-SPARQL:ReferenceBegin = "2016-12-07", ReferenceEnd = "2016-12-06",但验证报告未检测到违规。如果我 运行 SPARQL 本身,它确实会挑选出观察结果。关于为什么的任何想法?我正在使用 Stardog/Stardog Studio 并且还在他们的用户支持平台上发帖。
@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 ))
}""" ;
] .
看来您的约束有两个问题:
您在 SHACL 中声明了 time
前缀,而不是 base
前缀。你想要:
sh:prefixes [
sh:declare [
sh:prefix "time" ;
sh:namespace "http://www.w3.org/2006/time#"^^xsd:anyURI ;
], [
sh:prefix "" ;
sh:namespace "http://foo.bar.org/"^^xsd:anyURI ;
]
] ;
您的焦点节点是 :ReferenceInterval
,但是您的查询的编写方式,$this
只会绑定到 :hasReferenceInterval [a :ReferenceInterval]
的实体。我重写了查询,使 ?interval
现在是 $this
,如下所示:
sh:select
"""SELECT $this (?beginDate AS ?intervalStart) (?endDate AS ?intervalEnd)
WHERE {
$this :ReferenceBegin ?beginIRI ;
:ReferenceEnd ?endIRI .
?beginIRI time:inXSDDate ?beginDate .
?endIRI time:inXSDDate ?endDate .
FILTER (! (?endDate >= ?beginDate ))
}""" ;
添加此约束后,我发现了违规行为。
我正在尝试为开始日期必须小于或等于结束日期的日期比较编写 SHACL 约束。当使用 :beginDate
和 :endDate
谓词将日期附加到同一节点时,约束是直接的:
:StartEndRuleShape a :PropertyShape ;
sh:path :beginDate ;
sh:lessThanOrEquals :endDate ;
sh:message "Begin Date is after End Date." .
现实世界的模型更为复杂。在附图中,请注意 :AnimalSubject
hasReferenceInterval
的方式。 ReferenceInterval IRI 有一个 :ReferenceBegin
和一个 :ReferenceEnd
,它们依次使用 time:inXSDDate
谓词分配日期值。在这种情况下如何应用约束以确保 ReferenceBegin 值等于或小于 ReferenceEnd 值?这是使用 SHACL-SPARQL 还是 sequencePath 的情况?我一直无法找到任何一个的好例子。
干杯!
我在违反约束的数据上测试了以下 SHACL-SPARQL:ReferenceBegin = "2016-12-07", ReferenceEnd = "2016-12-06",但验证报告未检测到违规。如果我 运行 SPARQL 本身,它确实会挑选出观察结果。关于为什么的任何想法?我正在使用 Stardog/Stardog Studio 并且还在他们的用户支持平台上发帖。
@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 ))
}""" ;
] .
看来您的约束有两个问题:
您在 SHACL 中声明了
time
前缀,而不是base
前缀。你想要:sh:prefixes [ sh:declare [ sh:prefix "time" ; sh:namespace "http://www.w3.org/2006/time#"^^xsd:anyURI ; ], [ sh:prefix "" ; sh:namespace "http://foo.bar.org/"^^xsd:anyURI ; ] ] ;
您的焦点节点是
:ReferenceInterval
,但是您的查询的编写方式,$this
只会绑定到:hasReferenceInterval [a :ReferenceInterval]
的实体。我重写了查询,使?interval
现在是$this
,如下所示:sh:select """SELECT $this (?beginDate AS ?intervalStart) (?endDate AS ?intervalEnd) WHERE { $this :ReferenceBegin ?beginIRI ; :ReferenceEnd ?endIRI . ?beginIRI time:inXSDDate ?beginDate . ?endIRI time:inXSDDate ?endDate . FILTER (! (?endDate >= ?beginDate )) }""" ;
添加此约束后,我发现了违规行为。