Hi Steve,

your email appears unfinished so I wasn't sure when/whether to respond. But the correct syntax for sh:filterShape would be like

sh:exists [
    sh:filterShape qudt:Unit ;
    sh:nodes [
        sh:path [
            sh:inversePath qudt:hasQuantityKind ;
        ] ;
    ] ;
]

i.e. it needs to be combined with sh:nodes. Imagine these node expressions like a pipeline where the output of one step becomes the input to the next. Here, the input nodes to the filterShape would be the results of the sh:path expression.

HTH
Holger


On 10/30/2020 8:34 AM, Steve Ray wrote:
Thanks Holger! That worked! I had to rebalance some ]'s but then it performed perfectly!

I'm still getting used to the syntax of the sh: operators. If I could trouble you for one more piece of advice.

I realized that there are some instances of qudt:PhysicalConstant that also point to instances of qudt:QuantityKind, so I want to filter out anything that is not an instance of qudt:Unit. After exploring the documentation at https://w3c.github.io/shacl/shacl-af <https://w3c.github.io/shacl/shacl-af>, I thought sh:filterShape might do the trick. The amended code is shown below. It isn't working - in fact it is weirdly now returning just the value of $this, i.e. the subject QuantityKind. Am I using sh:filterShape correctly? I'm trying to say "Look to see if anything is pointing to you via the hasQuantityKind property, and filter those down to just instances of qudt:Unit. If you find some, return those. If not, follow the skos:broader relation and try again with that QuantityKind."

Here is the functioning code:

qudt:QuantityKind-appropriateUnit

rdf:type sh:NodeShape ;

sh:property [

rdf:type sh:PropertyShape ;

sh:path qudt:appropriateUnit ;

sh:group qudt:AppropriateUnitsGroup ;

sh:order "15"^^xsd:decimal ;

sh:values [

sh:distinct [

sh:else [

sh:path qudt:appropriateUnit ;

sh:nodes [

sh:path skos:broader ;

] ;

] ;

sh:if [

sh:exists [

sh:path [

sh:inversePath qudt:hasQuantityKind ;

] ;

sh:filterShape qudt:Unit ;

] ;

] ;

sh:then [

sh:path [

sh:inversePath qudt:hasQuantityKind ;

] ;

sh:filterShape qudt:Unit ;

] ;

] ;

] ;

] ;

sh:targetClass qudt:QuantityKind ;

.


I realized that I need to
Steve




