OWL ontology:SPARQL 查询 ObjectProperty 的范围或域,当它们是 unionOf 类

OWL ontology: SPARQL query a range or domain of an ObjectProperty when they're unionOf classes

我必须使用 SPARQL 1.1 端点查询 ontology 版本 1.4,所以我不能使用 OWL 2 语义,如 ClassAssertion 等... ontology 中的多个属性具有以下格式:

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

域或范围是一个以上的并集 class。问题是我想检索具有特定域和范围的所有 classes,但使用以下查询:

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

我没有得到结果,而不是 km4c:hasGeometry。

有没有办法以某种方式查看 Collection 内部的这种目标?

首先,请注意 联合 域和范围的语义可能不是您所期望的。在 OWL 中,当你说 class D 是 属性 P 的定义域时,这意味着只要你有一个断言 P(x,y),你就可以推断出 D(x ).这意味着如果 P 的域是联合 C ⊔ D,那么从P(x,y)可以推断x是C的一个元素 ⊔ D;即,x 是 C 或 D,但您不一定知道是哪个。例如,您可以定义:

有翅膀 rdfs:domain(飞机 ⊔ 鸟)

然后,从 hasWings(x,2),你可以推断出 x 是飞机还是鸟,但你仍然不知道是哪一个。

无论如何,如果您仍然想要联合 class 作为域,您可以这样做。在 OWL ontology 映射的 RDF 序列化中,合并的 classes 在一个 RDF 列表中。查询这些有点复杂,但你当然可以做到。由于您没有提供完整的OWLontology,我们无法查询到您的实际数据(以后请提供完整的,最小的工作数据我们可以使用),但我们可以创建一个简单的 ontology。有两个 classes,A 和 B,以及两个属性,p 和 q。 p的定义域为A,q的定义域为A或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 语法更像是 RDF 的 N3/Turtle 序列化,因此了解该序列化也很有帮助。 unionOf 列表在这里更清楚:

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

现在您可以使用这样的查询来查找属性及其域,或者联合 classes,如果其中一个域是联合 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> |
-----------------------------------------------------

该查询的有趣部分是:

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

表示您遵循从 ?p 到 ?d 的路径,并且路径:

  • 以 rdfs:domain
  • 开头
  • and 之后是零次或多次重复:
    • owl:unionOf
    • 后跟零个或多个 rdf:rest
    • 后跟一个 rdf:first

它与这个问题并不完全相关,但您可能会发现 this answer (disclosure: my answer) to Is it possible to get the position of an element in an RDF Collection in SPARQL? 中关于查询 RDF 列表的讨论很有用。

然后,我也加了

filter isIri(?d)

否则我们会得到代表并集的节点 class,但这是一个您(可能)不想要的空白节点。