如何编写SPARQL查询完整检索含RDF列表的SHACL形状数据
问题描述
我有一份内容如下的ttl文件:
ex:Shape1 a sh:NodeShape ; sh:property ex:Property-1 rdfs:label "Shape 1" ex:Property-1 a sh:PropertyShape ; sh:path ex:property1 sh:in ( "Option 1" "Option 2" ) ; sh:name "Property 1" ex:property1 a owl:DatatypeProperty
将上述数据加载到已存储大量形状定义的三元组库后,需要使用什么查询语句才能完整取回全部对应数据?
我当前使用的如下查询可以获取除RDF列表外的所有所需内容,针对sh:in关联的列表部分仅返回空白节点,无法获取列表内的完整取值:
PREFIX sh: <http://www.w3.org/ns/shacl#> PREFIX ex: <http://example.com/#> CONSTRUCT { ?subject ?predicate ?object } WHERE { { bind(ex:Shape1 as ?subject) ex:Shape1 ?predicate ?object } UNION { ex:Shape1 sh:property ?subject . ?subject ?predicate ?object } UNION { ex:Shape1 sh:property/sh:path ?subject . ?subject ?predicate ?object } }
问题原因
Turtle语法中用括号包裹的列表是语法糖,底层实际会被序列化为基于rdf:first和rdf:rest串联的链表结构:
- 列表头是属性(比如
sh:in)直接指向的空白节点 - 每个链表节点通过
rdf:first存储当前位置的列表值 - 每个链表节点通过
rdf:rest指向下一个链表节点,最后一个节点的rdf:rest取值为rdf:nil
原有查询仅覆盖了NodeShape本身、关联的PropertyShape、PropertyShape关联的属性路径三类主体,没有遍历RDF链表的所有节点,也没有抓取链表节点对应的rdf:first、rdf:rest三元组,因此只能拿到列表头的空白节点,取不到列表内的实际值。
解决方案
使用补充了RDF列表遍历逻辑的CONSTRUCT查询即可完整取回所有数据,查询语句如下:
PREFIX sh: <http://www.w3.org/ns/shacl#> PREFIX ex: <http://example.com/#> PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> CONSTRUCT { ?s ?p ?o } WHERE { # 收集所有需要导出的主体节点,覆盖原有三类节点+所有RDF列表节点 { BIND(ex:Shape1 AS ?s) } UNION { ex:Shape1 sh:property ?s } UNION { ex:Shape1 sh:property/sh:path ?s } UNION { # 匹配sh:in关联的RDF链表的所有节点 ex:Shape1 sh:property/sh:in/rdf:rest* ?s } # 返回所有上述主体节点的全部三元组 ?s ?p ?o }
这个查询通过sh:property/sh:in/rdf:rest*属性路径,从sh:in指向的列表头节点出发,匹配0到多次rdf:rest跳转,覆盖链表上的所有节点,最终把这些节点的所有三元组(包括存值的rdf:first、指向下一节点的rdf:rest)全部构造返回,就能拿到完整的列表内容。
内容的提问来源于stack exchange,提问作者agustaf
相关产品推荐
相关产品推荐

