The example ontology has two classes (:MyClass
and :Value
) and two properties (:MyObjProp
and :MyDataProp
).
:MyClass
a owl:Class ;
a sh:NodeShape ;
rdfs:subClassOf owl:Thing ;
.
:MyDataProp
a owl:DatatypeProperty ;
rdfs:domain :MyClass ;
rdfs:range xsd:string ;
.
:MyObjProp
a owl:ObjectProperty ;
rdfs:domain :MyClass ;
rdfs:range :Value ;
.
:Value
a owl:Class ;
rdfs:subClassOf owl:Thing ;
.
Some instances were added.
:MyClass_1
a :MyClass ;
:MyDataProp :Value_1 ;
:MyObjProp :Value_1 ;
.
:MyClass_2
a :MyClass ;
:MyObjProp :Value_2 ;
.
:Value_1
a :Value ;
.
:Value_2
a :Value ;
.
A NodeShape :NodeShapeRule
with a sh:rule
(:SPARQLRule_1
) was created. This rule creates new triples. With the sh:condition
the rule should be restricted to a subset of targets.
:NodeShapeRule
a sh:NodeShape ;
sh:rule :SPARQLRule_1 ;
sh:targetClass :MyClass ;
.
:SPARQLRule_1
a sh:SPARQLRule ;
sh:condition :NodeShapeConditionSPARQL ;
sh:construct """
PREFIX : <http://example.org/ex#>
CONSTRUCT
{
$this :MyDataProp \"New input\" .
}
WHERE
{
$this :MyObjProp ?p .
}
""" ;
.
For the restriction two equivalent NodeShapes were defined. The first constraint works with sh:property, the other uses sh:sparql.
:NodeShapeConditionProperty
a sh:NodeShape ;
sh:property [
sh:path :MyObjProp ;
sh:description "NodeShapeConditionProperty" ;
sh:hasValue :Value_1 ;
] ;
sh:targetClass :MyClass ;
.
:NodeShapeConditionSPARQL
a sh:NodeShape ;
sh:sparql [
sh:message "NodeShapeConditionSPARQL" ;
sh:prefixes <http://example.org/ex> ;
sh:select """
PREFIX : <http://example.org/ex#>
SELECT $this
WHERE
{
$this :MyObjProp ?prop .
}
""" ;
] ;
sh:targetClass :MyClass ;
.
While doing inferencing with Topbraid Composer I received different results for both solutions. Only the solution with sh:property provides the expected response. Please, can someone explain me this behavior?
:MyClass_1 :MyDataProp "New input"
The right explanation is that the SPAQRL query produces a constraint violation for each result (row) in SELECT query. So if the SPARQL query returns no result (rows) then all is fine and the rule will fire. The reason for this design is that this enables SPARQL queries to return more information about the violation, e.g. the focus node ($this
) and the value node (?value
).
Changing the :NodeShapeConditionSPARQL
it produces violation for not existing results and then both solutions behave in the same manner.
:NodeShapeConditionSPARQL
a sh:NodeShape ;
sh:sparql [
sh:message "NodeShapeConditionSPARQL" ;
sh:prefixes <http://example.org/ex> ;
sh:select """
PREFIX : <http://example.org/ex#>
SELECT $this
WHERE
{
FILTER NOT EXISTS { $this :MyObjProp ?anyProp } .
}
""" ;
] ;
sh:targetClass :MyClass ;
.