diff --git a/spec/rendered.html b/spec/rendered.html index 212eaa7..203f42c 100644 --- a/spec/rendered.html +++ b/spec/rendered.html @@ -1,16 +1,16 @@ - + - + + -
+

RML-CC: Collections and Containers in RML

Draft Community Group Report - +

@@ -286,9 +275,9 @@

RML-CC: Collections and Containers in RML

RML-CC: Collections and Containers in RML

Learn more about W3C Community and Business Groups. -

+

1. Conformance

As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.

The key words MAY, MUST, and SHOULD in this document are to be interpreted as described in @@ -332,7 +321,7 @@

RML-CC: Collections and Containers in RML

described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.

2.2 Document conventions

We assume readers have basic familiarity with RDF and RML.

-

In this document, examples assume +

In this document, examples assume http://example.org/ as the base IRI provided to the RML engine and the following namespace prefix bindings unless otherwise stated:

@@ -403,14 +392,16 @@

RML-CC: Collections and Containers in RML

The associated RML mapping starts as follows:

@prefix rml: <http://w3id.org/rml/>.
-@prefix ql:  <http://semweb.mmlab.be/ns/ql#>.
 @prefix ex:  <http://example.com/ns>.
-@base        <http://example.com/ns>.
 
 <#TM> a rml:TriplesMap;
   rml:logicalSource [
-    rml:source "data.json" ;
-    rml:referenceFormulation ql:JSONPath ;
+    rml:referenceFormulation rml:JSONPath;
+    rml:source [ 
+        a rml:RelativePathSource;
+        rml:root rml:MappingDirectory;
+        rml:path "data.json"
+    ] ;
     rml:iterator "$.*" ;
   ];
 
@@ -448,18 +439,18 @@ 

RML-CC: Collections and Containers in RML

rml:predicateObjectMap [
   rml:predicate ex:with ;
   rml:objectMap [
-      rml:template "list/{id}" ;
+      rml:template "list{id}" ;
       rml:gather ( [ rml:reference "values.*" ; ] ) ;
       rml:gatherAs rdf:List ;
   ] ;
 ] ;

will yield the following output:

-
:a ex:with :list/a . :list/a rdf:first "1" ; rdf:rest ("2" "3") .
-:b ex:with :list/b . :list/b rdf:first "4" ; rdf:rest ("5" "6") .
-:c ex:with :list/c . :list/c rdf:first "7" ; rdf:rest ("8" "9") .
+
:a ex:with :lista . :lista rdf:first "1" ; rdf:rest ("2" "3") .
+:b ex:with :listb . :listb rdf:first "4" ; rdf:rest ("5" "6") .
+:c ex:with :listc . :listc rdf:first "7" ; rdf:rest ("8" "9") .
-

This is similar to the previous example, yet in this case the head node of each produced collection is assigned an IRI :list/a, :list/b and :list/c.

+

This is similar to the previous example, yet in this case the head node of each produced collection is assigned an IRI :lista, :listb and :listc.

5. Vocabulary definition

This section introduces the classes, properties, and constants of the RML Containers and Collections specification.

@@ -470,6 +461,7 @@

