Я пытаюсь извлечь intersectionOf и unionOf в файл OWL, где interesctionOf и unionOf состоят из набора классов, someValuesFrom или / и onProperty. Я создал запрос SPARQL, который извлекает «коллекцию» для intersectionOf, но проблема в том, что некоторые из полученных данных не связаны с классом.

Например, у меня есть класс под названием man. У этого класса есть эквивалентный класс, который представляет собой intersectionOf из трех классов, а именно adult, person и male. Мой запрос SPARQL возвращает некорректный результат: он возвращает, что классы adult, person и male эквивалентны классу man (т.е. эта часть верна), но они также являются эквивалентными классами всем другим классам в моем OWL файл, такой как haulage_worker, что неверно. Вот мой запрос SPARQL:

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

А это мой файл OWL:

<?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>

Это результат, который я получил (это неправильный результат):

-----------------------------------------
    | 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      |
    -----------------------------------------

Ожидаемый результат будет таким:

-----------------------------------------
    | 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           |                 |
    -----------------------------------------

Что мне следует изменить в моем запросе SPARQL, чтобы результат был похож на предыдущую таблицу?

2
Abdullah Almuhaimeed 22 Окт 2013 в 21:47

1 ответ

Лучший ответ

Немного очистив ваш запрос, у нас есть:

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

Ваша проблема заключается в том, что вы выбираете ?class, который может быть любым owl:Class в онтологии (если он начинается с соответствующего префикса), а затем выбираете ?equivalentClass из списка классов пересечений ?x, и ?x не имеет никакого отношения к ?class. (You were also sorting by? no , but I think you meant to sort by? class`.)

Определить правильный запрос для написания будет проще, если мы посмотрим на данные в более удобочитаемом формате, например Turtle. В Turtle класс man:

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

Вы ищете вещи, которые являются owl:Class es, связаны owl:equivalentClass с чем-то еще, что является owl:Class и имеет значение списка для owl:intersectionOf. В SPARQL это не так уж сложно, и запрос фактически имеет ту же структуру, что и этот текст Turtle:

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

Я изменил имя переменной с equivalentClass на otherClass, потому что adult, male и person не эквивалентны на man. Их пересечение есть. Используя инструмент командной строки Jena sparql, вы получите следующие результаты:

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

Этот запрос извлекает только классы, эквивалентные некоторому пересечению. Ожидаемые результаты показали все классы, чьи IRI начинались с abc: или owl:, что означает, что дополнительная структура на самом деле является необязательной, поэтому мы соответствующим образом корректируем запрос, заключая необязательные части в optional { … } , и мы получаем желаемые результаты:

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           |            |
------------------------------------
2
Joshua Taylor 22 Окт 2013 в 22:20
Уважаемый Джошуа Тейлор, теперь все работает нормально :) Большое спасибо за вашу помощь, я очень ценю это.
 – 
Abdullah Almuhaimeed
23 Окт 2013 в 12:23
Рад слышать, что это помогло! В Stack Overflow, когда ответ работает для вас, вы должны принять его, чтобы сообщить другим, что он решил вашу проблему. , и уменьшить количество вопросов без принятых ответов. Это также дает вам и вашему собеседнику немного репутации.
 – 
Joshua Taylor
23 Окт 2013 в 16:10
Убить Джошуа Тейлора, извините, я новичок на веб-сайте Stack Overfollow, я не знал, что должен принять ответ, когда он работает со мной, я думал, что достаточно ответить только в комментариях, извините :)
 – 
Abdullah Almuhaimeed
23 Окт 2013 в 22:21
Не о чем сожалеть! В конце концов, все на какое-то время новы! Я рад, что это смогло вам помочь. Удачного SPARQL'инга!
 – 
Joshua Taylor
23 Окт 2013 в 22:29
Большое спасибо за вашу доброту, Джошуа Тейлор :). И сейчас я работаю над извлечением раздела unionOf и пытаюсь следовать вашим советам, пока не получается, но я продолжаю пытаться и надеюсь, что у меня это сработает :)
 – 
Abdullah Almuhaimeed
23 Окт 2013 в 22:40