On Wed, Oct 28, 2020 at 7:39 PM Holger Knublauch <hol...@topquadrant.com <mailto:hol...@topquadrant.com>> wrote:


    On 10/29/2020 11:51 AM, Steve Ray wrote:
    Hi,
    I am trying to recreate a recursive magic property, using a SHACL
    property shape. However, I suspect that the reason the recursion
    is not working is because the property identified in the sh:path
    statement isn't really a function in the same sense as a magic
    property is a function.

    My shape code is as follows:

    qudt:QuantityKind-appropriateUnit

    rdf:type sh:NodeShape ;

    sh:property [

    rdf:type sh:PropertyShape ;

    sh:path qudt:dappropriateUnit ;

    sh:values [

    sh:prefixes <http://qudt.org/2.1/schema/shacl/overlay/qudt
    <http://qudt.org/2.1/schema/shacl/overlay/qudt>> ;

    sh:select """SELECT DISTINCT ?unit

    WHERE {

    {

    ?unit qudt:hasQuantityKind $this .

    }

    UNION

    {

    NOT EXISTS {

    ?unit qudt:hasQuantityKind $this .

    } .

    $this skos:broader ?parent1 .

    ?parent1 qudt:dappropriateUnit ?unit .

    } .

    }""" ;

    ] ;

    ] ;

    sh:targetClass qudt:QuantityKind ;

    .


    The non-recursive part works (the first clause of the union). But
    the second union clause does not work. Is there a way to make the
    qudt:dappropriateUnit property know that there's this associated
    sh:values clause?

    As you have found out, SPARQL itself doesn't "see" the additional
    inferred triples. SHACL node expressions do, if you can
    reformulate this query, using sh:path.

    In TopBraid there is a "native" way of querying inferred values
    within SPARQL too:

    Try

        ( ?parent1 qudt:dappropriateUnit ) tosh:values ?unit .

    which is a magic property that will look at both inferred and
    asserted values at query time. Make sure to avoid infinite loops
    though, i.e. no cycles in the graph.

    As this would only work within TopBraid, a more "standard"
    approach would be to use node expressions. Something like

    sh:values [
        sh:distinct [
            sh:if [
                sh:exists [
                    sh:path [ sh:inversePath qudt:hasQuantityKind ]
                ]
            ] ;
            sh:then [
                    sh:path [ sh:inversePath qudt:hasQuantityKind ]
                ]
            ] ;
            sh:else [
                sh:path qudt:dappropriateUnit ;
                sh:nodes [
                    sh:path skos:broader ;
                ]
            ]
        ]
    ]

    which due to the geekiness and my lack of example data I haven't
    tested. It's another syntax for "If this has a subject for
    hasQuantityKind then use that, otherwise recurse into the broader
    parent". The sh:path near the sh:else would do the recursion
    automatically, I believe.

    https://w3c.github.io/shacl/shacl-af/#node-expressions-path
    <https://w3c.github.io/shacl/shacl-af/#node-expressions-path>

    (I just noticed the example there was wrong but this will
    hopefully be fixed soon).

    Holger



    Steve


-- You received this message because you are subscribed to the
    Google Groups "TopBraid Suite Users" group.
    To unsubscribe from this group and stop receiving emails from it,
    send an email to topbraid-users+unsubscr...@googlegroups.com
    <mailto:topbraid-users+unsubscr...@googlegroups.com>.
    To view this discussion on the web visit
    
https://groups.google.com/d/msgid/topbraid-users/CAGUep86_5U4TAKX-Jjb5erVdzZZZ9Xrfvv5%3DOzNJi-69gCjdzg%40mail.gmail.com
    
<https://groups.google.com/d/msgid/topbraid-users/CAGUep86_5U4TAKX-Jjb5erVdzZZZ9Xrfvv5%3DOzNJi-69gCjdzg%40mail.gmail.com?utm_medium=email&utm_source=footer>.
-- You received this message because you are subscribed to the Google
    Groups "TopBraid Suite Users" group.
    To unsubscribe from this group and stop receiving emails from it,
    send an email to topbraid-users+unsubscr...@googlegroups.com
    <mailto:topbraid-users+unsubscr...@googlegroups.com>.
    To view this discussion on the web visit
    
https://groups.google.com/d/msgid/topbraid-users/f0606b84-d191-ad63-014b-a1ca870980ce%40topquadrant.com
    
<https://groups.google.com/d/msgid/topbraid-users/f0606b84-d191-ad63-014b-a1ca870980ce%40topquadrant.com?utm_medium=email&utm_source=footer>.

--
You received this message because you are subscribed to the Google Groups "TopBraid Suite Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to topbraid-users+unsubscr...@googlegroups.com <mailto:topbraid-users+unsubscr...@googlegroups.com>. To view this discussion on the web visit https://groups.google.com/d/msgid/topbraid-users/CAGUep87iYAM%3DzFHyQXKicx54ZBGRLWHsUzQdp_SsQ2hkxHE%2Bfw%40mail.gmail.com <https://groups.google.com/d/msgid/topbraid-users/CAGUep87iYAM%3DzFHyQXKicx54ZBGRLWHsUzQdp_SsQ2hkxHE%2Bfw%40mail.gmail.com?utm_medium=email&utm_source=footer>.

--
You received this message because you are subscribed to the Google Groups "TopBraid 
Suite Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to topbraid-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/topbraid-users/61fdce92-912d-48e5-48b5-33c501d0426c%40topquadrant.com.

Reply via email to