听起来你有一个类是某个交叉类的子类。例如,你可能有
学生⊑人⊓注册了一些课程
在 Protégé OWL 本体编辑器中,这看起来像:
如果您为子类编写 SPARQL 查询,例如,
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
select ?subclass ?superclass where {
?subclass rdfs:subClassOf ?superclass
}
并且您没有推理器来推断其他数据,您不会在结果中将Student视为子类,但您可能会看到一个空白(匿名)节点:
---------------------------------------------------------
| subclass | superclass |
=========================================================
| <http://www.examples.org/school#Student> | _:b0 |
---------------------------------------------------------
要理解为什么会这样,您需要看一下本体的 RDF 序列化。在这种情况下,它是(在 RDF/XML 中):
<rdf:RDF
xmlns="http://www.examples.org/school#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:owl="http://www.w3.org/2002/07/owl#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
<owl:Ontology rdf:about="http://www.examples.org/school"/>
<owl:Class rdf:about="http://www.examples.org/school#Course"/>
<owl:Class rdf:about="http://www.examples.org/school#Person"/>
<owl:Class rdf:about="http://www.examples.org/school#Student">
<rdfs:subClassOf>
<owl:Class>
<owl:intersectionOf rdf:parseType="Collection">
<owl:Class rdf:about="http://www.examples.org/school#Person"/>
<owl:Restriction>
<owl:onProperty>
<owl:ObjectProperty rdf:about="http://www.examples.org/school#enrolledIn"/>
</owl:onProperty>
<owl:someValuesFrom rdf:resource="http://www.examples.org/school#Course"/>
</owl:Restriction>
</owl:intersectionOf>
</owl:Class>
</rdfs:subClassOf>
</owl:Class>
</rdf:RDF>
或者在更易读的 Turtle 中(也更像 SPARQL 查询语法):
@prefix : <http://www.examples.org/school#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
:Student a owl:Class ;
rdfs:subClassOf [ a owl:Class ;
owl:intersectionOf ( :Person [ a owl:Restriction ;
owl:onProperty :enrolledIn ;
owl:someValuesFrom :Course
] )
] .
:Person a owl:Class .
:enrolledIn a owl:ObjectProperty .
:Course a owl:Class .
<http://www.examples.org/school>
a owl:Ontology .
实际上,Student rdfs:subClassOf [ ... ]
数据中有一个三元组,但[ ... ]
是一个空白节点;它是一个匿名的owl:Class
,是其他一些类的交集。推理者可以告诉您,如果X ⊑ ( Y和Z ) 然后X ⊑ Y 和X ⊑ Z,但 SPARQL 查询本身不会这样做。但是,您可以像这样进行更复杂的 SPARQL 查询:
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix owl: <http://www.w3.org/2002/07/owl#>
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
select ?subclass ?superclass where {
{ ?subclass rdfs:subClassOf ?superclass }
union
{ ?subclass rdfs:subClassOf [ owl:intersectionOf [ rdf:rest* [ rdf:first ?superclass ] ] ] }
}
--------------------------------------------------------------------------------------
| subclass | superclass |
======================================================================================
| <http://www.examples.org/school#Student> | _:b0 |
| <http://www.examples.org/school#Student> | <http://www.examples.org/school#Person> |
| <http://www.examples.org/school#Student> | _:b1 |
--------------------------------------------------------------------------------------
两个空白节点分别是匿名交集类和匿名限制类(enrolledIn some Course)。如果您只想要 IRI 结果,您可以使用filter
:
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix owl: <http://www.w3.org/2002/07/owl#>
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
select ?subclass ?superclass where {
{ ?subclass rdfs:subClassOf ?superclass }
union
{ ?subclass rdfs:subClassOf [ owl:intersectionOf [ rdf:rest* [ rdf:first ?superclass ] ] ] }
filter( isIRI( ?superclass ) )
}
--------------------------------------------------------------------------------------
| subclass | superclass |
======================================================================================
| <http://www.examples.org/school#Student> | <http://www.examples.org/school#Person> |
--------------------------------------------------------------------------------------
现在,作为最后一点,如果你想让你的查询更小一点,因为这两个union
ed 模式的唯一区别是连接?subclass
和的路径?superclass
,你实际上可以只用一个属性路径来编写它。(虽然,如Sparql 查询 Subclass 或 EquivalentTo中所述,如果这样做,您可能会遇到 Protégé 的一些问题。)这个想法是您可以重写它:
{ ?subclass rdfs:subClassOf ?superclass }
union
{ ?subclass rdfs:subClassOf [ owl:intersectionOf [ rdf:rest* [ rdf:first ?superclass ] ] ] }
因此,通过使用属性路径,这也消除了对空白节点的需要:
?subclass ( rdfs:subClassOf |
( rdfs:subClassOf / owl:intersectionOf / rdf:rest* / rdf:first ) ) ?superclass
你可以再简化一点
?subclass rdfs:subClassOf/((owl:intersectionOf/rdf:rest*/rdf:first)+) ?superclass
你甚至可以从中删除一层括号,使其成为
?subclass rdfs:subClassOf/(owl:intersectionOf/rdf:rest*/rdf:first)+ ?superclass
但是你必须开始记住优先规则,这不是很有趣。该查询虽然有效:
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix owl: <http://www.w3.org/2002/07/owl#>
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
select ?subclass ?superclass where {
?subclass rdfs:subClassOf/(owl:intersectionOf/rdf:rest*/rdf:first)+ ?superclass
filter( isIRI( ?superclass ) )
}
--------------------------------------------------------------------------------------
| subclass | superclass |
======================================================================================
| <http://www.examples.org/school#Student> | <http://www.examples.org/school#Person> |
--------------------------------------------------------------------------------------