Can I specify a range for rdf:List members?

2019-04-12 23:55发布

If I want to say that the title of something should be an rdfs:Literal, I do this:

example:title a owl:DatatypeProperty ;
    rdfs:range rdfs:Literal .

Now I want to express that something has an ordered list of titles:

example:titles a rdf:List .

How do I specify what the members of the list should be? Do I need to subclass rdf:List?

UPDATE: I would like to keep using rdf:List if possible, based on the answer by Joshua I think the following says that any rdf:List with only rdfs:Literal values is an example:ListOfLiterals, and I can then use that as a range.

@prefix entity: <http://example.com/stuff/> .
@prefix example: <http://example.com/my/term/> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .

example:ListOfLiterals a owl:Class ;
    owl:equivalentClass [
        a owl:Class ;
        owl:intersectionOf (
            rdf:List
            [
                a owl:Restriction ;
                owl:allValuesFrom rdfs:Literal ;
                owl:onProperty rdf:first
            ]
            [
                a owl:Restriction ;
                owl:allValuesFrom example:ListOfLiterals ;
                owl:onProperty rdf:rest
            ] )
    ] .

example:Book a owl:Class .

example:titles a owl:DatatypeProperty ;
    rdfs:domain example:Book ;
    rdfs:range example:ListOfLiterals .

entity:somebook a example:Book ;
    example:titles ( "Book Title"@en "Second Book Title"@en ) .

Does that make any sense, or did I misunderstand something?

标签: rdf
1条回答
手持菜刀,她持情操
2楼-- · 2019-04-13 00:40

First, note that using rdf:Lists in your OWL code means that you're going to be in OWL Full, whereas many of the reasoners are designed to work with OWL DL. You might be OK with this, and if you are, then great. If you need to remain in OWL DL, then you'll have to use your own vocabulary for lists, e.g., a class warp:List and properties warp:first and warp:rest, and use those instead of their RDF counterparts.

At any rate, once you've decided on your List class and your first and rest properties, you can define a list type ListOfElements that can only contain members of some class Element with the following restriction:

ElementList ⊑ List and (first only Element) and (rest only ElementList)

This means that an ElementList is: (i) a List; (ii) has an value for the first property that is an Element; and (iii) has an ElementList as its rest, which means that the rest of the things in the List must also be Elements. Whatever the nil object is should already be declared as a List, but you may also want to include:

nil a ElementList

but this isn't necessarily as important. For your case, you'd want to define a class TitleList in a similar fashion, and then declare the range of your property as TitleList.

Here's an example ontology that includes just defines these type of List class and an ElementList class (in human readable Turtle):

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

:rest   a            owl:ObjectProperty ;
        rdfs:domain  :List ;
        rdfs:range   :List .

:List   a       owl:Class .

:nil    a       owl:NamedIndividual , :ElementList , :List .

:ElementList  a          owl:Class ;
        rdfs:subClassOf  [ a                   owl:Class ;
                           owl:intersectionOf  ( :List [ a                  owl:Restriction ;
                                                         owl:allValuesFrom  :Element ;
                                                         owl:onProperty     :first
                                                       ] [ a                  owl:Restriction ;
                                                           owl:allValuesFrom  :ElementList ;
                                                           owl:onProperty     :rest
                                                         ] )
                         ] .

:Element  a     owl:Class .

:first  a            owl:ObjectProperty ;
        rdfs:domain  :List .

<http://stackoverflow.com/a/19480798/1281433/code>
        a       owl:Ontology .

[ a                      owl:Axiom ;
  rdfs:comment           "It's probably a good idea to specify that nil is an ElementList.  This could also be inferred, though, if there is a nil-terminated List that is known to be an ElementList." ;
  owl:annotatedProperty  rdf:type ;
  owl:annotatedSource    :nil ;
  owl:annotatedTarget    :ElementList
] .

For full generality, I've defined new a new List class, first and rest properties, and an individual nil, but if OWL Full is OK with you, then you can just use rdf:List, etc. For completeness, here's the same ontology in RDF/XML:

<rdf:RDF
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:owl="http://www.w3.org/2002/07/owl#"
    xmlns="http://stackoverflow.com/a/19480798/1281433/code#"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
  <owl:Ontology rdf:about="http://stackoverflow.com/a/19480798/1281433/code"/>
  <owl:Class rdf:about="http://stackoverflow.com/a/19480798/1281433/code#List"/>
  <owl:Class rdf:about="http://stackoverflow.com/a/19480798/1281433/code#ElementList">
    <rdfs:subClassOf>
      <owl:Class>
        <owl:intersectionOf rdf:parseType="Collection">
          <owl:Class rdf:about="http://stackoverflow.com/a/19480798/1281433/code#List"/>
          <owl:Restriction>
            <owl:onProperty>
              <owl:ObjectProperty rdf:about="http://stackoverflow.com/a/19480798/1281433/code#first"/>
            </owl:onProperty>
            <owl:allValuesFrom>
              <owl:Class rdf:about="http://stackoverflow.com/a/19480798/1281433/code#Element"/>
            </owl:allValuesFrom>
          </owl:Restriction>
          <owl:Restriction>
            <owl:onProperty>
              <owl:ObjectProperty rdf:about="http://stackoverflow.com/a/19480798/1281433/code#rest"/>
            </owl:onProperty>
            <owl:allValuesFrom rdf:resource="http://stackoverflow.com/a/19480798/1281433/code#ElementList"/>
          </owl:Restriction>
        </owl:intersectionOf>
      </owl:Class>
    </rdfs:subClassOf>
  </owl:Class>
  <owl:ObjectProperty rdf:about="http://stackoverflow.com/a/19480798/1281433/code#rest">
    <rdfs:range rdf:resource="http://stackoverflow.com/a/19480798/1281433/code#List"/>
    <rdfs:domain rdf:resource="http://stackoverflow.com/a/19480798/1281433/code#List"/>
  </owl:ObjectProperty>
  <owl:ObjectProperty rdf:about="http://stackoverflow.com/a/19480798/1281433/code#first">
    <rdfs:domain rdf:resource="http://stackoverflow.com/a/19480798/1281433/code#List"/>
  </owl:ObjectProperty>
  <owl:Axiom>
    <rdfs:comment>It's probably a good idea to specify that nil is an ElementList.  This could also be inferred, though, if there is a nil-terminated List that is known to be an ElementList.</rdfs:comment>
    <owl:annotatedTarget rdf:resource="http://stackoverflow.com/a/19480798/1281433/code#ElementList"/>
    <owl:annotatedSource>
      <owl:NamedIndividual rdf:about="http://stackoverflow.com/a/19480798/1281433/code#nil">
        <rdf:type rdf:resource="http://stackoverflow.com/a/19480798/1281433/code#ElementList"/>
        <rdf:type rdf:resource="http://stackoverflow.com/a/19480798/1281433/code#List"/>
      </owl:NamedIndividual>
    </owl:annotatedSource>
    <owl:annotatedProperty rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#type"/>
  </owl:Axiom>
</rdf:RDF>
查看更多
登录 后发表回答