Search code examples
rdfowlontologyrdfsblank-nodes

Property with blank node as range


When I define property in ontology, how would I define that range of this property is a "blank" node? For example I want to define property hasPhoneNumber with domain Person. Than I know that person can have more than one phone numbers, so instance of Person will have blank node attached to hasPhoneNumber property and then phone numbers attached to this blank node.


Solution

  • In short, you can't do this. Blank nodes are just another type of resource. Blank nodes act as existential variables in RDF; use of a blank node in a graph says that some resource exists and stands in certain relationships to other. For instance, the graph (with no blank nodes):

    :x :hasPhoneNumber :phoneNumberList .
    :phoneNumbeList rdf:value "phone number 1", "phone number 2" .
    

    entails the following graph (with blank nodes):

    :x :hasPhoneNumber [ rdf:value "phone number 1", "phone number 2" ] .
    

    For more about this treatment, see 1.5. Blank Nodes as Existential Variables from the W3C recommendation, RDF Semantics.

    At the RDF and RDFS level, (where you'd be defining domains and ranges of properties) to distinguish whether a resource is a URI resource or a blank node. It's not really clear what it would mean either, if you could. By saying that

    :p rdfs:domain :C ;
       rdfs:range  :D .
    

    what you're saying is that any time you see a use of :p, e.g.,

    :a :p :b .
    

    that you can add the following triples to the graph:

    :a rdf:type :C .
    :b rdf:type :D .
    

    Notice since rdfs:domain and rdfs:range are about adding more triples to the graph, it doesn't really matter whether the subject and object of a triple using :p (:a and :b in this case) are blank nodes or URI nodes.

    If you want to have more than one phone number for a person, you could just use multiple triples, and have something like:

    :p :hasPhoneNumber :phoneNumber1 , :phoneNumber2, :phoneNumber3 .
    

    which is the three triples:

    :p :hasPhoneNumber :phoneNumber1 .
    :p :hasPhoneNumber :phoneNumber2 .
    :p :hasPhoneNumber :phoneNumber3 .
    

    Alternatively, if you want to model that a person can have some collection of phone numbers, you might use an RDF container. E.g., with an rdf:List:

    :p :hasPhoneNumber ( :phoneNumber1 :phoneNumber2 :phoneNumber3 ) .
    

    which can be written in full as

    :p :hasPhoneNumber [ rdf:first :phoneNumber1 ;
                         rdf:rest [ rdf:first :phoneNumber2 ;
                                    rdf:rest [ rdf:first :phoneNumber3 ;
                                               rdf:rest  rdf:nil ] ] ] .