Retrieve the collection of unionOf and intersectionOf for each OWL

♀尐吖头ヾ 提交于 2020-01-23 22:03:30

问题


I'm trying to extract intersectionOf and unionOf in an OWL file, where interesctionOf and unionOf consist of collection of classes, someValuesFrom or/and onProperty. I have created a SPARQL query which extracts the "collection" for the intersectionOf, but the problem is that some of the retrieved data are not related to the class.

For example, I have class called man. This class has an equivalent class which is intersectionOf of three classes, namely, adult,person, and male .My SPARQL query returns some incorrect result: it returns that the classes adult, person, and male are equivalent to class man (i.e., this part is correct), but they are also equivalent classes to all other classes in my OWL file such as haulage_worker, which is incorrect. Here is my SPARQL query:

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 ?equivalentClass  
WHERE{ ?class a owl:Class .
FILTER( STRSTARTS(STR(?class),"http://www.w3.org/2002/07/owl#") || STRSTARTS(STR(?class),"http://owl.cs.manchester.ac.uk/2009/07/sssw/people#") 

)

     ?x a owl:Class ; owl:intersectionOf ?list .
     ?list rdf:rest*/rdf:first ?equivalentClass .


   } GROUP BY ?class ?equivalentClass ORDER BY ?no

and 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>
  <owl:Class rdf:about="http://owl.cs.manchester.ac.uk/2009/07/sssw/people#man">
    <owl:equivalentClass>
      <owl:Class>
        <owl:intersectionOf rdf:parseType="Collection">
          <owl:Class rdf:about="http://owl.cs.manchester.ac.uk/2009/07/sssw/people#adult"/>
          <owl:Class rdf:about="http://owl.cs.manchester.ac.uk/2009/07/sssw/people#person"/>
          <owl:Class rdf:about="http://owl.cs.manchester.ac.uk/2009/07/sssw/people#male"/>
        </owl:intersectionOf>
      </owl:Class>
    </owl:equivalentClass>
  </owl:Class>
</rdf:RDF>

This is the output which I got (they are not correct output):

-----------------------------------------
    | class               | equivalentClass |
    =========================================
    | abc:adult           | abc:adult       |
    | abc:adult           | abc:male        |
    | abc:adult           | abc:person      |
    | abc:haulage_company | abc:adult       |
    | abc:haulage_company | abc:male        |
    | abc:haulage_company | abc:person      |
    | abc:haulage_worker  | abc:adult       |
    | abc:haulage_worker  | abc:male        |
    | abc:haulage_worker  | abc:person      |
    | abc:male            | abc:adult       |
    | abc:male            | abc:male        |
    | abc:male            | abc:person      |
    | abc:man             | abc:adult       |
    | abc:man             | abc:male        |
    | abc:man             | abc:person      |
    | abc:person          | abc:adult       |
    | abc:person          | abc:male        |
    | abc:person          | abc:person      |
    | owl:Thing           | abc:adult       |
    | owl:Thing           | abc:male        |
    | owl:Thing           | abc:person      |
    -----------------------------------------

The expected output would be like this:

-----------------------------------------
    | class               | equivalentClass |
    =========================================
    | abc:adult           | abc:adult       |
    | abc:adult           | abc:male        |
    | abc:adult           | abc:person      |
    | abc:haulage_company |                 |
    | abc:haulage_company |                 |
    | abc:haulage_company |                 |
    | abc:haulage_worker  |                 |
    | abc:haulage_worker  |                 |
    | abc:haulage_worker  |                 |
    | abc:male            | abc:adult       |
    | abc:male            | abc:male        |
    | abc:male            | abc:person      |
    | abc:man             | abc:adult       |
    | abc:man             | abc:male        |
    | abc:man             | abc:person      |
    | abc:person          | abc:adult       |
    | abc:person          | abc:male        |
    | abc:person          | abc:person      |
    | owl:Thing           |                 |
    | owl:Thing           |                 |
    | owl:Thing           |                 |
    -----------------------------------------

What should I change in my SPARQL query in order to make my output like the previous table?


回答1:


Cleaning up your query a bit, we have:

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 ?equivalentClass where {
  ?class a owl:Class .
  filter( strstarts(str(?class),str(owl:)) ||     # since "owl:" is an IRI, you can 
          strstarts(str(?class),str(abc:))    )   # use str(owl:) and str(:abc)

  ?x a owl:Class ; 
     owl:intersectionOf ?list .
     ?list rdf:rest*/rdf:first ?equivalentClass .
}
group by ?class ?equivalentClass
order by ?class                                   # ?class, not ?no

Your problem lies in that you're selecting ?class, which can be every owl:Class in the ontology (as long as it starts with an appropriate prefix), and then selecting ?equivalentClass from the list of intersection classes of ?x, and ?x has no connection whatsoever to ?class. (You were also sorting by?no, but I think you meant to sort by?class`.)

Figuring out the right query to write will be easier if we take a look at the data in a more human readable format, e.g., Turtle. In Turtle, the man class is:

ns0:man  a                   owl:Class ;
        owl:equivalentClass  [ a                   owl:Class ;
                               owl:intersectionOf  ( ns0:adult ns0:person ns0:male )
                             ] .

You're looking for things which are owl:Classes, are related by owl:equivalentClass to something else that's an owl:Class, and which has a list value for owl:intersectionOf. This isn't too hard in SPARQL, and the query actually has the same kind of structure as this Turtle text:

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 ?otherClass where {
  ?class a owl:Class ;
         owl:equivalentClass [ a owl:Class ;
                               owl:intersectionOf [ rdf:rest*/rdf:first ?otherClass ] ] .
  filter( strstarts(str(?class),str(owl:)) ||
          strstarts(str(?class),str(abc:))    )
}
group by ?class ?otherClass
order by ?class

I changed the variable name from equivalentClass to otherClass, because adult, male, and person aren't equivalent to man. Their intersection is. Using Jena's command line sparql tool, you'll get results like this:

$ sparql --data data.rdf --query query.rq
------------------------
| class   | otherClass |
========================
| abc:man | abc:adult  |
| abc:man | abc:male   |
| abc:man | abc:person |
------------------------

This query only retrieves classes that are equivalent to some intersection. Your expected results showed all the classes whose IRIs started with abc: or owl:, which means that the extra structure is actually optional, so we adjust the query accordingly by wrapping the optional parts in optional { … }, and we get the kind of results we're looking for:

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 ?otherClass where {
  ?class a owl:Class .
  optional { 
    ?class owl:equivalentClass [ a owl:Class ;
                                 owl:intersectionOf [ rdf:rest*/rdf:first ?otherClass ] ] .
  }
  filter( strstarts(str(?class),str(owl:)) ||
          strstarts(str(?class),str(abc:))    )
}
group by ?class ?otherClass
order by ?class
$ sparql --data data.rdf --query query.rq
------------------------------------
| class               | otherClass |
====================================
| abc:adult           |            |
| abc:haulage_company |            |
| abc:haulage_worker  |            |
| abc:male            |            |
| abc:man             | abc:adult  |
| abc:man             | abc:male   |
| abc:man             | abc:person |
| abc:person          |            |
| owl:Thing           |            |
------------------------------------


来源:https://stackoverflow.com/questions/19524838/retrieve-the-collection-of-unionof-and-intersectionof-for-each-owl

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!