rdfrdfsblank-nodes

How are blank nodes used in the context of understanding RDF triple statements?


I understand that a named node in RDF is a node that has a name (i.e. can be identified by an IRI), and that a blank node is a node that is not named (i.e. not described via an IRI).

Is it correct to say that a node represents a resource in RDF? In this case, both named and blank nodes would be considered resources.

Looking at an RDF schema I see a number of XML tags that seem to represent nodes (both blank and named). For example:

<rdf:Description rdf:about="http://.../SomeObject">
    <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#Class"/>
    <rdfs:subClassOf rdf:resource="http://.../OtherClass"/>
    <rdfs:subClassOf rdf:nodeID="node1e2d5tndrx143"/>
</rdf:Description>

and

<rdf:Description rdf:nodeID="node1e2d5tndrx60">
    <rdf:type rdf:resource="http://www.w3.org/2000/01/rdf-schema#Datatype"/>
    <owl:oneOf rdf:nodeID="node1e2d5tndrx61"/>
</rdf:Description>

(and because this node references another blank node)

<rdf:Description rdf:nodeID="node1e2d5tndrx61">
    <rdf:type rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#List"/>
    <rdf:first>1</rdf:first>
    <rdf:rest rdf:nodeID="node1e2d5tndrx62"/>
</rdf:Description>

It would seem to me that the resources available at this particular API endpoint include these three nodes, one of which is named http://www.w3.org/2001/XMLSchema#float and two of which are blank (node1e2d5tndrx60, node1e2d5tndrx61)

This link - https://lists.w3.org/Archives/Public/public-esw-thes/2004Nov/0061.html - seemingly an old w3.org on the subject of rdf:about vs rdf:ID vs rdf:nodeID mentions that blank nodes are indicated via the rdf:nodeID attribute.

If both these nodes are 'resources' at this particular API endpoint (I assume they are - please let me know if that is incorrect), so far as I know I could never query for a blank node directly, but that in this particular RDF document the blank nodes are being used to constrain what objects are allowed (via the rdf:range property) for a triple that specifies the hasObjectClass property/predicate:

<rdf:Description rdf:about="http://.../hasSomeObjectClass">
    <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#DatatypeProperty"/>
    <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#FunctionalProperty"/>
    <rdfs:label>Some Object Class</rdfs:label>
    <rdfs:domain rdf:resource="http://..../SomeObject"/>
    <rdfs:range rdf:nodeID="node1e2d5tndrx60"/>
</rdf:Description>

My understanding is that triples using the :hasSomeObjectClass predicate (<subj> <pred> <obj>) will:

  1. Include/can only include subjects that are of rdf:type "SomeObject"
  2. Include/can only include objects that are 'subtyped' of the blank node node1e2d5tndrx60

Lastly, in blank node node1e2d5tndrx60 I see that there is an owl constraint - any allowable object can be considered as part of a list. Presumably a list of objects that share a particular class?

Question

Looking at the domain property of the hasSomeObjectClass resource, I am able to find:

  1. A node that represents the SomeObject class
  2. Many nodes that have the rdfs:subClassOf property and that reference SomeObject as the resource

So in terms of how a triple specification is resolved in which the predicate specifies a domain of this type, I understand conceptually how that can be enforced/resolved.

However I can't see a link between the blank node and how the range constraint could be enforced/resolved. Is it easy to explain on a conceptual level how blank nodes are used in terms of resolving specified triples?

I'm very, very new to the world of Linked Data. Please let me know how this question could be improved on!


Solution

  • Blank nodes identifiers are local identifiers, not IRIs. Blank nodes are disjoint with IRIs and literals as defined in the RDF specification.

    A few popular application of blank nodes are:

    1. Describing multi-component structures such as lists, or grouping of triples, such as the case when an object of a triple being address, which is identified not with an IRI but with a set of triples describing it.
    locn:address [
           rdf:type locn:Address ;
           locn:addressArea "Amsterdam"@en ;
           locn:fullAddress "Oudekerksplein 23"@en ;
           locn:postCode "1012 GX" .
         ] .
    

    This is the most popular way of denoting blank nodes, but they can also be revealed:

    ex:AdddressDeOudeKerk locn:address _:b1 .
    _:b1 rdf:type locn:Address .
    _:b1 locn:addressArea "Amsterdam"@en .
    _:b1 locn:fullAddress "Oudekerksplein 23"@en .
    _:b1 locn:postCode "1012 GX" .
    
    1. Making statements about statements

      2.1. With reification

      2.2. Alternative approaches, for example, the one used in Wikidata.

    For example, in this query

    SELECT ?president ?presidentLabel ?image ?start
    WHERE {
        ?president  wdt:P31 wd:Q5 ;      
             p:P39 [ ps:P39 wd:Q11696;
                     pq:P580 ?start ];
             wdt:P18 ?image .
    
       SERVICE wikibase:label {
               bd:serviceParam wikibase:language "en" .
       }
    
     }
    

    p:P39 is a property for the statement "position held", while ps:P39 is to the value "position held" The blank not is such a statement, which is the value (the object) of the triple pattern ?president p:P39 ?statement for which ?statement ps:P39 wd:Q11696 and ?statement pq:P580 ?start and to ask fora particular characteristic of the statement,in this case "start time" (with qualifier pq:P580)

    1. Anonymous classes in OWL Example:
    :Vegetarian rdf:type owl:Class ;
            owl:equivalentClass [ rdf:type owl:Restriction ;
                                  owl:onProperty :eats ;
                                  owl:allValuesFrom :Vegetable
                                ] .
    
    1. Shapes in SHACL Example:
    :Contract
      rdf:type sh:NodeShape ;
      sh:property [
          rdf:type sh:PropertyShape ;
          sh:path :hasParty ;
          sh:minCount 2 ;
          sh:name "has party" ;
        ] ;
      sh:targetSubjectsOf :hasParty ;
    .