3

we're trying to validate some data but right now the SHACL validation is on the anonymous object of a triple so focus node comes back empty. What we want is to get the subject of that triple as focus node.

I created a small example to illustrate my problem.

My shapes.ttl file:

@prefix ex: <http://example.com#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

ex:DiameterShape
  rdf:type sh:NodeShape ;
  sh:property [
      sh:path ex:hasValue ;
      sh:datatype xsd:integer ;
      sh:message "Diameter should be an integer"@en ;
    ] ;
  sh:property [
      sh:path ex:hasValue ;
      sh:maxInclusive 4000 ;
      sh:minInclusive 300 ;
      sh:message "Diameter should be between 300 and 4000"@en ;
      sh:severity sh:Warning ;
    ] ;
  sh:targetClass ex:Diameter ;
.
ex:ThingShape
  rdf:type sh:NodeShape ;
  sh:property [
      sh:path ex:hasAspect ;
      sh:class ex:Diameter ;
    ] ;
  sh:targetClass ex:Thing ;
.

My data.ttl file:

@prefix ex: <http://example.com#> .

ex:Thing_123
    a ex:Thing ;
  ex:hasAspect [
    a ex:Diameter ;
    ex:hasValue 200 ;
  ] .

Which contains invalid data. Running the shaclvalidator tool...

shaclvalidate.bat -datafile data.ttl -shapesfile shapes.ttl

...returns the error but notice the focus node is empty... meaning in a large enough data set it's impossible to find where the error comes from. Ideally we want to see ex:Thing_123 as focus node.

We only have control over the shapes file so getting rid of anonymous nodes is not an option.

[ rdf:type     sh:ValidationReport ;
  sh:conforms  false ;
  sh:result    [ rdf:type                      sh:ValidationResult ;
                 sh:focusNode                  []  ;
                 sh:resultMessage              "Diameter should be between 300 and 4000"@en ;
                 sh:resultPath                 ex:hasValue ;
                 sh:resultSeverity             sh:Warning ;
                 sh:sourceConstraintComponent  sh:MinInclusiveConstraintComponent ;
                 sh:sourceShape                []  ;
                 sh:value                      200
               ]
] .

Thanks in advance!

Stanislav Kralin
  • 11,070
  • 4
  • 35
  • 58
CrocoDillon
  • 126
  • 5

1 Answers1

2

The sh:focusNode is not exactly empty. What you see is the Turtle rendering, and in Turtle there is no syntax to express which particular blank node from another document you want to reference.

However, on the programmatic side, the sh:focusNode will point at the same (Jena) node that is also found in the data graph. So the only real solution right now is to not use the command line tool but instead use the validation results as part of a (Java) program. The blank node ID will be the same in both graphs and you can then look up the "root" subject like ex:Thing_123 in the data graph by walking up the incoming references. This is not anything that the TopBraid SHACL engine does automatically right now, and even if it would do that there might be multiple blank nodes underneath.

Holger Knublauch
  • 1,176
  • 5
  • 4
  • Thanks for your answer, I'm gonna have to find out if using the CLI is a hard requirement or not. Meanwhile I've been playing with moving all the rules to `ThingShape` like so: ``` ex:ThingShape rdf:type sh:NodeShape ; sh:property [ sh:path (ex:hasAspect ex:hasValue) ; sh:datatype xsd:integer ; sh:message "Diameter should be an integer"@en ; ] ; sh:targetClass ex:Thing ; . ``` This gives me the result I want but I still need to be able to specify this rule only targets `ex:Diameter` aspects as there can be more aspects. Is that possible? – CrocoDillon Jun 02 '22 at 07:14
  • To make a constraint only apply to certain values, one trick is to say sh:or ( sh:not [ sh:class ex:Diameter ] [ ... ] ) where the actual conditions go into ... BTW another alternative to a sh:path expression here would be to use sh:node ex:DiameterShape in the property shape of hasAspect. – Holger Knublauch Jun 05 '22 at 22:21
  • I'm sorry but I still can't make it work. Considering this my data: `ex:Thing_123 a ex:Thing ; ex:hasAspect [ a ex:Diameter ; ex:hasValue 200 ; ] ; ex:hasAspect [ a ex:Shape ; ex:hasValue ex:Round ; ] .`, how can I make a shape for `ex:Thing` (so the focus node gives me `ex:Thing_123`) that validates `ex:Diameter` as integer between 300 and 4000 but `ex:Shape` as either `ex:Round` or `ex:Square`? – CrocoDillon Jun 07 '22 at 20:36
  • Stackoverflow comments are probably not the right format to discuss such follow-ups. It doesn't even allow code formatting so it's very cramped here. Alternative is https://lists.w3.org/Archives/Public/public-shacl/2021Nov/0007.html – Holger Knublauch Jun 09 '22 at 03:04
  • Thanks, I posted the question there. Fingers crossed. – CrocoDillon Jun 09 '22 at 10:14