The problem with your query:
It may be easier to understand the results of the SPARQL query if you look at your data in the Turtle serialization rather than the RDF/XML serialization. The relevant portion of your data is:
ns0:haulage_worker a owl:Class ;
rdfs:comment ""^^xsd:string ;
rdfs:label "haulage worker"^^xsd:string ;
owl:equivalentClass [ a owl:Restriction ;
owl:onProperty ns0:works_for ;
owl:someValuesFrom [ a owl:Class ;
owl:unionOf ( [ a owl:Restriction ;
owl:onProperty ns0:part_of ;
owl:someValuesFrom ns0:haulage_company
] ns0:haulage_company )
]
Consider the match for the part about owl:unionOf
. In your query, it's
owl:unionOf ( [ a owl:Restriction ;
owl:onProperty ns0:part_of ;
owl:someValuesFrom ns0:haulage_company ]
ns0:haulage_company )
The elements of the list are a blank node with some properties, and ns0:haulage_company
. The query that should match some of this data is:
owl:unionOf [ rdf:first ?ObjectProperty;
rdf:rest ?someValuesFrom ;
rdf:rest*/rdf:first ?otherClass ]] .
The thing that will match ?ObjectProperty
is the first element of the list which, in this case, is not an object property, but is a blank node. The thing that will match ?someValuesFrom
is the list node representing the rest of the list.
Fixing your query:
I'm not quite sure exactly what you are trying to return from this query. Based on your expected results, it looks like you're saying that a class ?class
can be related to an owl:someValuesFrom
restriction, in which case you want to bind ?ObjectProperty
and ?someValuesFrom
to the object property and class (if it's not a blank node), and bind ?otherClass
to other related (non-blank) classes otherwise. You said you expected these results:
-----------------------------------------------------------------------------
| class | ObjectProperty | someValuesFrom | otherClass |
=============================================================================
| abc:haulage_company | | | |
| abc:haulage_worker | abc:works_for | | |
| abc:haulage_worker | abc:part_of | haulage_company | haulage_company |
| owl:Thing | | | |
-----------------------------------------------------------------------------
but if my understanding is correct, I think it would be easier and more useful to get something like:
-----------------------------------------------------------------------------
| class | ObjectProperty | someValuesFrom | otherClass |
=============================================================================
| abc:haulage_company | | | |
| abc:haulage_worker | abc:works_for | | |
| abc:haulage_worker | abc:part_of | haulage_company | |
| abc:haulage_worker | | | haulage_company |
| owl:Thing | | | |
-----------------------------------------------------------------------------
You can do that with a query like this:
prefix : <http://owl.cs.manchester.ac.uk/2009/07/sssw/people#>
prefix owl: <http://www.w3.org/2002/07/owl#>
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
select distinct ?class ?onProperty ?someValuesFrom ?otherClass where {
#-- Select each named class.
?class a owl:Class .
filter( !isBlank( ?class ))
optional {
#-- Find "related" classes by following a somewhat complex
#-- property path that will follow equivalent classes,
#-- existential restrictions, and unionOf expressions.
?class (owl:equivalentClass
|owl:someValuesFrom
|(owl:unionOf/rdf:rest*/rdf:first))+ ?r .
#-- Save non-blank related classes as ?otherClass.
bind(if(isBlank(?r),?unbound,?r) as ?otherClass)
#-- If the related class is a restriction, then we can
#-- take its owl:onProperty and owl:someValuesFrom.
optional {
?r owl:onProperty ?onProperty ;
owl:someValuesFrom ?svf .
bind( if(isBlank(?svf),?unbound,?svf) as ?someValuesFrom )
}
}
}
values ?unbound { UNDEF }
The pattern to save values that aren't bound to blank nodes is described in answers to an answers.semanticweb.com question, Binding a variable only when another is non-blank? The idea is to use values ?unbound { UNDEF }
to ensure that ?unbound
always has an undefined value, and then to use bind
and if
to assign either ?unbound
or some other value to a projected variable. In essence, it's this:
bind(if(isBlank(...),?unbound,...) as ...)
values ?unbound { UNDEF }
The results are
-----------------------------------------------------------------------
| class | onProperty | someValuesFrom | otherClass |
=======================================================================
| owl:Thing | | | |
| :haulage_company | | | |
| :haulage_worker | | | |
| :haulage_worker | :works_for | | |
| :haulage_worker | :part_of | :haulage_company | |
| :haulage_worker | | | :haulage_company |
-----------------------------------------------------------------------
This does include a row for :haulage_worker
that doesn't have bindings for any of the other variables, but I think that's OK, since you already wanted such rows for owl:Thing
and :haulage_company
.