I have an owl file I built in Protege. What is the sparql query which will select all the subclasses of a class and all the subclasses of those subclasses, so on and so on (Breadth First Search Sort of Manner)?
This might be answered by Sparql query Subclass or EquivalentTo, but that question and its answer contain a lot more information that what you're asking for here. You can't really enforce the search strategy (depth first vs. breadth first), but you can (sort of) order subclasses by their distance from the root, if there's a unique path from the root to the subclass. First, let's get some sample data:
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
@prefix : <https://stackoverflow.com/q/23094361/1281433/>.
# a
# / \
# b c
# / \ / \
# d e f g
:b rdfs:subClassOf :a .
:c rdfs:subClassOf :a .
:d rdfs:subClassOf :b .
:e rdfs:subClassOf :b .
:f rdfs:subClassOf :c .
:g rdfs:subClassOf :c .
You can use a query like this to get the subclasses of :a
:
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix : <https://stackoverflow.com/q/23094361/1281433/>
select ?subclass where {
?subclass rdfs:subClassOf* :a
}
------------
| subclass |
============
| :a |
| :c |
| :g |
| :f |
| :b |
| :e |
| :d |
------------
The results include :a
because we used the path rdfs:subClassOf*
. This is logically correct, since a class is a subclass of itself, but if you don't want :a
included, you could use rdfs:subClassOf+
, or you could filter out :a
with filter( ?subclass != :a )
.
In the case that there's a single path from the root to the subclass, you can count the intermediate nodes between them to determine their depth. If you order by depth in this way, then you'll get your results in something like what a breadth first search would give you the following. This technique is described in more detail in Is it possible to get the position of an element in an RDF Collection in SPARQL? and Calculate length of path between nodes?.
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix : <https://stackoverflow.com/q/23094361/1281433/>
select ?subclass (count(?intermediate)-1 as ?depth) where {
?subclass rdfs:subClassOf* ?intermediate .
?intermediate rdfs:subClassOf* :a .
}
group by ?subclass
order by ?depth
--------------------
| subclass | depth |
====================
| :a | 0 |
| :b | 1 |
| :c | 1 |
| :d | 2 |
| :e | 2 |
| :f | 2 |
| :g | 2 |
--------------------