I'm trying to extract class's content from owl file which consists of onProperty and someValuesFrom where the someValueFrom consists of class that contain a unionOf (onProperty, someValueFrom and equivalentClass), I have created a SPARQL query to extract these data, however every time it returns blank nodes such as ":b0" and ":b1". Does anyone have any idea what should I do with my query in order to make it provide the needed results. This is my owl file:
<?xml version="1.0"?>
<rdf:RDF
xmlns="http://owl.cs.manchester.ac.uk/2009/07/sssw/people#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:owl="http://www.w3.org/2002/07/owl#"
xmlns:ns0="http://owl.cs.manchester.ac.uk/2009/07/sssw/people#"
xml:base="http://owl.cs.manchester.ac.uk/2009/07/sssw/people">
<owl:Ontology rdf:about="http://owl.cs.manchester.ac.uk/2009/07/sssw/people"/>
<owl:Class rdf:about="http://www.w3.org/2002/07/owl#Thing"/>
<owl:Class rdf:about="http://owl.cs.manchester.ac.uk/2009/07/sssw/people#haulage_worker">
<rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
></rdfs:comment>
<owl:equivalentClass>
<owl:Restriction>
<owl:onProperty>
<owl:ObjectProperty rdf:about="http://owl.cs.manchester.ac.uk/2009/07/sssw/people#works_for"/>
</owl:onProperty>
<owl:someValuesFrom>
<owl:Class>
<owl:unionOf rdf:parseType="Collection">
<owl:Restriction>
<owl:onProperty>
<owl:ObjectProperty rdf:about="http://owl.cs.manchester.ac.uk/2009/07/sssw/people#part_of"/>
</owl:onProperty>
<owl:someValuesFrom>
<owl:Class rdf:about="http://owl.cs.manchester.ac.uk/2009/07/sssw/people#haulage_company"/>
</owl:someValuesFrom>
</owl:Restriction>
<owl:Class rdf:about="http://owl.cs.manchester.ac.uk/2009/07/sssw/people#haulage_company"/>
</owl:unionOf>
</owl:Class>
</owl:someValuesFrom>
</owl:Restriction>
</owl:equivalentClass>
<rdfs:label rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
>haulage worker</rdfs:label>
</owl:Class>
</rdf:RDF>
and This is my SPARQL query that I have created :
prefix abc: <http://owl.cs.manchester.ac.uk/2009/07/sssw/people#>
prefix ghi: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
prefix mno: <http://www.w3.org/2001/XMLSchema#>
prefix owl: <http://www.w3.org/2002/07/owl#>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
prefix list: <http://jena.hpl.hp.com/ARQ/list#>
select distinct ?class ?ObjectProperty ?someValuesFrom ?otherClass where { ?class a owl:Class .
OPTIONAL{
?class owl:equivalentClass ?e .
?e a owl:Restriction .
# ?e owl:onProperty ?ObjectProperty .
?e owl:someValuesFrom [ a owl:Class;
owl:unionOf [ rdf:first ? ObjectProperty;
rdf:rest ?someValuesFrom ; rdf:rest*/rdf:first ?otherClass]] .
}
FILTER( STRSTARTS(STR(?class),STR(owl:)) || STRSTARTS(STR(?class),STR(abc:)))
}group by ?class ?ObjectProperty ?someValuesFrom ?otherClass
order by ?class
and This is the result that I had got :
-------------------------------------------------------------------------------
| class | ObjectProperty | someValuesFrom | otherClass |
===============================================================================
| abc:haulage_company | | | |
| abc:haulage_worker | _:b0 | _:b1 | _:b0 |
| abc:haulage_worker | _:b0 | _:b1 | abc:haulage_company |
| owl:Thing | | | |
-------------------------------------------------------------------------------
but the expected result is :
-----------------------------------------------------------------------------
| 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 | | | |
-----------------------------------------------------------------------------
What should I do with my SPARQL query in order to make return this result?
Many thanks in advance :)
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.
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
.