我无法给出正式的证明,但这看起来不可能。这不是属性路径的设计目的,也不是存在某些扩展的原因(1 https://wiki.blazegraph.com/wiki/index.php/PropertyPaths, 2 http://docs.openlinksw.com/virtuoso/rdfsparqlimplementatiotrans/).
在某些承诺下(例如,具有树状结构),它是possible https://stackoverflow.com/questions/44301893/how-to-check-for-a-sub-property-at-all-levels-expanded-from-a-sparql-wildcard找出一些东西使用FILTER NOT EXISTS
然而,这不是一个通用的解决方案。
这个想法是通过两个查询来完成此操作。从本质上来说,这是SELECT
over CONSTRUCT
。顺便说一句,这样的 SPARQL 扩展已经proposed http://ceur-ws.org/Vol-749/paper19.pdf.
让我们使用rdflib /questions/tagged/rdflibOntospy 是基于它的,因为
Ontospy 不提供任何本体编辑功能,也不能用于询问三元组存储。
Input (ontology.ttl
)
@prefix : <http://www.example.org/ontology#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@base <http://www.example.org/ontology> .
<http://www.example.org/ontology> rdf:type owl:Ontology .
:hasPart rdf:type owl:ObjectProperty .
:Country rdf:type owl:Class ;
rdfs:subClassOf [ rdf:type owl:Restriction ;
owl:onProperty :hasPart ;
owl:someValuesFrom :State
] .
:State rdf:type owl:Class ;
rdfs:subClassOf [ rdf:type owl:Restriction ;
owl:onProperty :hasPart ;
owl:someValuesFrom :City
] .
:City rdf:type owl:Class .
Python代码
import rdflib
g = rdflib.Graph()
g.parse("ontology.ttl", format="n3")
qres = g.update(
"""PREFIX : <http://www.example.org/ontology#>
INSERT { ?c :hasSome ?p }
WHERE { ?c rdfs:subClassOf [ owl:onProperty :hasPart ;
owl:someValuesFrom ?p ] }""")
qres = g.query(
"""PREFIX : <http://www.example.org/ontology#>
SELECT ?a ?b WHERE {?a :hasSome+ ?b }""")
for row in qres:
print("%s :hasSome+ %s" % row)
qres = g.update(
"""PREFIX : <http://www.example.org/ontology#>
DELETE { ?s :hasSome ?o } WHERE { ?s :hasSome ?o }""")
Output
:Country :hasSome+ :State
:State :hasSome+ :City
:Country :hasSome+ :City
如果您不想修改初始 RDFLib 图,只需创建另一个图:
import rdflib
g1 = rdflib.Graph()
g1.parse("ontology.ttl", format="n3")
qres = g1.query(
"""PREFIX : <http://www.example.org/ontology#>
CONSTRUCT {?c :hasSome ?p } WHERE {
?c rdfs:subClassOf [ owl:onProperty :hasPart ;
owl:someValuesFrom ?p ] }""")
g2 = rdflib.Graph();
for triple in qres: # quite a few triples
g2.add(triple)
qres = g2.query(
"""PREFIX : <http://www.example.org/ontology#>
SELECT ?a ?b WHERE { ?a :hasSome+ ?b }""")
for row in qres:
print("%s :hasSome+ %s" % row)
也许你可以使用transitiveClosure() http://rdflib.readthedocs.io/en/stable/apidocs/rdflib.html#rdflib.graph.Graph.transitiveClosure or transitive_objects() http://rdflib.readthedocs.io/en/stable/apidocs/rdflib.html#rdflib.graph.Graph.transitive_objects而不是这两种情况下的第二个查询。