RML-CC: Collections and Containers in RML

  • A rml:GatherMap MUST have exactly one rml:gatherAs property.
  • A rml:GatherMap MAY have zero or exactly one rml:strategy property.
  • +

    5.1.2 rml:Strategy

    A strategy is a plan or set of actions designed to achieve a specific goal or outcome. Instances of rml:Strategy represent ways to perform an action such as combining two collections and containers. See constants for examples.

    5.2 Properties

    5.2.1 rml:gather

    The rml:gather informs the RML processor where the terms of a collection or container come from. This property relates a gather map with a non-empty list of term maps. @@ -478,7 +470,7 @@

    RML-CC: Collections and Containers in RML

  • The domain of rml:gather is rml:GatherMap.
  • The range of rml:gather is a non-empty list (rdf:List) of rml:TermMap instances. In particular, this list may include instances of rml:GatherMap thus allowing for nested gather maps.
  • -

    5.2.2 rml:strategy

    +

    5.2.2 rml:strategy

    Declaring an rml:strategy in a gather map informs the processor about how to create collections and containers when faced with multi-valued term maps. This specification defines rml:append and rml:cartesianProduct as instances of rml:Strategy.

    In the rml:append strategy, the sets of RDF terms generated by each term map of the gather map are simply appended to the collection (respectively container) being constructed. Thus, only one collection (respectively container) is generated.

    @@ -500,8 +492,7 @@

    RML-CC: Collections and Containers in RML

  • The range of rml:allowEmptyListAndContainer is xsd:boolean.
  • Property rml:allowEmptyListAndContainer is optional, it takes the value false by default.

    -

    5.3 Constants

    -

    5.3.1 rml:append

    +

    5.3 Constants

    5.3.1 rml:append

    rml:append is an instance of class rml:Strategy. Used as the object of property rml:strategy, it informs the processor that the sets of RDF terms generated by each term map of the gather map are to be appended within the collection or container. The order is that in which the term maps are declared in the gather map. Example:

    For the input document:

    @@ -557,16 +548,16 @@

    RML-CC: Collections and Containers in RML

    rml:predicateObjectMap [
       rml:predicate ex:with ;
       rml:objectMap [
    -      rml:template "seq/{id}" ;
    +      rml:template "seq{id}" ;
           rml:gather ( [ rml:reference "values.*" ; ] ) ;
           rml:gatherAs rdf:Seq ;
       ] ;
     ] ;

    will yield the following output:

    -
    :a ex:with :seq/a . :seq/a rdf:_1 "1" ; rdf:_2 "2" , rdf:_3 "3" .
    -:b ex:with :seq/b . :seq/b rdf:_1 "4" ; rdf:_2 "5" , rdf:_3 "6" .
    -:c ex:with :seq/c . :seq/c rdf:_1 "7" ; rdf:_2 "8" , rdf:_3 "9"  .
    +
    :a ex:with :seqa . :seqa rdf:_1 "1" ; rdf:_2 "2" , rdf:_3 "3" .
    +:b ex:with :seqb . :seqb rdf:_1 "4" ; rdf:_2 "5" , rdf:_3 "6" .
    +:c ex:with :seqc . :seqc rdf:_1 "7" ; rdf:_2 "8" , rdf:_3 "9"  .

    6.3 Generating well-formed named collections or containers

    @@ -600,15 +591,15 @@

    RML-CC: Collections and Containers in RML

    rml:predicateObjectMap [
       rml:predicate ex:with ;
       rml:objectMap [
    -      rml:template "list/{id}" ;
    +      rml:template "list{id}" ;
           rml:gather ( [ rml:reference "values.*" ; ] ) ;
           rml:gatherAs rdf:List ;
       ] ;
     ] ;

    The processor must generate the following output:

    -
    :a ex:with :list/a . :list/a rdf:first "1" ; rdf:rest ("2" "3" "7" "8" "9") .
    -:b ex:with :list/b . :list/b rdf:first "4" ; rdf:rest ("5" "6") .
    +
    :a ex:with :lista . :lista rdf:first "1" ; rdf:rest ("2" "3" "7" "8" "9") .
    +:b ex:with :listb . :listb rdf:first "4" ; rdf:rest ("5" "6") .

    It is assumed that a processor will concatenate the collections or containers while respecting the order of the iterations as provided by the logical source.

    6.3.2 Named collections or containers generated by a multi-valued gather map

    Let's consider the following input document:

    @@ -638,7 +629,7 @@

    RML-CC: Collections and Containers in RML

    Now, when an rml:template, rml:constant or rml:reference is provided, to avoid generating ill-formed lists that would share the same head node IRI, the processor must concatenate the lists.

    If we add an rml:template in the object map:

    rml:objectMap [
    -  rml:template "list/{id}" ;
    +  rml:template "list{id}" ;
       rml:gather ( [ rml:reference "a.*" ] [ rml:reference "b.*" ]) ;
       rml:gatherAs rdf:List ;
       rml:strategy rml:cartesianProduct ;
    @@ -668,7 +659,7 @@ 

    RML-CC: Collections and Containers in RML

    rml:predicateObjectMap [ rml:predicate ex:with ; rml:objectMap [ - rml:template "list/{id}" ; + rml:template "list{id}" ; rml:gather ( [ rml:reference "values1.*" ; ] [ rml:reference "values2.*" ; ] ) ; rml:gatherAs rdf:List ; ] ; @@ -677,14 +668,14 @@

    RML-CC: Collections and Containers in RML

    For each document, the values of values1 and values2 are appended in the same list, as per the default rml:append strategy. Furthermore, the lists generated for id "a" must be concatenated since they share the same head node IRI, as explained in the multiple iterations case. The expected output is:

    -
    :a ex:with :list/a .
    -:list/a rdf:first "1" ; rdf:rest ("a" "b" "5" "6" "e") .
    -:b ex:with :list/b .
    -:list/b rdf:first "3" ; rdf:rest ("4" "c" "d") .
    +
    :a ex:with :lista .
    +:lista rdf:first "1" ; rdf:rest ("a" "b" "5" "6" "e") .
    +:b ex:with :listb .
    +:listb rdf:first "3" ; rdf:rest ("4" "c" "d") .

    Now let's change the default strategy to rml:cartesianProduct:

    rml:objectMap [
    -    rml:template "list/{id}" ;
    +    rml:template "list{id}" ;
         rml:gather ( [ rml:reference "values1.*" ; ] [ rml:reference "values2.*" ; ] ) ;
         rml:gatherAs rdf:List ;
         rml:strategy rml:cartesianProduct ;
    @@ -696,10 +687,10 @@ 

    RML-CC: Collections and Containers in RML

    Similarly, for the documents with id "a", the result is: ("1" "a" "1" "b") and ("5" "e" "6" "e"). But again, these lists must be concatenated since they share the same head node IRI, as explained in the multiple iterations case.

    Therefore, the processor must now generate the following output:

    -
    :a ex:with :list/a .
    -:list/a rdf:first "1" ; rdf:rest ("a" "1" "b" "5" "e" "6" "e") .
    -:b ex:with :list/b .
    -:list/b rdf:first "3" ; rdf:rest ("c" "3" "d" "4" "c" "4" "d") .
    +
    :a ex:with :lista .
    +:lista rdf:first "1" ; rdf:rest ("a" "1" "b" "5" "e" "6" "e") .
    +:b ex:with :listb .
    +:listb rdf:first "3" ; rdf:rest ("c" "3" "d" "4" "c" "4" "d") .

    7. Examples (Informative)

    In this section, we present additional examples and describe the expected output.

    7.1 Dealing with empty collections and containers

    @@ -733,7 +724,7 @@

    RML-CC: Collections and Containers in RML

    rml:predicateObjectMap [
       rml:predicate ex:with ;
       rml:objectMap [
    -      rml:template "list/{id}" ;
    +      rml:template "list{id}" ;
           rml:allowEmptyListAndContainer true ;
           rml:gather ( [ rml:reference "values.*" ; ] ) ;
           rml:gatherAs rdf:List ;
    @@ -742,12 +733,12 @@ 

    RML-CC: Collections and Containers in RML

    then the document with "id": "d" entails an empty list, that is a list whose head node is rdf:nil and therefore has no IRI. We expect the following output where

    -
    :a ex:with :list/a .
    -:list/a rdf:first "1" ; rdf:rest ("2" "3") .
    -:b ex:with :list/b .
    -:list/b rdf:first "4" ; rdf:rest ("5" "6") .
    -:c ex:with :list/c .
    -:list/c rdf:first "7" ; rdf:rest ("8" "9") .
    +
    :a ex:with :lista .
    +:lista rdf:first "1" ; rdf:rest ("2" "3") .
    +:b ex:with :listb .
    +:listb rdf:first "4" ; rdf:rest ("5" "6") .
    +:c ex:with :listc .
    +:listc rdf:first "7" ; rdf:rest ("8" "9") .
     :d ex:with () .
    @@ -812,7 +803,7 @@

    RML-CC: Collections and Containers in RML

    The following mapping will relate instances of authors to names. The names of authors are, for the sake of the example, represented as bags containing a title, first name, and lastname.

    <#AuthorTM>
         rml:logicalTable [ rml:tableName "AUTHOR" ; ] ;
    -    rml:subjectMap [ rml:template "/person/{ID}" ; ] ;
    +    rml:subjectMap [ rml:template "/person{ID}" ; ] ;
         rml:predicateObjectMap [
             rml:predicate ex:name ;
             rml:objectMap [
    @@ -826,9 +817,9 @@ 

    RML-CC: Collections and Containers in RML

    .

    In this example we generate, for each row in table AUTHOR, an blank node of type rdf:Bag. Each such bag "gathers" values from different term maps. The execution of this mapping will produce the following result:

    -
    :person/1 ex:name [ a rdf:Bag; rdf:_1 "Mary"; rdf:_2 "Shelley" ] . 
    -:person/2 ex:name [ a rdf:Bag; rdf:_1 "Sir"; rdf:_2 "Terry"; rdf:_3 "Pratchett" ] . 
    -:person/3 ex:name [ a rdf:Bag; rdf:_1 "Stephen"; rdf:_2 "Baxter" ] .
    +
    :person1 ex:name [ a rdf:Bag; rdf:_1 "Mary"; rdf:_2 "Shelley" ] . 
    +:person2 ex:name [ a rdf:Bag; rdf:_1 "Sir"; rdf:_2 "Terry"; rdf:_3 "Pratchett" ] . 
    +:person3 ex:name [ a rdf:Bag; rdf:_1 "Stephen"; rdf:_2 "Baxter" ] .

    While not shown in this example, different term maps allow to collect terms of different types: resources, literals, typed or language-tagged literals, etc. The fourth record in the table did not generate a bag, since each term map in the gather map did not yield a value. By default, empty lists and containers are withheld. One does have the possibility to keep those with rml:allowEmptyListAndContainer`.

    @@ -836,7 +827,7 @@

    RML-CC: Collections and Containers in RML

    Continuing with the relational data example, here we relate books to authors with a rml:parentTriplesMap. The authors of a book are represented as a list.

    <#BookTM>
         rml:logicalTable [ rml:tableName "BOOK" ; ] ;
    -    rml:subjectMap [ rml:template "/book/{ID}" ; ] ;
    +    rml:subjectMap [ rml:template "/book{ID}" ; ] ;
         rml:predicateObjectMap [
             rml:predicate ex:writtenBy ;
             rml:objectMap [
    @@ -853,20 +844,23 @@ 

    RML-CC: Collections and Containers in RML

    .

    Intuitively, we will join each record (or iteration) with data from the parent triples map. The join may yield one or more results, which are then gathered into a list. The execution of this mapping will produce the following RDF:

    -
    :book/1 ex:writtenby ( :person/1 ) . 
    -:book/2 ex:writtenby ( :person/2 :person/3 ) .
    +
    :book1 ex:writtenby ( :person1 ) . 
    +:book2 ex:writtenby ( :person2 :person3 ) .

    In RML, it is assumed that each term map is multi-valued. That this, each term map may return one or more values. The default behavior is to append the values in the order of the term maps appearing in the gather map.

    7.4 Using a gather map in a subject map

    Here we exemplify the use of a term map in a subject map. Continuing with the JSON file from the running example, the following mapping generates an RDF sequence whose head node is used to state provenance information on that sequence:

    <#TM> a rml:TriplesMap;
       rml:logicalSource [
    -    rml:source "data.json" ;
    -    rml:referenceFormulation ql:JSONPath ;
    +    rml:source [ 
    +        a rml:RelativePathSource;
    +        rml:root rml:MappingDirectory;
    +        rml:path "data.json"
    +    ] ;
         rml:iterator "$.*" ;
       ];
     
       rml:subjectMap [
    -    rml:template "seq/{id}" ;
    +    rml:template "seq{id}" ;
         rml:gather ( [ rml:reference "values.*" ; ] ) ;
         rml:gatherAs rdf:Seq ;  
       ] ;
    @@ -877,14 +871,14 @@ 

    RML-CC: Collections and Containers in RML

    ] .

    The expected result is:

    -
    :seq/a rdf:_1 "1" ; rdf:_2 "2" ; rdf:_3 "3" .
    -:seq/a prov:wasDerivedFrom <data.json> .
    +
    :seqa rdf:_1 "1" ; rdf:_2 "2" ; rdf:_3 "3" .
    +:seqa prov:wasDerivedFrom <data.json> .
     
    -:seq/b rdf:_1 "4" ; rdf:_2 "5" ; rdf:_3 "6" .
    -:seq/b prov:wasDerivedFrom <data.json> .
    +:seqb rdf:_1 "4" ; rdf:_2 "5" ; rdf:_3 "6" .
    +:seqb prov:wasDerivedFrom <data.json> .
     
    -:seq/c rdf:_1 "7" ; rdf:_2 "8" ; rdf:_3 "9" .
    -:seq/c prov:wasDerivedFrom <data.json> .
    +:seqc rdf:_1 "7" ; rdf:_2 "8" ; rdf:_3 "9" . +:seqc prov:wasDerivedFrom <data.json> .
    @@ -1130,4 +1124,4 @@

    RML-CC: Collections and Containers in RML

    panel.hidden = true; panel.classList.remove("docked"); } -})() \ No newline at end of file +})() \ No newline at end of file