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> ;
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 ;
.
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
(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-user...@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.
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 ;
.
To view this discussion on the web visit https://groups.google.com/d/msgid/topbraid-users/f0606b84-d191-ad63-014b-a1ca870980ce%40topquadrant.com.
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
To view this discussion on the web visit https://groups.google.com/d/msgid/topbraid-users/CAGUep87iYAM%3DzFHyQXKicx54ZBGRLWHsUzQdp_SsQ2hkxHE%2Bfw%40mail.gmail.com.