An OWL ontology may have classes A, B, and C, and axiom (in DL notation):
A ⊑ (B ⊓ C)
or in approximate Manchester OWL Syntax:
A subClassOf (B and C)
It is logically true that A is a subclass of B, and that A is a subclass of C, but the triples
A rdfs:subClassOf B
A rdfs:subClassOf C
are not necessarily present in the RDF serialization of the OWL ontology. For instance, consider this very simple ontology in Protégé and its RDF serialization in RDF/XML and Turtle:
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://stackoverflow.com/q/19924861/1281433/sample.owl#"
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://stackoverflow.com/q/19924861/1281433/sample.owl"/>
<owl:Class rdf:about="http://stackoverflow.com/q/19924861/1281433/sample.owl#C"/>
<owl:Class rdf:about="http://stackoverflow.com/q/19924861/1281433/sample.owl#B"/>
<owl:Class rdf:about="http://stackoverflow.com/q/19924861/1281433/sample.owl#A">
<rdfs:subClassOf>
<owl:Class>
<owl:intersectionOf rdf:parseType="Collection">
<owl:Class rdf:about="http://stackoverflow.com/q/19924861/1281433/sample.owl#B"/>
<owl:Class rdf:about="http://stackoverflow.com/q/19924861/1281433/sample.owl#C"/>
</owl:intersectionOf>
</owl:Class>
</rdfs:subClassOf>
</owl:Class>
</rdf:RDF>
@prefix : <http://stackoverflow.com/q/19924861/1281433/sample.owl#> .
@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#> .
<http://stackoverflow.com/q/19924861/1281433/sample.owl>
a owl:Ontology .
:B a owl:Class .
:C a owl:Class .
:A a owl:Class ;
rdfs:subClassOf [ a owl:Class ;
owl:intersectionOf ( :B :C )
] .
The serialization has a triple with rdfs:subClassOf
, but the object isn't :B
or :C
, so a query like
:A rdfs:subClassOf ?superclass
won't return the superclasses of :A
. How can I write a SPARQL query that will return those superclasses of :A
?
It sounds like you've got a class that is a subclass of some intersection class. E.g., you might have
In the Protégé OWL ontology editor, this would look like:
If you write a SPARQL query for subclasses, e.g.,
and you don't have a reasoner inferring additional data, you won't see Student as a subclass in your results, but you might see an blank (anonymous) node:
To understand why this is the case, you need to take a look at the RDF serialization of the ontology. In this case, it's (in RDF/XML):
Or in the more human-readable Turtle (which is also more like the SPARQL query syntax):
There is, in fact, a
Student rdfs:subClassOf [ ... ]
triple in the data, but the[ ... ]
is a blank node; it's an anonymousowl:Class
that is the intersection of some other classes. A reasoner would be able to tell you that if X ⊑ (Y and Z) then X ⊑ Y and X ⊑ Z, but a SPARQL query on its own won't do that. You could make a more complex SPARQL query like this that would, though:The two blank nodes are the anonymous intersection class, and the anonymous restriction class (enrolledIn some Course). If you only want IRI results, you can use a
filter
:Now, as final touch, if you want to make your query a bit smaller, since the only difference in those two
union
ed patterns is the path that connects?subclass
and?superclass
, you can actually write this with just one property path. (Although, as noted in Sparql query Subclass or EquivalentTo, you might run into some issues with Protégé if you do this.) The idea is that you can rewrite this:as this, by using property paths, which also removes the need for the blank nodes:
and you can simplify that a bit more to
and you can even remove one level of parentheses from that, to make it
but then you'd have to start remembering the precedence rules, and that's not much fun. The query works though: