Search code examples
sparqlshaclsnomed-ct

SHACL SPARQLTarget not validating the SPARQL query output nodes


I have a NodeShape with a sh:SPARQLTarget . I tried to run the Target SPARQL query in an ontology editor and it delivered results, but when I'm executing the same query in my custom target node shape in sh:select, it won't validate the target nodes returned by the SPARQL query. I am using pySHACL. Did I do something wrong? I'm out of ideas. Here is my Nodeshape and data graph:

I have used “” for sh:select instead of “”” “””, since I am defining the shapes_graph as a variable in my python code and it is already encoded in """ """. I have also enabled meta_shacl=True in pyShacl to ensure that my shapes_graph is valid. Also the nodeShape (snomed:dob363698007Shape) works well when provided with a normal TargetClass or TargetNode. What am I missing?

I have already referred SPARQLRule not constructing

**NodeShape**

snomed: 
    sh:declare [
        sh:prefix "snomed" ;
        sh:namespace <http://localhost:8890/snomed/> ; 
    ] .
    
snomed:dob363698007Shape
    a sh:NodeShape ;
    sh:target [
        a sh:SPARQLTarget ;
        sh:prefixes snomed: ;
        sh:select "SELECT ?this WHERE { ?node a snomed:24078009.?node a snomed:dob .?node snomed:609096000 ?this.?this a  snomed:dob363698007 .bind(?node as ?conceptName).bind(?this as ?RGName) .FILTER(REGEX(strafter(xsd:string(?RGName),'snomed/'),strafter(xsd:string(?conceptName),'snomed/')) ).}";
        ] ;
    sh:property [
        sh:path snomed:363698007;
        sh:minCount 1;
    ].```

**Data Graph**

```snomed:dob a rdfs:Class,snomed:dob ;
       rdfs:label "Semantic Pattern dob"^^xsd:string ;
        snomed:609096000 snomed:dob363698007 .

    snomed:dob363698007 a rdfs:Class,snomed:dob363698007;
       snomed:363698007 snomed:123037004 .  

    
    snomed:24078009 a rdfs:Class, snomed:24078009, snomed:dob;
        rdfs:label "Gangosa of yaws (disorder)"^^xsd:string ;
        snomed:609096000 snomed:24078009_3,snomed:24078009_5,snomed:24078009_6;
        rdfs:subClassOf snomed:128349005,
            snomed:140004,
            snomed:177010002,
            snomed:312118003,
            snomed:312129004,
            snomed:312422001,
            snomed:363166002,
            snomed:47841006,
            snomed:88037009 .

    snomed:24078009_3 a rdfs:Class, snomed:24078009_3, snomed:dob363698007 ;
        snomed:263502005 snomed:90734009 .

    snomed:24078009_5 a rdfs:Class, snomed:24078009_5,snomed:dob363698007;
        snomed:116676008 snomed:110435003 ;
        snomed:246075003 snomed:6246005 ;
        snomed:363698007 snomed:71836000 ;
        snomed:370135005 snomed:441862004 .

    snomed:24078009_6 a rdfs:Class, snomed:24078009_6,snomed:dob363698007 ;
        snomed:116676008 snomed:110435003 ;
        snomed:246075003 snomed:6246005 ;
        snomed:363698007 snomed:72914001 ;
        snomed:370135005 snomed:441862004 .

Solution

  • I've put your shacl shapes file and data graph into PySHACL to isolate the issue you are seeing.

    There are two problems with your given setup that I have found.

    Firstly, SPARQL-Based Targets is a feature from the SHACL Advanced Specification. PySHACL does not enable the Advanced-Spec features by default. You can enable "advanced mode" by passing advanced=True to the validation module, or -a or --advanced on the commandline tool.

    That is the main reason your SPARQL target was not selecting the nodes you expected.

    Next, after enabling advanced mode, you will see that PySHACL fails when loading your SHACL Shape Graph. That is because your prefix namespace is not declared correctly.

    See the examples in the SPARQL-Prefixes section of the Spec document. The specification states

    "The values of sh:namespace are literals of datatype xsd:anyURI."

    Your sh:namespace is a URIRef, not a Literal. Changing the namespace declaration to the following, fixes the error.

    sh:namespace "http://localhost:8890/snomed/"^^xsd:anyURI ;
    

    I've run PySHACL with the corrected Shapes Graph, and it works as expected.

    See this code for a complete working example: https://gist.github.com/ashleysommer/a319beeef33973906b76711675b2635c