RDFLib / pySHACL

A Python validator for SHACL
Apache License 2.0
245 stars 63 forks source link

Problem validating property path sequences #143

Closed KonradHoeffner closed 2 years ago

KonradHoeffner commented 2 years ago

The following shape should specify that all superclasses of type "Role" should have type "Role" as well. For example :SeniorPhysician is a role and has superclass :Physician, which is a role as well, so I expect the following to validate but it does not.

:RoleSuperClassShape a sh:NodeShape;
    sh:targetClass meta:Role;
    sh:property [
        sh:path rdf:type;
        sh:equals ( rdfs:subClassOf rdf:type ); 
        ].
bb:SeniorPhysician
    a meta:Role ;
    rdfs:subClassOf bb:Physician .

bb:Physician
    a meta:Role ;
    rdfs:subClassOf bb:HealthCareProfessional .
$ pyshacl -s shacl.ttl bb.ttl | head
Validation Report
Conforms: False
Results (60):
Constraint Violation in EqualsConstraintComponent (http://www.w3.org/ns/shacl#EqualsConstraintComponent):
        Severity: sh:Violation
        Source Shape: [ sh:equals ( rdfs:subClassOf rdf:type ) ; sh:path rdf:type ]
        Focus Node: bb:SeniorPhysician
        Value Node: meta:Role
        Result Path: rdf:type
        Message: Value of bb:SeniorPhysician->( rdfs:subClassOf rdf:type ) != meta:Role

Why does it give me an error even though the property path sequence should resolve to meta:Role? Is this an error in my SHACL file or a bug in pySHACL?

ashleysommer commented 2 years ago

Hi @KonradHoeffner

You are using sh:equals incorrectly. It appears that you're using a SHACL property-path expression in the value of sh:equals but that is not valid. sh:equals must be a single value.

I haven't tried it, but I think simply swapping the values of sh:path and sh:equals around do what you want:

:RoleSuperClassShape a sh:NodeShape;
    sh:targetClass meta:Role;
    sh:property [
        sh:path ( rdfs:subClassOf rdf:type );
        sh:equals rdf:type;
        ].
KonradHoeffner commented 2 years ago

Thanks for the help, that seems to do the trick! It also reports instances which do not have a value for rdfs:subClassOf but that is a problem in my shape and not pySHACL.