2

I have to query an ontology version 1.4, with a SPARQL 1.1 endpoint, so I can't use the OWL 2 semantic like ClassAssertion etc... several properties in the ontology have this format:

    <owl:ObjectProperty rdf:about="&km4c;hasGeometry">
    <rdfs:comment>some services and all railway elements have a specific geometry like polygons or linestrings</rdfs:comment>
    <rdfs:range rdf:resource="&gis;Geometry"/>
    <rdfs:domain>
        <owl:Class>
            <owl:unionOf rdf:parseType="Collection">
                <rdf:Description rdf:about="&km4c;RailwayElement"/>
                <rdf:Description rdf:about="&km4c;Service"/>
            </owl:unionOf>
        </owl:Class>
    </rdfs:domain>
</owl:ObjectProperty>

with domain or range that is a Union of more than one class. The problem is that i want to retrieve all the classes with a certain domain and range, but with the following query:

SELECT DISTINCT ?p
{
    ?p rdfs:range gis:Geometry.
    ?p rdfs:domain km4c:Service
}

i get no result, instead of km4c:hasGeometry.

Is there a way to somehow look inside the Collection with this kind of goal?

1 Answers1

3

First, note that the semantics of union of domains and ranges may not be what you expect. In OWL, when you say that class D is a domain of property P, it means that whenever you have an assertion P(x,y), you can infer that D(x). That means that if a domain of P is a union C &sqcup; D, then from P(x,y), you can infer that x is an element of C &sqcup; D; i.e., that x is either a C or a D, but you don't necessarily know which. For instance, you might define:

        hasWings rdfs:domain (Airplane &sqcup; Bird)

Then, from hasWings(x,2), you could infer that x is an Airplane or a Bird, but you still wouldn't know which.

Anyhow, if you still want a union class as a domain, you can do that. In the RDF serialization of the mapping of the OWL ontology, the unioned classes are in an RDF list. It's a little bit more complicated to query over those, but you can certainly do it. Since you didn't provide a complete OWL ontology, we can't query over your actual data (in the future, please provide complete, minimal working data that we can use), but we can create a simple ontology. There are two classes, A and B, and two properties, p and q. The domain of p is A, and the domain of q is A or B:

<rdf:RDF
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns="http://example.org/"
    xmlns:owl="http://www.w3.org/2002/07/owl#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema#">
  <owl:Ontology rdf:about="http://example.org/"/>
  <owl:Class rdf:about="http://example.org/#A"/>
  <owl:Class rdf:about="http://example.org/#B"/>
  <owl:ObjectProperty rdf:about="http://example.org/#q">
    <rdfs:domain>
      <owl:Class>
        <owl:unionOf rdf:parseType="Collection">
          <owl:Class rdf:about="http://example.org/#A"/>
          <owl:Class rdf:about="http://example.org/#B"/>
        </owl:unionOf>
      </owl:Class>
    </rdfs:domain>
  </owl:ObjectProperty>
  <owl:ObjectProperty rdf:about="http://example.org/#p">
    <rdfs:domain rdf:resource="http://example.org/#A"/>
  </owl:ObjectProperty>
</rdf:RDF>

SPARQL syntax is much more like the N3/Turtle serialization of RDF, so it's helpful to see that serialization, too. The unionOf list is much clearer here:

@prefix :      <http://example.org/> .
@prefix rdf:   <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix owl:   <http://www.w3.org/2002/07/owl#> .
@prefix xsd:   <http://www.w3.org/2001/XMLSchema#> .
@prefix rdfs:  <http://www.w3.org/2000/01/rdf-schema#> .

<http://example.org/#A>
        a       owl:Class .

<http://example.org/#p>
        a            owl:ObjectProperty ;
        rdfs:domain  <http://example.org/#A> .

<http://example.org/#B>
        a       owl:Class .

<http://example.org/#q>
        a            owl:ObjectProperty ;
        rdfs:domain  [ a            owl:Class ;
                       owl:unionOf  ( <http://example.org/#A> <http://example.org/#B> )
                     ] .

:       a       owl:Ontology .

Now you can use a query like this to find properties and their domains, or the unioned classes if one of the domains is a union class:

prefix :      <http://example.org/>
prefix rdf:   <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
prefix owl:   <http://www.w3.org/2002/07/owl#>
prefix xsd:   <http://www.w3.org/2001/XMLSchema#>
prefix rdfs:  <http://www.w3.org/2000/01/rdf-schema#>

select ?p ?d where {
  ?p rdfs:domain/(owl:unionOf/rdf:rest*/rdf:first)* ?d
  filter isIri(?d)
}
-----------------------------------------------------
| p                       | d                       |
=====================================================
| <http://example.org/#q> | <http://example.org/#A> |
| <http://example.org/#q> | <http://example.org/#B> |
| <http://example.org/#p> | <http://example.org/#A> |
-----------------------------------------------------

The interesting parts of that query are:

?p rdfs:domain/(owl:unionOf/rdf:rest*/rdf:first)* ?d

which says you follow a path from ?p to ?d, and the path:

  • starts with rdfs:domain
  • and is followed by zero or more repetitions of:
    • owl:unionOf
    • followed by zero or more rdf:rest
    • followed by a single rdf:first

It's not exactly related to this question, but you may find the discussion of querying RDF lists in this answer (disclosure: my answer) to Is it possible to get the position of an element in an RDF Collection in SPARQL? useful.

Then, I also added

filter isIri(?d)

because otherwise we get the node that represents the union class, but that's a blank node that you (probably) don't want.

Community
  • 1
  • 1
Joshua Taylor
  • 80,876
  • 9
  • 135
  • 306