diff --git a/.gitignore b/.gitignore
index ea29b39..a820245 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,4 @@
venv
*__pycache__
test-cases/burp.jar
+**/node_modules/
\ No newline at end of file
diff --git a/shapes/lv.ttl b/shapes/lv.ttl
index 6431da2..1d1e9fe 100644
--- a/shapes/lv.ttl
+++ b/shapes/lv.ttl
@@ -240,15 +240,32 @@ rmlsh:LogicalViewJoinShape a sh:NodeShape ;
A field of the logical view join.
""" ;
sh:message """
- At least one rml:field property must be specified for a rml:LogicalViewJoin, with a resource as its value.
+ At least one rml:field property must be specified for a rml:LogicalViewJoin, with a leaf expression field as its value.
""" ;
sh:path rml:field ;
sh:minCount 1 ;
sh:nodeKind sh:BlankNodeOrIRI ;
- sh:or (
- [ sh:node rmlsh:ExpressionFieldShape ]
- [ sh:node rmlsh:IterableFieldShape ]
- )
+ sh:node rmlsh:LeafExpressionFieldShape ;
+ ] .
+
+rmlsh:LeafExpressionFieldShape a sh:NodeShape ;
+ rdfs:label "Leaf Expression Field" ;
+ rdfs:comment """
+ A leaf expression field is an expression field without nested fields.
+ """ ;
+ sh:message """
+ Node must have a valid rml:ExpressionField description.
+ """ ;
+ sh:node rmlsh:ExpressionFieldShape ;
+ sh:property [
+ sh:description """
+ A leaf expression field is an expression field without nested fields.
+ """ ;
+ sh:message """
+ A leaf expression field has no nested fields.
+ """ ;
+ sh:path rml:field ;
+ sh:maxCount 0 ;
] .
rmlsh:StructuralAnnotationShape a sh:NodeShape;
@@ -312,3 +329,33 @@ rmlsh:InclusionAnnotationShape a sh:NodeShape;
sh:maxCount 1 ;
sh:nodeKind sh:BlankNodeOrIRI ;
] .
+
+rmlsh:parentCyclesShape a sh:NodeShape ;
+ sh:targetSubjectsOf rml:viewOn ;
+ sh:targetSubjectsOf rml:field ;
+ sh:sparql [
+ a sh:SPARQLConstraint ;
+ sh:message "There must be no cycles via rml:viewOn or rml:Field." ;
+ sh:select """
+ PREFIX rml:
+ SELECT ?this
+ WHERE {
+ ?this (rml:viewOn|rml:field)+ ?this .
+ }
+ """ ;
+ ] .
+
+rmlsh:joinCyclesShape a sh:NodeShape ;
+ sh:targetSubjectsOf rml:viewOn ;
+ sh:sparql [
+ a sh:SPARQLConstraint ;
+ sh:message "There must be no cycles via rml:viewOn and rml:leftJoin or rml:innerJoin." ;
+ sh:select """
+ PREFIX rml:
+ SELECT ?this
+ WHERE {
+ ?this a rml:LogicalView .
+ ?this ((rml:leftJoin|rml:innerJoin)/rml:parentLogicalView)+ ?this .
+ }
+ """ ;
+ ] .
diff --git a/shapes/tests.py b/shapes/tests.py
index 8fe1fdd..295eca0 100755
--- a/shapes/tests.py
+++ b/shapes/tests.py
@@ -53,7 +53,12 @@ def test_validation_rules(self, path: str) -> None:
rules test cases.
"""
print(f'Testing validation with: {path}')
- self._validate_rules(path)
+ if 'RMLLVTC0008a' in path or 'RMLLVTC0008b' in path or \
+ 'RMLLVTC0008c' in path or 'RMLLVTC0008d' in path:
+ with self.assertRaises(Exception):
+ self._validate_rules(path)
+ else:
+ self._validate_rules(path)
if __name__ == '__main__':
diff --git a/spec/config.js b/spec/config.js
index c582e09..a95a859 100644
--- a/spec/config.js
+++ b/spec/config.js
@@ -33,7 +33,7 @@ var respecConfig = {
// formal title, define it here
// subtitle : "White Paper",
// if you wish the publication date to be other than the last modification, set this
- publishDate: "2025-10-23",
+ publishDate: "2025-11-20",
// if the specification's copyright date is a range of years, specify
// the start date here:
copyrightStart: "2024",
diff --git a/spec/docs/20251120/index.html b/spec/docs/20251120/index.html
new file mode 100644
index 0000000..822710b
--- /dev/null
+++ b/spec/docs/20251120/index.html
@@ -0,0 +1,2849 @@
+
+
+
+
+
+
+
+
+RML Logical Views
+
+
+
+
+
+
+
+
+
+
+
+
+ <img src="https://rml-fields.goatcounter.com/count?p=/test-noscript">
+
+
+
+
+
+
+
+
+
+
+
+Abstract RML logical views is an extension of the RDF Mapping Language (RML) that increases the language's capability to
+construct RDF datasets from nested input data, to join data sources (also across data hierarchies),
+and to handle data sources that mix source formats,
+by allowing to specify a logical view: a flattened, source format-agnostic view
+over one or more existing data sources.
+Additionally, it provides a mechanism to express relationships between data sources,
+as well as additional information about their fields, through structural annotations.
+This document describes RML logical views through definitions and examples.
+The version of this document is DRAFT .
+
+
+Table of Contents Abstract Status of This Document 1. Overview1.1 Document conventions1.2 Conformance2. Problem2.1 Nested data structures2.2 Mixed data formats2.3 Joining of data sources3. Logical views3.1 Logical view iterator3.2 Logical view expressions4. Fields4.1 Field parents4.2 Field names4.3 Field records4.4 Field reference formulations5. Logical view joins5.1 Join types5.2 Logical view join examples5.2.1 Left join5.2.2 Inner join5.2.3 Two left joins6. Structural Annotations6.1 Invariance Principle6.2 IriSafe6.3 PrimaryKey6.4 Unique6.5 NotNull6.6 ForeignKey6.7 InclusionA. ReferencesA.1 Normative references
+
+This section is non-normative.
+We assume readers have basic familiarity with RDF and RML concepts.
+In this document, examples assume
+the following namespace prefix bindings unless otherwise stated:
+
+The examples are contained in color-coded boxes. We use the Turtle syntax [turtle ] to write RDF.
+
+
+
+# This box contains an example mapping
+
+
+
+
+
+# This box contains the example output
+
+
+
+
+This section is non-normative.
+RML Logical Views aims to resolve challenges such as handling hierarchy of nested data, more flexible joining (also across data hierarchies), and handling data sources that mix source formats.
+
+References to nested data structures, like JSON or XML, may return multiple values. These values can be composite: they may again contain multiple values.
+[RML-Core ] defines mapping constructs that produce results by combining the results of other mapping constructs in a specific order.
+For example, a triples map combines the results of a subject map and a predicate-object map in that order.
+Another example is a template expression ,
+which combines character strings and zero or more reference expressions in declared order.
+When mapping constructs produce multiple results, the combining mapping constructs will apply an n-ary Cartesian product over the sets of results, maintaining the order of the mapping constructs. In the case of nested data structures, this may cause the generation of results that do not match the source hierarchy, i.e. do not follow the root-to-leaf paths in the source data, since values are combined irrespective of it.
+Furthermore, there is varying expressiveness in data source expression and query languages, and many languages have limited support for hierarchy traversal. For example, JSONPath has no operator to refer to an ancestor in the document hierarchy [RFC9535 ].
+This limits the ability of RML-Core to map nested data.
+
+It is not possible to declare the construction of below output triples from below data source with RML-Core.
+
+
+
+
+:person/alice/item/sword :hasName "sword" ;
+ :hasWeight 1500 .
+:person/alice/item/shield :hasName "shield" ;
+ :hasWeight 2500 .
+:person/bob/item/flower :hasName "flower" ;
+ :hasWeight 15 .
+
+
+
+
+
+
+RML-Core restricts join operations to referencing object maps . Since a referencing object map can only generate an object that is an IRI or blank node subject as specified by a parent triples map, it is not possible to combine data from two sources in one term, use data from a join on another position than the object, or generate a literal using data from a join.
+Moreover, RML-Core cannot declare join operations correctly across hierarchies.
+
+
+A logical view is a type of abstract logical source that is derived from another abstract logical source by defining fields with data from said abstract logical source .
+A logical view (rml:LogicalView) is represented by a resource that MUST contain:
+
+exactly one view on property (rml:viewOn), whose value is a abstract logical source (rml:AbstractLogicalSource),
+at least one field property (rml:field), whose value is a field (rml:Field).
+zero or more join properties (rml:leftJoin, rml:innerJoin), whose value is a logical view join (rml:LogicalViewJoin).
+
+A logical view (rml:LogicalView) has an implicit default reference formulation (rml:referenceFormulation) and logical iterator (rml:iterator), which MUST not be overwritten.
+
+
+
+Property
+Domain
+Range
+
+
+
+rml:viewOn
+rml:LogicalView
+rml:AbstractLogicalSource
+
+
+rml:field
+rml:LogicalView or rml:Field
+rml:Field
+
+
+rml:leftJoin
+rml:LogicalView
+rml:LogicalViewJoin
+
+
+rml:innerJoin
+rml:LogicalView
+rml:LogicalViewJoin
+
+
+The logical iterator of a logical view produces a logical view iteration sequence , i.e. an ordered sequence of sets of key-value pairs.
+Each set of key-value pairs represents a logical iteration of the logical view , called a logical view iteration .
+Each key in a logical view iteration sequence is a string and each value is a record or a non-negative integer.
+A record is either an iterable record or an expression record .
+An iterable record is a logical iteration , i.e. an item on which expressions can be evaluated.
+An expression record is one element of an expression evaluation result .
+A record key has a record as value.
+Each record key is accompanied with an index key .
+An index key has a non-negative integer as value, indicating the zero-based position of the corresponding record.
+
+Note
+The order of logical view iterations produced, may differ between RML processors.
+Implementations are not required to guarantee a specific or stable iteration order.
+This may result in differences in the index values of fields across different mapping executions.
+Furthermore, other reference formulations , e.g., rml:SQLQuery, may not have a deterministic logical iteration order, potentially leading to differences in index values across mapping executions.
+
+
+A logical view iteration sequence MUST have a finite set of keys that appear in each logical view iteration .
+In any particular logical view iteration , the value of a key MAY be a null value.
+Each logical view iteration has at least the following keys:
+
+Additional keys-value pairs with custom record keys can be defined by the fields of the logical view ,
+which is further detailed in 4. Fields .
+A logical view reference is a reference expression that references a defined referenceable key in a logical view iteration .
+A referenceable key is either
+
+A record key of an iterable record (including the record key <it>) cannot be referenced.
+The expression evaluation result of a logical view reference is the value corresponding to the referenced key.
+The natural RDF datatype of an index key 's values is xsd:integer .
+The natural RDF datatype of an expression record is obtained by applying the natural mapping of the reference formulation used to retrieve the record .
+A logical view reference can be used in expression maps just as any other reference expression .
+When a non-existing or a non-referenceable key is referenced, RML processors should report an error.
+
+
+
+
+:jsonView a rml:LogicalView ;
+ rml:viewOn :jsonSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "$.name" ;
+ ] ;
+ rml:field [
+ a rml:IterableField ;
+ rml:fieldName "item" ;
+ rml:iterator "$.items[*]" ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "type" ;
+ rml:reference "$.type" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "weight" ;
+ rml:reference "$.weight" ;
+ ] ;
+ ] .
+
+
+
+Note some columns in the table below have been shortened for brevity.
+
+
+
+
+
+
+:triplesMapPerson a rml:TriplesMap ;
+ rml:logicalSource :jsonView ;
+ rml:subjectMap [
+ rml:template "http://example.org/person/{name}" ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasName ;
+ rml:objectMap [
+ rml:reference "name" ;
+ ] ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasItem ;
+ rml:objectMap [
+ rml:parentTriplesMap :triplesMapItem ;
+ ] ;
+ ] .
+
+:triplesMapItem a rml:TriplesMap ;
+ rml:logicalSource :jsonView ;
+ rml:subjectMap [
+ rml:template "http://example.org/person/{name}/item/{item.#}" ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasName ;
+ rml:objectMap [
+ rml:reference "item.type" ;
+ ] ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasWeight ;
+ rml:objectMap [
+ rml:reference "item.weight" ;
+ ] ;
+ ] .
+
+
+
+
+
+<http://example.org/person/alice> :hasName "alice" ;
+ :hasItem <http://example.org/person/alice/item/0> ,
+ <http://example.org/person/alice/item/1> .
+
+<http://example.org/person/bob> :hasName "bob" ;
+ :hasItem <http://example.org/person/bob/item/0> .
+
+<http://example.org/person/alice/item/0> :hasName "sword" ;
+ :hasWeight 1500 .
+
+<http://example.org/person/alice/item/1> :hasName "shield" ;
+ :hasWeight 2500 .
+
+<http://example.org/person/bob/item/0> :hasName "flower" ;
+ :hasWeight 15 .
+
+
+
+
+
+A field gives a name to data derived from the abstract logical source on which the logical view is defined.
+A field (rml:Field) is represented by a resource that MUST contain:
+
+exactly one field name property (rml:fieldName), that specifies the declared name of the field
+zero or more field properties (rml:field), to describe nested field , also of the type rml:Field
+
+
+
+
+Property
+Domain
+Range
+
+
+
+rml:fieldName
+rml:Field
+xsd:string
+
+
+rml:field
+rml:LogicalView or rml:Field
+rml:Field
+
+
+There are two types of fields: an expression field and an iterable field .
+An expression field (rml:ExpressionField) is a type of expression map .
+Consequently, an expression field MUST have an expression .
+An iterable field (rml:IterableField) is a type of iterable .
+Consequently, an iterable field MUST have a reference formulation and a logical iterator .
+If no reference formulation is declared for an iterable field , the reference formulation of the field's parent is implied.
+A field MUST have a declared name that is an alphanumerical string. Fields with the same parent MUST have different declared names.
+We distinguish between the field 's declared name and the field 's absolute name .
+If a field 's parent is another field , the field 's absolute name is the concatenation of the name of the parent field , a dot ., and the field 's declared name.
+Otherwise, the field 's absolute name equals its declared name .
+
+
+In this example a field with declared name "name" is declared and added to the logical view . The parent of the field with declared name "name" is the logical source :jsonSource.
+
+
+
+:jsonSource a rml:LogicalSource ;
+ rml:source :jsonFile ;
+ rml:referenceFormulation rml:JSONPath ;
+ rml:iterator "$.people[*]" .
+
+:jsonView a rml:LogicalView ;
+ rml:viewOn :jsonSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "$.name" ;
+ ] .
+
+
+
+
+
+
+A field defines records :
+
+A field adds following keys and corresponding values to the logical view iteration sequence :
+
+
+
+In this example a field with declared name "item" is added to the logical view from Example 5 . Additionally a nested field "type" and a nested field "weight" are added to the "item" field .
+
+
+:jsonView a rml:LogicalView ;
+ rml:viewOn :jsonSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "$.name" ;
+ ] ;
+ rml:field [
+ a rml:IterableField ;
+ rml:fieldName "item" ;
+ rml:iterator "$.items[*]" ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "type" ;
+ rml:reference "$.type" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "weight" ;
+ rml:reference "$.weight" ;
+ ] ;
+ ] .
+
+
+
+Note some columns in the table below have been shortened for brevity.
+
+
+
+
+
+
+A logical view join (rml:LogicalViewJoin) is an operation that extends the logical iteration of one logical view (the child logical view ) with fields derived from another logical view (the parent logical view ),
+using a join condition .
+A logical view join MUST contain:
+
+exactly one parent logical view property (rml:parentLogicalView), whose value is a logical view (rml:LogicalView) that supplies the additional fields. This is referred to as the parent logical view .
+at least one join condition property (rml:joinCondition), whose value is a join condition .
+at least one field property (rml:field), whose value is a leaf expression field , i.e., an expression field (rml:ExpressionField) without nested fields.
+This field MUST contain only logical view references that can be evaluated on the parent logical view.
+The declared name of this field MUST be different from the absolute name of every other field in the child logical view .
+
+Similar to how joins are defined in RML-Core ,
+the logical view in the subject position of the join property fulfills the role of child logical source in the join condition(s) , but of the logical view join , and is referred to as child logical view .
+The parent logical view fulfills the role of the parent logical source in the join condition(s) , but of the logical view join .
+
+
+
+Property
+Domain
+Range
+
+
+
+rml:parentLogicalView
+rml:LogicalViewJoin
+rml:LogicalView
+
+
+rml:joinCondition
+rml:LogicalViewJoin
+rml:Join
+
+
+rml:field
+rml:LogicalViewJoin
+rml:ExpressionField
+
+
+
+
+
+
+In this example a logical view with fields built with data from the logical source :csvSource is joined with the logical view from Example 6 .
+In case of a left join (as in the example), this results in 4 logical iterations in the logical view.
+If an inner joins would have been used, the logical view would have only 3 logical iterations.
+
+
+
+
+:csvSource a rml:LogicalSource ;
+ rml:source :csvFile ;
+ rml:referenceFormulation rml:CSV .
+
+:csvView a rml:LogicalView ;
+ rml:viewOn :csvSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "birthyear" ;
+ rml:reference "birthyear" ;
+ ] ;
+ rml:leftJoin [
+ rml:parentLogicalView :jsonView ;
+ rml:joinCondition [
+ rml:parent "name" ;
+ rml:child "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "item_type" ;
+ rml:reference "item.type" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "item_weight" ;
+ rml:reference "item.weight" ;
+ ] ;
+ ] .
+
+
+
+
+
+
+
+
+
+When an inner join is used, the resulting logical view has only 3 logical iterations.
+
+
+:csvView a rml:LogicalView ;
+ rml:viewOn :csvSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "birthyear" ;
+ rml:reference "birthyear" ;
+ ] ;
+ rml:leftJoin [
+ rml:parentLogicalView :jsonView
+ rml:joinCondition [
+ rml:parent "name" ;
+ rml:child "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "item_type" ;
+ rml:reference "item.type" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "item_weight" ;
+ rml:reference "item.weight" ;
+ ] ;
+ ] .
+
+
+
+
+
+
+
+
+
+
+In this example a second logical view join is added to the logical view from Example 8 . The parent logical view of this second join is derived from logical source :additionalCsvSource with below input data.
+
+
+
+
+:additionalCsvView a rml:LogicalView ;
+ rml:viewOn :additioncalCsvSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "id" ;
+ rml:reference "id" ;
+ ] .
+
+:csvView a rml:LogicalView ;
+ rml:viewOn :csvSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "birthyear" ;
+ rml:reference "birthyear" ;
+ ] ;
+ rml:leftJoin [
+ rml:parentLogicalView :jsonView ;
+ rml:joinCondition [
+ rml:parent "name" ;
+ rml:child "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "item_type" ;
+ rml:reference "item.type" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "item_weight" ;
+ rml:reference "item.weight" ;
+ ] ;
+ ] ;
+ rml:leftJoin [
+ rml:parentLogicalView :additionalCsvView ;
+ rml:joinCondition [
+ rml:parent "name" ;
+ rml:child "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "id" ;
+ rml:reference "id" ;
+ ] ;
+ ] .
+
+
+
+
+
+
+Structural annotations provide a mechanism to express relationships between logical views, as well as additional information about fields.
+Each logical view MAY have zero or more structural annotation properties (rml:structuralAnnotation), connecting the logical view to a structural annotation object (i.e., of type rml:StructuralAnnotation).
+
+
+
+Property
+Domain
+Range
+
+
+
+rml:structuralAnnotation
+rml:LogicalView
+rml:StructuralAnnotation
+
+
+Following structural annotations MAY be defined:
+
+All structural annotations of a logical view lv MUST have an on fields property (rml:onFields), linking the structural annotation to a list of field names occurring in lv . Intuitively, property on fields specifies the fields in lv that are involved by the structural annotation. The semantics of this involvement depends on the specific annotation.
+
+
+
+Property
+Domain
+Range
+
+
+
+rml:onFields
+rml:StructuralAnnotation
+rdf:List
+
+
+
+Structural annotations provide additional information about the data that might be used by the RML processor to optimize the KG construction process. If this additional information is incorrect, then the RML processor might either fail or produce wrong results. When using structural annotations, users should make sure that the following invariance principle is satisfied:
+For any source instances, the RDF graph produced by the RML engine using an RML mapping with annotations, and the same RML mapping where annotations have been removed, MUST be the same.
+We emphasize that RML engines might exploit structural annotations, as they could totally ignore them. It is responsibility of the user to make sure that the annotations provided are indeed correct (that is, the data complies with the annotations). Sanity checks MAY be provided by the RML engines themselves, but this is not mandatory. Note that providing wrong annotations to an engine that takes annotations into account, for instance for applying optimizations, could result in a violation of the invariance principle, with unpredictable results.
+
+An IriSafe structural annotation (rml:IriSafeAnnotation) on fields F indicates that the content of each field in F is IRI safe , that is, each field in F does not contain any character that is not in the iunreserved production in RFC3987 .
+
+A PrimaryKey structural annotation (rml:PrimaryKeyAnnotation) on fields (f1, ..., fn) imposes two conditions:
+
+no duplicate record sequences are present over the list of fields (f1, ..., fn) ;
+No NULL value is admitted in any of the field f1, ..., fn .
+
+Each logical view MAY specify AT MOST ONE PrimaryKey annotation .
+
+
+ Consider the following CSV file containing birthdays of people:
+
+
+Now, assume that we know:
+
+Attribute name in the CSV is "UNIQUE" and "NOT NULL";
+
+Such a constraint naturally corresponds to the notion of PRIMARY KEY from the world of relational databases. This fact could be valuable information for the RML engine, especially in the virtual setting. However, CSV files do not support the definition of constraints. This limitation can be addressed by using structural annotations to inform the RML engine about the presence of such constraints. We illustrate this approach with a concrete example below.
+First, we specify the logical source corresponding to the CSV file:
+
+
+We are now ready to specify our logical view and associated rml:primaryKeyAnnotation.
+
+
+:csvSource a rml:LogicalView ;
+ rml:viewOn :csvSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "name"
+ ];
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "birthday" ;
+ rml:reference "birthday"
+ ];
+ rml:structuralAnnotation [
+ a rml:primaryKeyAnnotation;
+ rml:onFields ("name" )
+ ].
+
+
+
+
+
+The Unique structural annotation (rml:UniqueAnnotation) is analogous to the notion of UNIQUE constraints in databases. Specifically, a Unique annotation on fields (f1, ..., fn) imposes the following condition:
+
+no duplicate record sequences are present over the list of fields (f1, ..., fn) .
+
+Note that every PrimaryKey annotation is, as a matter of fact, also a Unique annotation .
+
+The NotNull structural annotation (rml:NotNullAnnotation) is analogous to the notion of NOT NULL constraints in databases. Specifically, a NotNull annotation on fields F imposes that each field in F does not contain NULL values.
+
+
+
+The ForeignKey structural annotation (rml:ForeignKeyAnnotation) is analogous to the notion of foreign key constraint in databases. Specifically, a ForeignKey annotation on fields (f1, ..., fn) , target view lv , and target fields (tf1,...,tfn) imposes the following conditions:
+
+each NULL-free record sequence over the list of fields (f1, ..., fn) occurs also as a record sequence in (tf1,...,tfn) ;
+Target view lv defines a Unique annotation on fields (tf1,...,tfn) .
+
+The target view is a logical view specified through the property rml:targetView, whereas the target fields are an RDF list of field names specified through the property rml:targetFields. These two properties are specified as follows:
+
+
+
+Property
+Domain
+Range
+
+
+
+rml:targetView
+rml:InclusionAnnotation
+rml:LogicalView
+
+
+rml:targetFields
+rml:InclusionAnnotation
+rdf:List
+
+
+Therefore, each ForeignKey annotation MUST specify (additionally to the inherited rml:onFields property):
+
+Exactly one rml:targetView property
+Exactly one rml:targetFields property.
+
+
+
+Consider the following JSON file containing information about warriors.
+
+
+Now, assume that we know:
+
+Attribute name in the CSV of Example 11 is "UNIQUE" and "NOT NULL";
+All warriors in our domain are contained in the JSON of Example 12 .
+
+The first constraint naturally corresponds to the notion of PRIMARY KEY from the world of relational databases. This fact could be valuable information for the RML engine, especially in the virtual setting. However, note that constraints cannot be expressed on CSV files.
+The second constraint naturally corresponds to a FOREIGN KEY constraint from the world of relational databases. However, as the involved values spread across different (and diverse) sources, it cannot be expressed as such. Also this one could provide valuable information for the RML engine.
+We can exploit the mechanism of structural annotations to inform the RML engine about the existence of such "relational-like" constraint. We here work out an example.
+First, we need to specify the logical sources. The logical source corresponding to the CSV of Example 11 :
+
+
+The logical source corresponding to the JSON of Example 12 :
+
+
+:jsonSource a rml:LogicalSource ;
+ rml:source :jsonFile ;
+ rml:referenceFormulation rml:JSONPath ;
+ rml:iterator "$.people[*]" .
+
+
+
+We are now ready to specify our logical views, and associated structural annotations. The first logical view is the one corresponding to :csvSource.
+
+
+:csvSource a rml:LogicalView ;
+ rml:viewOn :csvSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "name"
+ ];
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "birthday" ;
+ rml:reference "birthday"
+ ];
+ rml:structuralAnnotation [
+ a rml:PrimaryKeyAnnotation;
+ rml:onFields ("name" );
+ ].
+
+
+
+Now, we declare the logical view corresponding to :jsonSource. Note that this view contains a rml:ForeignKeyAnnotation:
+
+
+:jsonView a rml:LogicalView ;
+ rml:viewOn :jsonSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "$.name" ;
+ ] ;
+ rml:field [
+ a rml:IterableField ;
+ rml:fieldName "item" ;
+ rml:iterator "$.items[*]" ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "type" ;
+ rml:reference "$.type" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "weight" ;
+ rml:reference "$.weight" ;
+ ]
+ ] ;
+ rml:structuralAnnotation [
+ a rml:ForeignKeyAnnotation;
+ rml:onFields ("name" );
+ rml:targetView :csvView;
+ rml:targetFields ("name" )
+ ].
+
+
+
+
+
+The Inclusion structural annotation (rml:InclusionAnnotation) is analogous to the notion of inclusion dependency in databases. Specifically, an Inclusion annotation on fields (f1, ..., fn) , target view lv , and target fields (tf1,...,tfn) imposes the following condition:
+
+each NULL-free record sequence over the list of fields (f1, ..., fn) occurs also as a record sequence in (tf1,...,tfn) ;
+
+As for ForeignKey annotation , the target view MUST be a logical view specified through the property rml:targetView, whereas the target fields MUST be an RDF list of field names specified through the property rml:targetFields.
+Therefore, each inclusion annotation MUST specify (additionally to the inherited rml:onFields property):
+
+Exactly one rml:targetView property
+Exactly one rml:targetFields property.
+
+
+
+
+
+
+ ↑
+
+
+
+
Referenced in:
+
+ Not referenced in this document.
+
+
+
+
+
Referenced in:
+
+ Not referenced in this document.
+
+
\ No newline at end of file
diff --git a/spec/docs/20251120/resources/css/extras.css b/spec/docs/20251120/resources/css/extras.css
new file mode 100644
index 0000000..3d7ce4e
--- /dev/null
+++ b/spec/docs/20251120/resources/css/extras.css
@@ -0,0 +1,21 @@
+
+a.sec-ref:before {
+ content: "“";
+}
+
+a.sec-ref:after {
+ content: "”";
+}
+
+span.orcid a {
+ text-decoration: none !important;
+ border: none !important;
+}
+
+span.orcid a img {
+ transform: translateY(3px);
+}
+
+html {
+ background: white !important;
+}
\ No newline at end of file
diff --git a/spec/docs/20251120/resources/images/orcid_logo.png b/spec/docs/20251120/resources/images/orcid_logo.png
new file mode 100644
index 0000000..e743726
Binary files /dev/null and b/spec/docs/20251120/resources/images/orcid_logo.png differ
diff --git a/spec/docs/index.html b/spec/docs/index.html
index 2765d22..50889e7 100644
--- a/spec/docs/index.html
+++ b/spec/docs/index.html
@@ -46,7 +46,7 @@
RML Logical Views
-
+
+
+RML-LV: Test Cases
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Abstract This document defines the RML-LV test cases to the determine the RML-LV specification conformance of tools.
+
+
+Table of Contents Abstract Status of This Document 1. Introduction2. Data model3. Test cases4. RMLLVTC0000a5. RMLLVTC0000b6. RMLLVTC0000c7. RMLLVTC0001a8. RMLLVTC0001b9. RMLLVTC0001c10. RMLLVTC0001d11. RMLLVTC0002a12. RMLLVTC0002b13. RMLLVTC0002c14. RMLLVTC0003a15. RMLLVTC0003b16. RMLLVTC0003c17. RMLLVTC0004a18. RMLLVTC0004b19. RMLLVTC0004c20. RMLLVTC0004d21. RMLLVTC0005a22. RMLLVTC0005b23. RMLLVTC0005c24. RMLLVTC0006a25. RMLLVTC0006b26. RMLLVTC0006c27. RMLLVTC0006d28. RMLLVTC0006e29. RMLLVTC0006f30. RMLLVTC0007a31. RMLLVTC0007b32. RMLLVTC0007c33. RMLLVTC0008a34. RMLLVTC0008b35. RMLLVTC0008c36. RMLLVTC0008d37. RMLLVTC0009a38. RMLLVTC0009b39. RMLLVTC0009c
+
+
+This document defines the RML-LV test cases, consisting of a collection of test case documents (input and expected output).
+The purpose of the test cases is to determine the conformance of tools that execute RML rules to the RML-LV specification.
+
+
+
+The test cases are semantically described for re-usability and shareability following the W3C Test case description .
+Each test:Testcase as the following properties:
+
+dcterms:identifier: unique ID of the test case.
+rmltest:hasError: if an error of the RML Processor is expected or not.
+rmltest:input: One or more input data of the test case.
+rmltest:output: One or more output data of the test case.
+rmltest:inputFormat: the input data format.
+rmltest:outputFormat: the output data format.
+rmltest:mappingDocument: the RML mapping rules in Turtle.
+
+
+
+
+This section describes the RML-LV test cases. These descriptions are also available as RDF.
+The files are available on GitHub in the folder test-cases.
+Each test case is contained in a single folder, containing three types of files:
+
+Zero or more files containing the data sources, in the case of JSON, XML, CSV, or containing the SQL statements to create the necessary tables, in the case of MySQL, PostgreSQL, and SQL Server.
+One file with the RML rules, called mapping.ttl, in the Turtle format.
+Zero or more files with the expected RDF. No file is provided if an error is expected that must halt the generation of the RDF because of an error.
+
+
+
+
+
+Title : Logical view on JSON source
+Description : Test a view on a hierarchical source
+Error expected? No
+Input
+{
+ "people" : [
+ {
+ "name" : "alice" ,
+ "items" : [
+ {
+ "type" : "sword" ,
+ "weight" : 1500
+ } ,
+ {
+ "type" : "shield" ,
+ "weight" : 2500
+ }
+ ]
+ } ,
+ {
+ "name" : "bob" ,
+ "items" : [
+ {
+ "type" : "flower" ,
+ "weight" : 15
+ }
+ ]
+ }
+ ]
+}
+
+Mapping
+@prefix rml : <http ://w3id.org/rml/> .
+@prefix : <http ://example.org/> .
+
+:jsonSource a rml :LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.json" ;
+ ] ;
+ rml:referenceFormulation rml:JSONPath ;
+ rml:iterator "$.people[*]" .
+
+:jsonView a rml:LogicalView ;
+ rml:viewOn :jsonSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "$.name" ;
+ ] .
+
+:triplesMapPerson a rml:TriplesMap ;
+ rml:logicalSource :jsonView ;
+ rml:subjectMap [
+ rml:template "http://example.org/person/{name}" ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasName ;
+ rml:objectMap [
+ rml:reference "name" ;
+ ] ;
+ ] .
+
+Output
+<http://example.org/person/alice> <http://example.org/hasName> "alice" .
+<http://example.org/person/bob> <http://example.org/hasName> "bob" .
+
+
+
+Title : Logical view on CSV source
+Description : Test a view on a tabular source
+Error expected? No
+Input
+name,birthyear
+alice,1995
+bob,1999
+tobias,2005
+
+Mapping
+@prefix rml : <http ://w3id.org/rml/> .
+@prefix : <http ://example.org/> .
+
+:csvSource a rml :LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.csv" ;
+ ] ;
+ rml:referenceFormulation rml:CSV .
+
+:csvView a rml:LogicalView ;
+ rml:viewOn :csvSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "name" ;
+ ] .
+
+:triplesMapPerson a rml:TriplesMap ;
+ rml:logicalSource :csvView ;
+ rml:subjectMap [
+ rml:template "http://example.org/person/{name}" ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasName ;
+ rml:objectMap [
+ rml:reference "name" ;
+ ] ;
+ ] .
+
+Output
+<http://example.org/person/alice> <http://example.org/hasName> "alice" .
+<http://example.org/person/bob> <http://example.org/hasName> "bob" .
+<http://example.org/person/tobias> <http://example.org/hasName> "tobias" .
+
+
+
+Title : Logical View on Logical View
+Description : Test a view on a logical view
+Error expected? No
+Input
+{
+ "people" : [
+ {
+ "name" : "alice" ,
+ "items" : [
+ {
+ "type" : "sword" ,
+ "weight" : 1500
+ } ,
+ {
+ "type" : "shield" ,
+ "weight" : 2500
+ }
+ ]
+ } ,
+ {
+ "name" : "bob" ,
+ "items" : [
+ {
+ "type" : "flower" ,
+ "weight" : 15
+ }
+ ]
+ }
+ ]
+}
+
+Mapping
+@prefix rml : <http ://w3id.org/rml/> .
+@prefix : <http ://example.org/> .
+
+:jsonSource a rml :LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.json" ;
+ ] ;
+ rml:referenceFormulation rml:JSONPath ;
+ rml:iterator "$.people[*]" .
+
+:jsonView a rml:LogicalView ;
+ rml:viewOn :jsonSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "$.name" ;
+ ] .
+
+:jsonViewOnJsonView a rml:LogicalView ;
+ rml:viewOn :jsonView ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "newName" ;
+ rml:reference "name" ;
+ ] .
+
+:triplesMapPerson a rml:TriplesMap ;
+ rml:logicalSource :jsonViewOnJsonView ;
+ rml:subjectMap [
+ rml:template "http://example.org/person/{newName}" ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasName ;
+ rml:objectMap [
+ rml:reference "newName" ;
+ ] ;
+ ] .
+
+Output
+<http://example.org/person/alice> <http://example.org/hasName> "alice" .
+<http://example.org/person/bob> <http://example.org/hasName> "bob" .
+
+
+
+Title : Expression Field: Reference
+Description : Test a reference in an expression field
+Error expected? No
+Input
+{
+ "people" : [
+ {
+ "name" : "alice" ,
+ "items" : [
+ {
+ "type" : "sword" ,
+ "weight" : 1500
+ } ,
+ {
+ "type" : "shield" ,
+ "weight" : 2500
+ }
+ ]
+ } ,
+ {
+ "name" : "bob" ,
+ "items" : [
+ {
+ "type" : "flower" ,
+ "weight" : 15
+ }
+ ]
+ }
+ ]
+}
+
+Mapping
+@prefix rml : <http ://w3id.org/rml/> .
+@prefix : <http ://example.org/> .
+
+:jsonSource a rml :LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.json" ;
+ ] ;
+ rml:referenceFormulation rml:JSONPath ;
+ rml:iterator "$.people[*]" .
+
+:jsonView a rml:LogicalView ;
+ rml:viewOn :jsonSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "$.name" ;
+ ] .
+
+:triplesMapPerson a rml:TriplesMap ;
+ rml:logicalSource :jsonView ;
+ rml:subjectMap [
+ rml:template "http://example.org/person/{name}" ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasName ;
+ rml:objectMap [
+ rml:reference "name" ;
+ ] ;
+ ] .
+
+Output
+<http://example.org/person/alice> <http://example.org/hasName> "alice" .
+<http://example.org/person/bob> <http://example.org/hasName> "bob" .
+
+
+
+Title : Expression Field: Template
+Description : Test a template in an expression field
+Error expected? No
+Input
+{
+ "people" : [
+ {
+ "name" : "alice" ,
+ "items" : [
+ {
+ "type" : "sword" ,
+ "weight" : 1500
+ } ,
+ {
+ "type" : "shield" ,
+ "weight" : 2500
+ }
+ ]
+ } ,
+ {
+ "name" : "bob" ,
+ "items" : [
+ {
+ "type" : "flower" ,
+ "weight" : 15
+ }
+ ]
+ }
+ ]
+}
+
+Mapping
+@prefix rml : <http ://w3id.org/rml/> .
+@prefix : <http ://example.org/> .
+
+:jsonSource a rml :LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.json" ;
+ ] ;
+ rml:referenceFormulation rml:JSONPath ;
+ rml:iterator "$.people[*]" .
+
+:jsonView a rml:LogicalView ;
+ rml:viewOn :jsonSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "$.name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "race" ;
+ rml:constant "human" ;
+ ] .
+
+:triplesMapPerson a rml:TriplesMap ;
+ rml:logicalSource :jsonView ;
+ rml:subjectMap [
+ rml:template "http://example.org/person/{name}" ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasRace ;
+ rml:objectMap [
+ rml:reference "race" ;
+ ] ;
+ ] .
+
+Output
+<http://example.org/person/alice> <http://example.org/hasRace> "human" .
+<http://example.org/person/bob> <http://example.org/hasRace> "human" .
+
+
+
+Title : Expression Field: Constant
+Description : Test a constant expression in an expression field
+Error expected? No
+Input
+{
+ "people" : [
+ {
+ "name" : "alice" ,
+ "lastName" : "smith" ,
+ "items" : [
+ {
+ "type" : "sword" ,
+ "weight" : 1500
+ } ,
+ {
+ "type" : "shield" ,
+ "weight" : 2500
+ }
+ ]
+ } ,
+ {
+ "name" : "bob" ,
+ "lastName" : "jones" ,
+ "items" : [
+ {
+ "type" : "flower" ,
+ "weight" : 15
+ }
+ ]
+ }
+ ]
+}
+
+Mapping
+@prefix rml : <http ://w3id.org/rml/> .
+@prefix : <http ://example.org/> .
+
+:jsonSource a rml :LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.json" ;
+ ] ;
+ rml:referenceFormulation rml:JSONPath ;
+ rml:iterator "$.people[*]" .
+
+:jsonView a rml:LogicalView ;
+ rml:viewOn :jsonSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "$.name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "fullName" ;
+ rml:template "{name} {lastName}" ;
+ ] .
+
+:triplesMapPerson a rml:TriplesMap ;
+ rml:logicalSource :jsonView ;
+ rml:subjectMap [
+ rml:template "http://example.org/person/{name}" ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasFullName ;
+ rml:objectMap [
+ rml:reference "fullName" ;
+ ] ;
+ ] .
+
+Output
+<http://example.org/person/alice> <http://example.org/hasFullName> "alice smith" .
+<http://example.org/person/bob> <http://example.org/hasFullName> "bob jones" .
+
+
+
+Title : Expression Field Siblings
+Description : Test multiple expression fields with the same parent
+Error expected? No
+Input
+{
+ "people" : [
+ {
+ "name" : "alice" ,
+ "lastName" : "smith" ,
+ "items" : [
+ {
+ "type" : "sword" ,
+ "weight" : 1500
+ } ,
+ {
+ "type" : "shield" ,
+ "weight" : 2500
+ }
+ ]
+ } ,
+ {
+ "name" : "bob" ,
+ "lastName" : "jones" ,
+ "items" : [
+ {
+ "type" : "flower" ,
+ "weight" : 15
+ }
+ ]
+ }
+ ]
+}
+
+Mapping
+@prefix rml : <http ://w3id.org/rml/> .
+@prefix : <http ://example.org/> .
+
+:jsonSource a rml :LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.json" ;
+ ] ;
+ rml:referenceFormulation rml:JSONPath ;
+ rml:iterator "$.people[*]" .
+
+:jsonView a rml:LogicalView ;
+ rml:viewOn :jsonSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "$.name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "lastName" ;
+ rml:reference "$.lastName" ;
+ ] .
+
+:triplesMapPerson a rml:TriplesMap ;
+ rml:logicalSource :jsonView ;
+ rml:subjectMap [
+ rml:template "http://example.org/person/{name}" ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasFullName ;
+ rml:objectMap [
+ rml:template "{name} {lastName}" ;
+ rml:termType rml:Literal ;
+ ] ;
+ ] .
+
+Output
+<http://example.org/person/alice> <http://example.org/hasFullName> "alice smith" .
+<http://example.org/person/bob> <http://example.org/hasFullName> "bob jones" .
+
+
+
+Title : Iterable Field
+Description : Test a nested field construction: iterable field with expression field as child
+Error expected? No
+Input
+{
+ "people" : [
+ {
+ "name" : "alice" ,
+ "items" : [
+ {
+ "type" : "sword" ,
+ "weight" : 1500
+ } ,
+ {
+ "type" : "shield" ,
+ "weight" : 2500
+ }
+ ]
+ } ,
+ {
+ "name" : "bob" ,
+ "items" : [
+ {
+ "type" : "flower" ,
+ "weight" : 15
+ }
+ ]
+ }
+ ]
+}
+
+Mapping
+@prefix rml : <http ://w3id.org/rml/> .
+@prefix xsd : <http ://www.w3.org/2001 /XMLSchema#> .
+@prefix : <http ://example.org/> .
+
+:jsonSource a rml :LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.json" ;
+ ] ;
+ rml:referenceFormulation rml:JSONPath ;
+ rml:iterator "$.people[*]" .
+
+:jsonView a rml:LogicalView ;
+ rml:viewOn :jsonSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "$.name" ;
+ ] ;
+ rml:field [
+ a rml:IterableField ;
+ rml:fieldName "item" ;
+ rml:iterator "$.items[*]" ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "type" ;
+ rml:reference "$.type" ;
+ ] ;
+ ] .
+
+:triplesMapPerson a rml:TriplesMap ;
+ rml:logicalSource :jsonView ;
+ rml:subjectMap [
+ rml:template "http://example.org/person/{name}" ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasItem ;
+ rml:objectMap [
+ rml:template "http://example.org/person/{name}/item/{item.type}" ;
+ ] ;
+ ] .
+
+Output
+<http :
+<http://example.org/person/alice> <http://example.org/hasItem> <http://example.org/person/alice/item/shield> .
+<http :
+
+
+
+Title : Iterable Field with Multiple Children
+Description : Test a nested field construction: iterable field with mulitple expression fields as children
+Error expected? No
+Input
+{
+ "people" : [
+ {
+ "name" : "alice" ,
+ "items" : [
+ {
+ "type" : "sword" ,
+ "weight" : 1500
+ } ,
+ {
+ "type" : "shield" ,
+ "weight" : 2500
+ }
+ ]
+ } ,
+ {
+ "name" : "bob" ,
+ "items" : [
+ {
+ "type" : "flower" ,
+ "weight" : 15
+ }
+ ]
+ }
+ ]
+}
+
+Mapping
+@prefix rml : <http ://w3id.org/rml/> .
+@prefix xsd : <http ://www.w3.org/2001 /XMLSchema#> .
+@prefix : <http ://example.org/> .
+
+:jsonSource a rml :LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.json" ;
+ ] ;
+ rml:referenceFormulation rml:JSONPath ;
+ rml:iterator "$.people[*]" .
+
+:jsonView a rml:LogicalView ;
+ rml:viewOn :jsonSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "$.name" ;
+ ] ;
+ rml:field [
+ a rml:IterableField ;
+ rml:fieldName "item" ;
+ rml:iterator "$.items[*]" ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "type" ;
+ rml:reference "$.type" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "weight" ;
+ rml:reference "$.weight" ;
+ ] ;
+ ] .
+
+:triplesMapItem a rml:TriplesMap ;
+ rml:logicalSource :jsonView ;
+ rml:subjectMap [
+ rml:template "http://example.org/person/{name}/item/{item.type}" ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasName ;
+ rml:objectMap [
+ rml:reference "item.type" ;
+ ] ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasWeight ;
+ rml:objectMap [
+ rml:reference "item.weight" ;
+ rml:datatype xsd:integer ;
+ ] ;
+ ] .
+
+Output
+<http://example.org/person/alice/item/sword> <http://example.org/hasName> "sword" .
+<http://example.org/person/alice/item/sword> <http://example.org/hasWeight> "1500" ^^<http://www.w3.org/2001 /XMLSchema#integer> .
+<http://example.org/person/alice/item/shield> <http://example.org/hasName> "shield" .
+<http://example.org/person/alice/item/shield> <http://example.org/hasWeight> "2500" ^^<http://www.w3.org/2001 /XMLSchema#integer> .
+<http://example.org/person/bob/item/flower> <http://example.org/hasName> "flower" .
+<http://example.org/person/bob/item/flower> <http://example.org/hasWeight> "15" ^^<http://www.w3.org/2001 /XMLSchema#integer> .
+
+
+
+Title : Nested Iterable Fields
+Description : Test a nested field construction: iterable field with an iterable field as child
+Error expected? No
+Input
+{
+ "people" : [
+ {
+ "name" : "alice" ,
+ "items" : [
+ {
+ "type" : "sword" ,
+ "measures" : {
+ "weight" : 1500 ,
+ "length" : 30
+ }
+ } ,
+ {
+ "type" : "shield" ,
+ "measures" : {
+ "weight" : 2500
+ }
+ }
+ ]
+ } ,
+ {
+ "name" : "bob" ,
+ "items" : [
+ {
+ "type" : "flower" ,
+ "measures" : {
+ "weight" : 15 ,
+ "length" : 15
+ }
+ }
+ ]
+ }
+ ]
+}
+
+Mapping
+@prefix rml : <http ://w3id.org/rml/> .
+@prefix xsd : <http ://www.w3.org/2001 /XMLSchema#> .
+@prefix : <http ://example.org/> .
+
+:jsonSource a rml :LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.json" ;
+ ] ;
+ rml:referenceFormulation rml:JSONPath ;
+ rml:iterator "$.people[*]" .
+
+:jsonView a rml:LogicalView ;
+ rml:viewOn :jsonSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "$.name" ;
+ ] ;
+ rml:field [
+ a rml:IterableField ;
+ rml:fieldName "item" ;
+ rml:iterator "$.items[*]" ;
+ rml:field [
+ rml:fieldName "type" ;
+ rml:reference "$.type" ;
+ ] ;
+ rml:field [
+ a rml:IterableField ;
+ rml:fieldName "measures" ;
+ rml:iterator "$.measures" ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "weight" ;
+ rml:reference "$.weight" ;
+ ];
+ ] ;
+ ] .
+
+:triplesMapItem a rml:TriplesMap ;
+ rml:logicalSource :jsonView ;
+ rml:subjectMap [
+ rml:template "http://example.org/person/{name}/item/{item.type}" ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasWeight ;
+ rml:objectMap [
+ rml:reference "item.measures.weight" ;
+ rml:datatype xsd:integer ;
+ ] ;
+ ] .
+
+Output
+<http://example.org/person/alice/item/sword> <http://example.org/hasWeight> "1500" ^^<http://www.w3.org/2001 /XMLSchema#integer> .
+<http://example.org/person/alice/item/shield> <http://example.org/hasWeight> "2500" ^^<http://www.w3.org/2001 /XMLSchema#integer> .
+<http://example.org/person/bob/item/flower> <http://example.org/hasWeight> "15" ^^<http://www.w3.org/2001 /XMLSchema#integer> .
+
+
+
+Title : Index Key: #
+Description : Test a reference to the index key #
+Error expected? No
+Input
+{
+ "people" : [
+ {
+ "name" : "alice" ,
+ "items" : [
+ {
+ "type" : "sword" ,
+ "weight" : 1500
+ } ,
+ {
+ "type" : "shield" ,
+ "weight" : 2500
+ }
+ ]
+ } ,
+ {
+ "name" : "bob" ,
+ "items" : [
+ {
+ "type" : "flower" ,
+ "weight" : 15
+ }
+ ]
+ }
+ ]
+}
+
+Mapping
+@prefix rml : <http ://w3id.org/rml/> .
+@prefix xsd : <http ://www.w3.org/2001 /XMLSchema#> .
+@prefix : <http ://example.org/> .
+
+:jsonSource a rml :LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.json" ;
+ ] ;
+ rml:referenceFormulation rml:JSONPath ;
+ rml:iterator "$.people[*]" .
+
+:jsonView a rml:LogicalView ;
+ rml:viewOn :jsonSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "$.name" ;
+ ] .
+
+:triplesMapPerson a rml:TriplesMap ;
+ rml:logicalSource :jsonView ;
+ rml:subjectMap [
+ rml:template "http://example.org/person/{name}" ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasSequenceNumber ;
+ rml:objectMap [
+ rml:reference "#" ;
+ rml:datatype xsd:integer ;
+ ] ;
+ ] .
+
+Output
+<http://example.org/person/alice> <http://example.org/hasSequenceNumber> "0" ^^<http://www.w3.org/2001 /XMLSchema#integer> .
+<http://example.org/person/bob> <http://example.org/hasSequenceNumber> "1" ^^<http://www.w3.org/2001 /XMLSchema#integer> .
+
+
+
+Title : Index Key: Iterable Field
+Description : Test a reference to the index key of an iterable field
+Error expected? No
+Input
+{
+ "people" : [
+ {
+ "name" : "alice" ,
+ "items" : [
+ {
+ "type" : "sword" ,
+ "weight" : 1500
+ } ,
+ {
+ "type" : "shield" ,
+ "weight" : 2500
+ }
+ ]
+ } ,
+ {
+ "name" : "bob" ,
+ "items" : [
+ {
+ "type" : "flower" ,
+ "weight" : 15
+ }
+ ]
+ }
+ ]
+}
+
+Mapping
+@prefix rml : <http ://w3id.org/rml/> .
+@prefix : <http ://example.org/> .
+
+:jsonSource a rml :LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.json" ;
+ ] ;
+ rml:referenceFormulation rml:JSONPath ;
+ rml:iterator "$.people[*]" .
+
+:jsonView a rml:LogicalView ;
+ rml:viewOn :jsonSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "$.name" ;
+ ] ;
+ rml:field [
+ a rml:IterableField ;
+ rml:fieldName "item" ;
+ rml:iterator "$.items[*]" ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "type" ;
+ rml:reference "$.type" ;
+ ] ;
+ ] .
+
+:triplesMapPerson a rml:TriplesMap ;
+ rml:logicalSource :jsonView ;
+ rml:subjectMap [
+ rml:template "http://example.org/person/{name}/item/{item.#}" ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasType ;
+ rml:objectMap [
+ rml:reference "item.type" ;
+ ] ;
+ ] .
+
+Output
+<http://example.org/person/alice/item/0 > <http://example.org/hasType> "sword" .
+<http://example.org/person/alice/item/1 > <http://example.org/hasType> "shield" .
+<http://example.org/person/bob/item/0 > <http://example.org/hasType> "flower" .
+
+
+
+
+Title : Index Key: Expression field
+Description : Test a reference to the index key of an expression field
+Error expected? No
+Input
+{
+ "people" : [
+ {
+ "name" : "alice" ,
+ "items" : [
+ "sword" ,
+ "shield"
+ ]
+ } ,
+ {
+ "name" : "bob" ,
+ "items" : [
+ "flower"
+ ]
+ }
+ ]
+}
+
+Mapping
+@prefix rml : <http ://w3id.org/rml/> .
+@prefix xsd : <http ://www.w3.org/2001 /XMLSchema#> .
+@prefix : <http ://example.org/> .
+
+:jsonSource a rml :LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.json" ;
+ ] ;
+ rml:referenceFormulation rml:JSONPath ;
+ rml:iterator "$.people[*]" .
+
+:jsonView a rml:LogicalView ;
+ rml:viewOn :jsonSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "$.name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "item" ;
+ rml:reference "$.items[*]" ;
+ ] .
+
+:triplesMapItem a rml:TriplesMap ;
+ rml:logicalSource :jsonView ;
+ rml:subjectMap [
+ rml:template "http://example.org/person/{name}/item/{item.#}" ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasType ;
+ rml:objectMap [
+ rml:reference "item" ;
+ ] ;
+ ] .
+
+Output
+<http://example.org/person/alice/item/0 > <http://example.org/hasType> "sword" .
+<http://example.org/person/alice/item/1 > <http://example.org/hasType> "shield" .
+<http://example.org/person/bob/item/0 > <http://example.org/hasType> "flower" .
+
+
+
+Title : Natural Datatype: Index #
+Description : Test the natural datatype mapping for the index #
+Error expected? No
+Input
+{
+ "people" : [
+ {
+ "name" : "alice" ,
+ "items" : [
+ {
+ "type" : "sword" ,
+ "weight" : 1500
+ } ,
+ {
+ "type" : "shield" ,
+ "weight" : 2500
+ }
+ ]
+ } ,
+ {
+ "name" : "bob" ,
+ "items" : [
+ {
+ "type" : "flower" ,
+ "weight" : 15
+ }
+ ]
+ }
+ ]
+}
+
+Mapping
+@prefix rml : <http ://w3id.org/rml/> .
+@prefix : <http ://example.org/> .
+
+:jsonSource a rml :LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.json" ;
+ ] ;
+ rml:referenceFormulation rml:JSONPath ;
+ rml:iterator "$.people[*]" .
+
+:jsonView a rml:LogicalView ;
+ rml:viewOn :jsonSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "$.name" ;
+ ] .
+
+:triplesMapPerson a rml:TriplesMap ;
+ rml:logicalSource :jsonView ;
+ rml:subjectMap [
+ rml:template "http://example.org/person/{name}" ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasSequenceNumber ;
+ rml:objectMap [
+ rml:reference "#" ;
+ ] ;
+ ] .
+
+Output
+<http://example.org/person/alice> <http://example.org/hasSequenceNumber> "0" ^^<http://www.w3.org/2001 /XMLSchema#integer> .
+<http://example.org/person/bob> <http://example.org/hasSequenceNumber> "1" ^^<http://www.w3.org/2001 /XMLSchema#integer> .
+
+
+
+Title : Natural Datatype: Index Expression Field
+Description : Test the natural datatype mapping for the index of an expression field
+Error expected? No
+Input
+{
+ "people" : [
+ {
+ "name" : "alice" ,
+ "items" : [
+ {
+ "type" : "sword" ,
+ "weight" : 1500
+ } ,
+ {
+ "type" : "shield" ,
+ "weight" : 2500
+ }
+ ]
+ } ,
+ {
+ "name" : "bob" ,
+ "items" : [
+ {
+ "type" : "flower" ,
+ "weight" : 15
+ }
+ ]
+ }
+ ]
+}
+
+Mapping
+@prefix rml : <http ://w3id.org/rml/> .
+@prefix : <http ://example.org/> .
+
+:jsonSource a rml :LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.json" ;
+ ] ;
+ rml:referenceFormulation rml:JSONPath ;
+ rml:iterator "$.people[*]" .
+
+:jsonView a rml:LogicalView ;
+ rml:viewOn :jsonSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "$.name" ;
+ ] ;
+ rml:field [
+ a rml:IterableField ;
+ rml:fieldName "item" ;
+ rml:iterator "$.items[*]" ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "type" ;
+ rml:reference "$.type" ;
+ ] ;
+ ] .
+
+:triplesMapPerson a rml:TriplesMap ;
+ rml:logicalSource :jsonView ;
+ rml:subjectMap [
+ rml:template "http://example.org/person/{name}/item/{item.type}" ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasSequenceNumber ;
+ rml:objectMap [
+ rml:reference "item.#" ;
+ ] ;
+ ] .
+
+Output
+<http://example.org/person/alice/item/sword> <http://example.org/hasSequenceNumber> "0" ^^<http://www.w3.org/2001 /XMLSchema#integer> .
+<http://example.org/person/alice/item/shield> <http://example.org/hasSequenceNumber> "1" ^^<http://www.w3.org/2001 /XMLSchema#integer> .
+<http://example.org/person/bob/item/flower> <http://example.org/hasSequenceNumber> "0" ^^<http://www.w3.org/2001 /XMLSchema#integer> .
+
+
+
+Title : Natural Datatype: Index Iterable Field
+Description : Test the natural datatype mapping for the index of an iterable field
+Error expected? No
+Input
+{
+ "people" : [
+ {
+ "name" : "alice" ,
+ "items" : [
+ "sword" ,
+ "shield"
+ ]
+ } ,
+ {
+ "name" : "bob" ,
+ "items" : [
+ "flower"
+ ]
+ }
+ ]
+}
+
+Mapping
+@prefix rml : <http ://w3id.org/rml/> .
+@prefix xsd : <http ://www.w3.org/2001 /XMLSchema#> .
+@prefix : <http ://example.org/> .
+
+:jsonSource a rml :LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.json" ;
+ ] ;
+ rml:referenceFormulation rml:JSONPath ;
+ rml:iterator "$.people[*]" .
+
+:jsonView a rml:LogicalView ;
+ rml:viewOn :jsonSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "$.name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "item" ;
+ rml:reference "$.items[*]" ;
+ ] .
+
+:triplesMapItem a rml:TriplesMap ;
+ rml:logicalSource :jsonView ;
+ rml:subjectMap [
+ rml:template "http://example.org/person/{name}/item/{item}" ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasSequenceNumber ;
+ rml:objectMap [
+ rml:reference "item.#" ;
+ ] ;
+ ] .
+
+Output
+<http://example.org/person/alice/item/sword> <http://example.org/hasSequenceNumber> "0" ^^<http://www.w3.org/2001 /XMLSchema#integer> .
+<http://example.org/person/alice/item/shield> <http://example.org/hasSequenceNumber> "1" ^^<http://www.w3.org/2001 /XMLSchema#integer> .
+<http://example.org/person/bob/item/flower> <http://example.org/hasSequenceNumber> "0" ^^<http://www.w3.org/2001 /XMLSchema#integer> .
+
+
+
+Title : Natural Datatype: Record Expression Field
+Description : Test the natural datatype mapping for a record of an expression field
+Error expected? No
+Input
+{
+ "people" : [
+ {
+ "name" : "alice" ,
+ "birth_year" : 1995
+ } ,
+ {
+ "name" : "bob" ,
+ "birth_year" : 1999
+ }
+ ]
+}
+
+Mapping
+@prefix rml : <http ://w3id.org/rml/> .
+@prefix xsd : <http ://www.w3.org/2001 /XMLSchema#> .
+@prefix : <http ://example.org/> .
+
+:jsonSource a rml :LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.json" ;
+ ] ;
+ rml:referenceFormulation rml:JSONPath ;
+ rml:iterator "$.people[*]" .
+
+:jsonView a rml:LogicalView ;
+ rml:viewOn :jsonSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "$.name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "birthyear" ;
+ rml:reference "$.birth_year" ;
+ ] .
+
+:triplesMapItem a rml:TriplesMap ;
+ rml:logicalSource :jsonView ;
+ rml:subjectMap [
+ rml:template "http://example.org/person/{name}" ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasBirthYear ;
+ rml:objectMap [
+ rml:reference "birthyear" ;
+ ] ;
+ ] .
+
+Output
+<http://example.org/person/alice> <http://example.org/hasBirthYear> "1995" ^^<http://www.w3.org/2001 /XMLSchema#integer> .
+<http://example.org/person/bob> <http://example.org/hasBirthYear> "1999" ^^<http://www.w3.org/2001 /XMLSchema#integer> .
+
+
+
+Title : Referencing a Non-Existing Key
+Description : Test a reference to a non-existing key
+Error expected? Yes
+Input
+{
+ "people" : [
+ {
+ "name" : "alice" ,
+ "items" : [
+ {
+ "type" : "sword" ,
+ "weight" : 1500
+ } ,
+ {
+ "type" : "shield" ,
+ "weight" : 2500
+ }
+ ]
+ } ,
+ {
+ "name" : "bob" ,
+ "items" : [
+ {
+ "type" : "flower" ,
+ "weight" : 15
+ }
+ ]
+ }
+ ]
+}
+
+Mapping
+@prefix rml : <http ://w3id.org/rml/> .
+@prefix : <http ://example.org/> .
+
+:jsonSource a rml :LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.json" ;
+ ] ;
+ rml:referenceFormulation rml:JSONPath ;
+ rml:iterator "$.people[*]" .
+
+:jsonView a rml:LogicalView ;
+ rml:viewOn :jsonSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "$.name" ;
+ ] .
+
+:triplesMapPerson a rml:TriplesMap ;
+ rml:logicalSource :jsonView ;
+ rml:subjectMap [
+ rml:template "http://example.org/person/{Name}" ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasName ;
+ rml:objectMap [
+ rml:reference "Name" ;
+ ] ;
+ ] .
+
+
+
+Title : Referencing the Record Key
+Description : Test a reference to the record key
+Error expected? Yes
+Input
+{
+ "people" : [
+ {
+ "name" : "alice" ,
+ "items" : [
+ {
+ "type" : "sword" ,
+ "weight" : 1500
+ } ,
+ {
+ "type" : "shield" ,
+ "weight" : 2500
+ }
+ ]
+ } ,
+ {
+ "name" : "bob" ,
+ "items" : [
+ {
+ "type" : "flower" ,
+ "weight" : 15
+ }
+ ]
+ }
+ ]
+}
+
+Mapping
+@prefix rml : <http ://w3id.org/rml/> .
+@prefix : <http ://example.org/> .
+
+:jsonSource a rml :LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.json" ;
+ ] ;
+ rml:referenceFormulation rml:JSONPath ;
+ rml:iterator "$.people[*]" .
+
+:jsonView a rml:LogicalView ;
+ rml:viewOn :jsonSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "$.name" ;
+ ] .
+
+:triplesMapPerson a rml:TriplesMap ;
+ rml:logicalSource :jsonView ;
+ rml:subjectMap [
+ rml:template "http://example.org/person/{name}" ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :isDerivedFrom ;
+ rml:objectMap [
+ rml:reference "<it>" ;
+ ] ;
+ ] .
+
+
+
+Title : Referencing the Record Key of an Iterable Field
+Description : Test a reference to the record key of an iterable field
+Error expected? Yes
+Input
+{
+ "people" : [
+ {
+ "name" : "alice" ,
+ "items" : [
+ {
+ "type" : "sword" ,
+ "weight" : 1500
+ } ,
+ {
+ "type" : "shield" ,
+ "weight" : 2500
+ }
+ ]
+ } ,
+ {
+ "name" : "bob" ,
+ "items" : [
+ {
+ "type" : "flower" ,
+ "weight" : 15
+ }
+ ]
+ }
+ ]
+}
+
+Mapping
+@prefix rml : <http ://w3id.org/rml/> .
+@prefix xsd : <http ://www.w3.org/2001 /XMLSchema#> .
+@prefix : <http ://example.org/> .
+
+:jsonSource a rml :LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.json" ;
+ ] ;
+ rml:referenceFormulation rml:JSONPath ;
+ rml:iterator "$.people[*]" .
+
+:jsonView a rml:LogicalView ;
+ rml:viewOn :jsonSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "$.name" ;
+ ] ;
+ rml:field [
+ a rml:IterableField ;
+ rml:fieldName "item" ;
+ rml:iterator "$.items[*]" ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "type" ;
+ rml:reference "$.type" ;
+ ] ;
+ ] .
+
+:triplesMapPerson a rml:TriplesMap ;
+ rml:logicalSource :jsonView ;
+ rml:subjectMap [
+ rml:template "http://example.org/person/{name}" ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasItem ;
+ rml:objectMap [
+ rml:template "http://example.org/person/{name}/{item}" ;
+ ] ;
+ ] .
+
+
+
+Title : Left Join
+Description : Test a left join
+Error expected? No
+Input
+{
+ "people" : [
+ {
+ "name" : "alice" ,
+ "items" : [
+ "sword" ,
+ "shield"
+ ]
+ } ,
+ {
+ "name" : "bob" ,
+ "items" : [
+ "flower"
+ ]
+ }
+ ]
+}
+
+Input 1
+name,birthyear
+alice,1995
+bob,1999
+tobias,2005
+
+Mapping
+@prefix rml: <http://w3id.org/rml/> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+@prefix : <http://example.org/> .
+
+:jsonSource a rml:LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.json" ;
+ ] ;
+ rml:referenceFormulation rml:JSONPath ;
+ rml:iterator "$.people[*]" .
+
+:jsonView a rml:LogicalView ;
+ rml:viewOn :jsonSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "$.name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "item" ;
+ rml:reference "$.items[*]" ;
+ ] .
+
+:csvSource a rml:LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.csv" ;
+ ] ;
+ rml:referenceFormulation rml:CSV .
+
+:csvView a rml:LogicalView ;
+ rml:viewOn :csvSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "birthyear" ;
+ rml:reference "birthyear" ;
+ ] ;
+ rml:leftJoin [
+ rml:parentLogicalView :jsonView ;
+ rml:joinCondition [
+ rml:parent "name" ;
+ rml:child "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "json_item" ;
+ rml:reference "item" ;
+ ] ;
+ ] .
+
+
+:triplesMapPerson a rml:TriplesMap ;
+ rml:logicalSource :csvView ;
+ rml:subjectMap [
+ rml:template "http://example.org/person/{name}" ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasBirthYear ;
+ rml:objectMap [
+ rml:reference "birthyear" ;
+ rml:datatype xsd:gYear ;
+ ] ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasItem ;
+ rml:objectMap [
+ rml:template "http://example.org/person/{name}/item/{json_item}" ;
+ ] ;
+ ] .
+
+Output
+<http://example.org/person/alice> <http://example.org/hasBirthYear> "1995" ^^<http://www.w3.org/2001 /XMLSchema#gYear> .
+<http://example.org/person/alice> <http://example.org/hasItem> <http://example.org/person/alice/item/sword> .
+<http://example.org/person/alice> <http://example.org/hasItem> <http://example.org/person/alice/item/shield> .
+<http://example.org/person/bob> <http://example.org/hasBirthYear> "1999" ^^<http://www.w3.org/2001 /XMLSchema#gYear> .
+<http://example.org/person/bob> <http://example.org/hasItem> <http://example.org/person/bob/item/flower> .
+<http://example.org/person/tobias> <http://example.org/hasBirthYear> "2005" ^^<http://www.w3.org/2001 /XMLSchema#gYear> .
+
+
+
+Title : Inner Join
+Description : Test an inner join
+Error expected? No
+Input
+{
+ "people" : [
+ {
+ "name" : "alice" ,
+ "items" : [
+ "sword" ,
+ "shield"
+ ]
+ } ,
+ {
+ "name" : "bob" ,
+ "items" : [
+ "flower"
+ ]
+ }
+ ]
+}
+
+Input 1
+name,birthyear
+alice,1995
+bob,1999
+tobias,2005
+
+Mapping
+@prefix rml : <http ://w3id.org/rml/> .
+@prefix xsd : <http ://www.w3.org/2001 /XMLSchema#> .
+@prefix : <http ://example.org/> .
+
+:jsonSource a rml :LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.json" ;
+ ] ;
+ rml:referenceFormulation rml:JSONPath ;
+ rml:iterator "$.people[*]" .
+
+:jsonView a rml:LogicalView ;
+ rml:viewOn :jsonSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "$.name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "item" ;
+ rml:reference "$.items[*]" ;
+ ] .
+
+:csvSource a rml:LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.csv" ;
+ ] ;
+ rml:referenceFormulation rml:CSV .
+
+:csvView a rml:LogicalView ;
+ rml:viewOn :csvSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "birthyear" ;
+ rml:reference "birthyear" ;
+ ] ;
+ rml:innerJoin [
+ rml:parentLogicalView :jsonView ;
+ rml:joinCondition [
+ rml:parent "name" ;
+ rml:child "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "json_item" ;
+ rml:reference "item" ;
+ ] ;
+ ] .
+
+
+:triplesMapPerson a rml:TriplesMap ;
+ rml:logicalSource :csvView ;
+ rml:subjectMap [
+ rml:template "http://example.org/person/{name}" ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasBirthYear ;
+ rml:objectMap [
+ rml:reference "birthyear" ;
+ rml:datatype xsd:gYear ;
+ ] ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasItem ;
+ rml:objectMap [
+ rml:template "http://example.org/person/{name}/item/{json_item}" ;
+ ] ;
+ ] .
+
+Output
+<http :
+<http://example.org/person/alice> <http://example.org/hasItem> <http://example.org/person/alice/item/sword> .
+<http :
+<http://example.org/person/bob> <http://example.org/hasBirthYear> "1999" ^^<http://www.w3.org/2001/XMLSchema#gYear> .
+<http://example.org/person/bob> <http://example.org/hasItem> <http://example.org/person/bob/item/flower> .
+
+
+
+Title : Two Left Joins
+Description : Test two left joins in one logical view
+Error expected? No
+Input
+{
+ "people" : [
+ {
+ "name" : "alice" ,
+ "items" : [
+ "sword" ,
+ "shield"
+ ]
+ } ,
+ {
+ "name" : "bob" ,
+ "items" : [
+ "flower"
+ ]
+ }
+ ]
+}
+
+Input 1
+name,birthyear
+alice,1995
+bob,1999
+tobias,2005
+
+Input 2
+name,id
+alice,123
+bob,456
+tobias,789
+
+Mapping
+@prefix rml: <http://w3id.org/rml/> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+@prefix : <http://example.org/> .
+
+:jsonSource a rml:LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.json" ;
+ ] ;
+ rml:referenceFormulation rml:JSONPath ;
+ rml:iterator "$.people[*]" .
+
+:jsonView a rml:LogicalView ;
+ rml:viewOn :jsonSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "$.name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "item" ;
+ rml:reference "$.items[*]" ;
+ ] .
+
+:additionalCsvSource a rml:LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people2.csv" ;
+ ] ;
+ rml:referenceFormulation rml:CSV .
+
+:additionalCsvView a rml:LogicalView ;
+ rml:viewOn :additionalCsvSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "id" ;
+ rml:reference "id" ;
+ ] ;
+.
+
+:csvSource a rml:LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.csv" ;
+ ] ;
+ rml:referenceFormulation rml:CSV .
+
+:csvView a rml:LogicalView ;
+ rml:viewOn :csvSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "birthyear" ;
+ rml:reference "birthyear" ;
+ ] ;
+ rml:leftJoin [
+ rml:parentLogicalView :jsonView ;
+ rml:joinCondition [
+ rml:parent "name" ;
+ rml:child "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "json_item" ;
+ rml:reference "item" ;
+ ] ;
+ ] ;
+ rml:leftJoin [
+ rml:parentLogicalView :additionalCsvView ;
+ rml:joinCondition [
+ rml:parent "name" ;
+ rml:child "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "csv2_id" ;
+ rml:reference "id" ;
+ ] ;
+ ] .
+
+
+:triplesMapPerson a rml:TriplesMap ;
+ rml:logicalSource :csvView ;
+ rml:subjectMap [
+ rml:template "http://example.org/person/{csv2_id}" ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasBirthYear ;
+ rml:objectMap [
+ rml:reference "birthyear" ;
+ rml:datatype xsd:gYear ;
+ ] ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasItem ;
+ rml:objectMap [
+ rml:template "http://example.org/person/{csv2_id}/item/{json_item}" ;
+ ] ;
+ ] .
+
+Output
+<http://example.org/person/123 > <http://example.org/hasBirthYear> "1995" ^^<http://www.w3.org/2001 /XMLSchema#gYear> .
+<http://example.org/person/123 > <http://example.org/hasItem> <http://example.org/person/123 /item/sword> .
+<http://example.org/person/123 > <http://example.org/hasItem> <http://example.org/person/123 /item/shield> .
+<http://example.org/person/456 > <http://example.org/hasBirthYear> "1999" ^^<http://www.w3.org/2001 /XMLSchema#gYear> .
+<http://example.org/person/456 > <http://example.org/hasItem> <http://example.org/person/456 /item/flower> .
+<http://example.org/person/789 > <http://example.org/hasBirthYear> "2005" ^^<http://www.w3.org/2001 /XMLSchema#gYear> .
+
+
+
+Title : Inner Join and Left Join
+Description : Test an inner join and a left join in one logical view
+Error expected? No
+Input
+{
+ "people" : [
+ {
+ "name" : "alice" ,
+ "items" : [
+ "sword" ,
+ "shield"
+ ]
+ } ,
+ {
+ "name" : "bob" ,
+ "items" : [
+ "flower"
+ ]
+ }
+ ]
+}
+
+Input 1
+name,birthyear
+alice,1995
+bob,1999
+tobias,2005
+
+Input 2
+name,id
+alice,123
+bob,456
+tobias,789
+
+Mapping
+@prefix rml: <http://w3id.org/rml/> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+@prefix : <http://example.org/> .
+
+:jsonSource a rml:LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.json" ;
+ ] ;
+ rml:referenceFormulation rml:JSONPath ;
+ rml:iterator "$.people[*]" .
+
+:jsonView a rml:LogicalView ;
+ rml:viewOn :jsonSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "$.name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "item" ;
+ rml:reference "$.items[*]" ;
+ ] .
+
+:additionalCsvSource a rml:LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people2.csv" ;
+ ] ;
+ rml:referenceFormulation rml:CSV .
+
+:additionalCsvView a rml:LogicalView ;
+ rml:viewOn :additionalCsvSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "id" ;
+ rml:reference "id" ;
+ ] ;
+.
+
+:csvSource a rml:LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.csv" ;
+ ] ;
+ rml:referenceFormulation rml:CSV .
+
+:csvView a rml:LogicalView ;
+ rml:viewOn :csvSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "birthyear" ;
+ rml:reference "birthyear" ;
+ ] ;
+ rml:innerJoin [
+ rml:parentLogicalView :jsonView ;
+ rml:joinCondition [
+ rml:parent "name" ;
+ rml:child "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "json_item" ;
+ rml:reference "item" ;
+ ] ;
+ ] ;
+ rml:leftJoin [
+ rml:parentLogicalView :additionalCsvView ;
+ rml:joinCondition [
+ rml:parent "name" ;
+ rml:child "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "csv2_id" ;
+ rml:reference "id" ;
+ ] ;
+ ] .
+
+
+:triplesMapPerson a rml:TriplesMap ;
+ rml:logicalSource :csvView ;
+ rml:subjectMap [
+ rml:template "http://example.org/person/{csv2_id}" ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasBirthYear ;
+ rml:objectMap [
+ rml:reference "birthyear" ;
+ rml:datatype xsd:gYear ;
+ ] ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasItem ;
+ rml:objectMap [
+ rml:template "http://example.org/person/{csv2_id}/item/{json_item}" ;
+ ] ;
+ ] .
+
+Output
+<http :
+<http://example.org/person/123> <http://example.org/hasItem> <http://example.org/person/123/item/sword> .
+<http :
+<http://example.org/person/456> <http://example.org/hasBirthYear> "1999" ^^<http://www.w3.org/2001/XMLSchema#gYear> .
+<http://example.org/person/456> <http://example.org/hasItem> <http://example.org/person/456/item/flower> .
+
+
+
+Title : Two Inner Joins
+Description : Test two left joins in one logical view
+Error expected? No
+Input
+{
+ "people" : [
+ {
+ "name" : "alice" ,
+ "items" : [
+ "sword" ,
+ "shield"
+ ]
+ } ,
+ {
+ "name" : "bob" ,
+ "items" : [
+ "flower"
+ ]
+ }
+ ]
+}
+
+Input 1
+name,birthyear
+alice,1995
+bob,1999
+tobias,2005
+
+Input 2
+name,id
+alice,123
+
+Mapping
+@prefix rml : <http ://w3id.org/rml/> .
+@prefix xsd : <http ://www.w3.org/2001 /XMLSchema#> .
+@prefix : <http ://example.org/> .
+
+:jsonSource a rml :LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.json" ;
+ ] ;
+ rml:referenceFormulation rml:JSONPath ;
+ rml:iterator "$.people[*]" .
+
+:jsonView a rml:LogicalView ;
+ rml:viewOn :jsonSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "$.name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "item" ;
+ rml:reference "$.items[*]" ;
+ ] .
+
+:additionalCsvSource a rml:LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people2.csv" ;
+ ] ;
+ rml:referenceFormulation rml:CSV .
+
+:additionalCsvView a rml:LogicalView ;
+ rml:viewOn :additionalCsvSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "id" ;
+ rml:reference "id" ;
+ ] ;
+.
+
+:csvSource a rml:LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.csv" ;
+ ] ;
+ rml:referenceFormulation rml:CSV .
+
+:csvView a rml:LogicalView ;
+ rml:viewOn :csvSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "birthyear" ;
+ rml:reference "birthyear" ;
+ ] ;
+ rml:innerJoin [
+ rml:parentLogicalView :jsonView ;
+ rml:joinCondition [
+ rml:parent "name" ;
+ rml:child "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "json_item" ;
+ rml:reference "item" ;
+ ] ;
+ ] ;
+ rml:innerJoin [
+ rml:parentLogicalView :additionalCsvView ;
+ rml:joinCondition [
+ rml:parent "name" ;
+ rml:child "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "csv2_id" ;
+ rml:reference "id" ;
+ ] ;
+ ] .
+
+
+:triplesMapPerson a rml:TriplesMap ;
+ rml:logicalSource :csvView ;
+ rml:subjectMap [
+ rml:template "http://example.org/person/{csv2_id}" ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasBirthYear ;
+ rml:objectMap [
+ rml:reference "birthyear" ;
+ rml:datatype xsd:gYear ;
+ ] ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasItem ;
+ rml:objectMap [
+ rml:template "http://example.org/person/{csv2_id}/item/{json_item}" ;
+ ] ;
+ ] .
+
+Output
+<http :
+<http://example.org/person/123> <http://example.org/hasItem> <http://example.org/person/123/item/sword> .
+<http :
+
+
+
+Title : Index Key of Field in Join
+Description : Test references to indexes of fields from a join
+Error expected? No
+Input
+{
+ "people" : [
+ {
+ "name" : "alice" ,
+ "items" : [
+ "sword" ,
+ "shield"
+ ]
+ } ,
+ {
+ "name" : "bob" ,
+ "items" : [
+ "flower"
+ ]
+ }
+ ]
+}
+
+Input 1
+name,birthyear
+alice,1995
+tobias,2005
+bob,1999
+
+Mapping
+@prefix rml : <http ://w3id.org/rml/> .
+@prefix xsd : <http ://www.w3.org/2001 /XMLSchema#> .
+@prefix : <http ://example.org/> .
+
+:jsonSource a rml :LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.json" ;
+ ] ;
+ rml:referenceFormulation rml:JSONPath ;
+ rml:iterator "$.people[*]" .
+
+:jsonView a rml:LogicalView ;
+ rml:viewOn :jsonSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "$.name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "item" ;
+ rml:reference "$.items[*]" ;
+ ] .
+
+:csvSource a rml:LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.csv" ;
+ ] ;
+ rml:referenceFormulation rml:CSV .
+
+:csvView a rml:LogicalView ;
+ rml:viewOn :csvSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "birthyear" ;
+ rml:reference "birthyear" ;
+ ] ;
+ rml:innerJoin [
+ rml:parentLogicalView :jsonView ;
+ rml:joinCondition [
+ rml:parent "name" ;
+ rml:child "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "json_item" ;
+ rml:reference "item" ;
+ ] ;
+ ] .
+
+
+:triplesMapPerson a rml:TriplesMap ;
+ rml:logicalSource :csvView ;
+ rml:subjectMap [
+ rml:template "http://example.org/person/{#}" ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasBirthYear ;
+ rml:objectMap [
+ rml:reference "birthyear" ;
+ rml:datatype xsd:gYear ;
+ ] ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasItem ;
+ rml:objectMap [
+ rml:template "http://example.org/person/{#}/item/{json_item.#}/{json_item}" ;
+ ] ;
+ ] .
+
+Output
+<http :
+<http://example.org/person/0> <http://example.org/hasItem> <http://example.org/person/0/item/0/sword> .
+<http :
+<http://example.org/person/2> <http://example.org/hasBirthYear> "1999" ^^<http://www.w3.org/2001/XMLSchema#gYear> .
+<http://example.org/person/2> <http://example.org/hasItem> <http://example.org/person/2/item/0/flower> .
+
+
+
+
+Title : Change Reference Formulations: CSV including JSON array
+Description : Test a change of reference formulations: csv source including json array
+Error expected? No
+Input
+name,items
+alice,"[{"" type"" :"" sword"" ,"" weight"" :1500},{"" type"" :"" shield"" ,"" weight"" :2500}] "
+bob,"[{"" type"" :"" flower"" ,"" weight"" :15}] "
+
+Mapping
+@prefix rml : <http ://w3id.org/rml/> .
+@prefix xsd : <http ://www.w3.org/2001 /XMLSchema#> .
+@prefix : <http ://example.org/> .
+
+:mixedCSVSource a rml :LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.csv" ;
+ ] ;
+ rml:referenceFormulation rml:CSV .
+
+:mixedCSVView a rml:LogicalView ;
+ rml:viewOn :mixedCSVSource ;
+ rml:field [
+ a rml:ExpressionField;
+ rml:fieldName "name" ;
+ rml:reference "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "items" ;
+ rml:reference "items" ;
+ rml:field [
+ a rml:IterableField ;
+ rml:referenceFormulation rml:JSONPath ;
+ rml:iterator "$[*]" ;
+ rml:fieldName "item" ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "type" ;
+ rml:reference "$.type" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "weight" ;
+ rml:reference "$.weight" ;
+ ] ;
+ ] ;
+ ] .
+
+:triplesMapItem a rml:TriplesMap ;
+ rml:logicalSource :mixedCSVView ;
+ rml:subjectMap [
+ rml:template "http://example.org/item_{#}_{items.item.#}" ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasType ;
+ rml:objectMap [
+ rml:reference "items.item.type" ;
+ ] ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasWeight ;
+ rml:objectMap [
+ rml:reference "items.item.weight" ;
+ rml:datatype xsd:integer ;
+ ] ;
+ ] .
+
+Output
+<http://example.org/item_0_0> <http://example.org/hasType> "sword" .
+<http://example.org/item_0_0> <http://example.org/hasWeight> "1500" ^^<http://www.w3.org/2001 /XMLSchema#integer> .
+<http://example.org/item_0_1> <http://example.org/hasType> "shield" .
+<http://example.org/item_0_1> <http://example.org/hasWeight> "2500" ^^<http://www.w3.org/2001 /XMLSchema#integer> .
+<http://example.org/item_1_0> <http://example.org/hasType> "flower" .
+<http://example.org/item_1_0> <http://example.org/hasWeight> "15" ^^<http://www.w3.org/2001 /XMLSchema#integer> .
+
+
+
+Title : Change Reference Formulations: CSV including JSON object
+Description : Test a change of reference formulations: csv source including json object
+Error expected? No
+Input
+name,item
+alice,"{" "type" ":" "sword" "," "weight" ":1500}"
+alice,"{" "type" ":" "shield" "," "weight" ":2500}"
+bob,"{" "type" ":" "flower" "," "weight" ":15}"
+
+Mapping
+@prefix rml : <http ://w3id.org/rml/> .
+@prefix xsd : <http ://www.w3.org/2001 /XMLSchema#> .
+@prefix : <http ://example.org/> .
+
+:mixedCSVSource a rml :LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.csv" ;
+ ] ;
+ rml:referenceFormulation rml:CSV .
+
+:mixedCSVView a rml:LogicalView ;
+ rml:viewOn :mixedCSVSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "item" ;
+ rml:reference "item" ;
+ rml:field [
+ a rml:IterableField ;
+ rml:referenceFormulation rml:JSONPath ;
+ rml:iterator "$" ;
+ rml:fieldName "itemJson" ;
+ rml:field [
+ a rml:ExpressionField;
+ rml:fieldName "type" ;
+ rml:reference "$.type" ; ] ;
+ rml:field [
+ a rml:ExpressionField;
+ rml:fieldName "weight" ;
+ rml:reference "$.weight" ;
+ ] ;
+ ] ;
+ ] .
+
+:triplesMapItem a rml:TriplesMap ;
+ rml:logicalSource :mixedCSVView ;
+ rml:subjectMap [
+ rml:template "http://example.org/item_{#}_{item.#}" ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasType ;
+ rml:objectMap [
+ rml:reference "item.itemJson.type" ;
+ ] ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasWeight ;
+ rml:objectMap [
+ rml:reference "item.itemJson.weight" ;
+ rml:datatype xsd:integer ;
+ ] ;
+ ] .
+
+Output
+<http://example.org/item_0_0> <http://example.org/hasType> "sword" .
+<http://example.org/item_0_0> <http://example.org/hasWeight> "1500" ^^<http://www.w3.org/2001 /XMLSchema#integer> .
+<http://example.org/item_1_0> <http://example.org/hasType> "shield" .
+<http://example.org/item_1_0> <http://example.org/hasWeight> "2500" ^^<http://www.w3.org/2001 /XMLSchema#integer> .
+<http://example.org/item_2_0> <http://example.org/hasType> "flower" .
+<http://example.org/item_2_0> <http://example.org/hasWeight> "15" ^^<http://www.w3.org/2001 /XMLSchema#integer> .
+
+
+
+Title : Change Reference Formulations: JSON including CSV
+Description : Test a change of reference formulations: json source including csv data
+Error expected? No
+Input
+{
+ "people" : [
+ {
+ "name" : "alice" ,
+ "items" : "type,weight\nsword,1500\nshield,2500"
+ } ,
+ {
+ "name" : "bob" ,
+ "items" : "type,weight\nflower,15"
+ }
+ ]
+}
+
+Mapping
+@prefix rml : <http ://w3id.org/rml/> .
+@prefix xsd : <http ://www.w3.org/2001 /XMLSchema#> .
+@prefix : <http ://example.org/> .
+
+:mixedJSONSource a rml :LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.json" ;
+ ] ;
+ rml:referenceFormulation rml:JSONPath ;
+ rml:iterator "$.people[*]" .
+
+:mixedJSONView a rml:LogicalView ;
+ rml:viewOn :mixedJSONSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "$.name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "items" ;
+ rml:reference "$.items" ;
+ rml:field [
+ a rml:IterableField ;
+ rml:referenceFormulation rml:CSV ;
+ rml:fieldName "item" ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "type" ;
+ rml:reference "type" ;
+ ] ;
+ rml:field [
+ a rml:expressionField ;
+ rml:fieldName "weight" ;
+ rml:reference "weight" ;
+ ] ;
+ ] ;
+ ].
+
+:triplesMapItem a rml:TriplesMap ;
+ rml:logicalSource :mixedJSONView ;
+ rml:subjectMap [
+ rml:template "http://example.org/item_{#}_{items.item.#}" ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasType ;
+ rml:objectMap [
+ rml:reference "items.item.type" ;
+ ] ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasWeight ;
+ rml:objectMap [
+ rml:reference "items.item.weight" ;
+ rml:datatype xsd:integer ;
+ ] ;
+ ] .
+
+Output
+<http://example.org/item_0_0> <http://example.org/hasType> "sword" .
+<http://example.org/item_0_0> <http://example.org/hasWeight> "1500" ^^<http://www.w3.org/2001 /XMLSchema#integer> .
+<http://example.org/item_0_1> <http://example.org/hasType> "shield" .
+<http://example.org/item_0_1> <http://example.org/hasWeight> "2500" ^^<http://www.w3.org/2001 /XMLSchema#integer> .
+<http://example.org/item_1_0> <http://example.org/hasType> "flower" .
+<http://example.org/item_1_0> <http://example.org/hasWeight> "15" ^^<http://www.w3.org/2001 /XMLSchema#integer> .
+
+
+
+Title : Cycle: Abstract Logical Source
+Description : Test a cycle in the abstract logical source of a logical view
+Error expected? Yes
+Mapping
+@prefix rml : <http ://w3id.org/rml/> .
+@prefix : <http ://example.org/> .
+
+:view1 a rml :LogicalView ;
+ rml:viewOn :view2 ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name1" ;
+ rml:reference "name2" ;
+ ] .
+
+:view2 a rml:LogicalView ;
+ rml:viewOn :view1 ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name2" ;
+ rml:reference "name1" ;
+ ] .
+
+:triplesMapPerson a rml:TriplesMap ;
+ rml:logicalSource :view2 ;
+ rml:subjectMap [
+ rml:template "http://example.org/person/{name2}" ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasName ;
+ rml:objectMap [
+ rml:reference "name2" ;
+ ] ;
+ ] .
+
+
+
+Title : Cycle: Joins
+Description : Test a cycle in two joins of two logical views
+Error expected? Yes
+Input
+{
+ "people" : [
+ {
+ "name" : "alice" ,
+ "items" : [
+ "sword" ,
+ "shield"
+ ]
+ } ,
+ {
+ "name" : "bob" ,
+ "items" : [
+ "flower"
+ ]
+ }
+ ]
+}
+
+Input 1
+name,birthyear
+alice,1995
+bob,1999
+tobias,2005
+
+Mapping
+@prefix rml: <http://w3id.org/rml/> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+@prefix : <http://example.org/> .
+
+:jsonSource a rml:LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.json" ;
+ ] ;
+ rml:referenceFormulation rml:JSONPath ;
+ rml:iterator "$.people[*]" .
+
+:jsonView a rml:LogicalView ;
+ rml:viewOn :jsonSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "$.name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "item" ;
+ rml:reference "$.items[*]" ;
+ ] ;
+ rml:leftJoin [
+ rml:parentLogicalView :csvView ;
+ rml:joinCondition [
+ rml:parent "name" ;
+ rml:child "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "csv_birthyear" ;
+ rml:reference "birthyear" ;
+ ] ;
+ ] .
+
+:csvSource a rml:LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.csv" ;
+ ] ;
+ rml:referenceFormulation rml:CSV .
+
+:csvView a rml:LogicalView ;
+ rml:viewOn :csvSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "birthyear" ;
+ rml:reference "birthyear" ;
+ ] ;
+ rml:leftJoin [
+ rml:parentLogicalView :jsonView ;
+ rml:joinCondition [
+ rml:parent "name" ;
+ rml:child "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "json_item" ;
+ rml:reference "item" ;
+ ] ;
+ ] .
+
+
+:triplesMapPerson a rml:TriplesMap ;
+ rml:logicalSource :csvView ;
+ rml:subjectMap [
+ rml:template "http://example.org/person/{name}" ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasBirthYear ;
+ rml:objectMap [
+ rml:reference "birthyear" ;
+ rml:datatype xsd:gYear ;
+ ] ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasItem ;
+ rml:objectMap [
+ rml:template "http://example.org/person/{name}/item/{json_item}" ;
+ ] ;
+ ] .
+
+
+
+Title : Cycle: Self-Join
+Description : Test a cycle in a join of a logical view: self-join
+Error expected? Yes
+Input
+{
+ "people" : [
+ {
+ "name" : "alice" ,
+ "items" : [
+ {
+ "type" : "sword" ,
+ "weight" : 1500
+ } ,
+ {
+ "type" : "shield" ,
+ "weight" : 2500
+ }
+ ]
+ } ,
+ {
+ "name" : "bob" ,
+ "items" : [
+ {
+ "type" : "flower" ,
+ "weight" : 15
+ }
+ ]
+ }
+ ]
+}
+
+Mapping
+@prefix rml : <http://w3id.org/rml/> .
+@prefix : <http://example.org/> .
+
+:jsonSource a rml :LogicalSource ;
+ rml :source [
+ a rml :RelativePathSource , rml :Source ;
+ rml :root rml :MappingDirectory ;
+ rml :path "people.json" ;
+ ] ;
+ rml :referenceFormulation rml :JSON Path ;
+ rml :iterator "$.people[*]" .
+
+:jsonView a rml :LogicalView ;
+ rml :viewOn :jsonSource ;
+ rml :field [
+ a rml :ExpressionField ;
+ rml :fieldName "name" ;
+ rml :reference "$.name" ;
+ ] ;
+ rml :leftJoin [
+ rml :parentLogicalView :jsonView ;
+ rml :joinCondition [
+ rml :parent "name" ;
+ rml :child "name" ;
+ ] ;
+ rml :field [
+ a rml :ExpressionField ;
+ rml :fieldName "newName" ;
+ rml :reference "name" ;
+ ] ;
+ ] .
+
+:triplesMapPerson a rml :TriplesMap ;
+ rml :logicalSource :jsonView ;
+ rml :subjectMap [
+ rml :template "http://example.org/person/{newName}" ;
+ ] ;
+ rml :predicateObjectMap [
+ rml :predicate :hasName ;
+ rml :objectMap [
+ rml :reference "newName" ;
+ ] ;
+ ] .
+
+
+
+Title : Cycle: Fields
+Description : Test a cycle in nested fields
+Error expected? Yes
+Input
+{
+ "people" : [
+ {
+ "name" : "alice" ,
+ "items" : [
+ {
+ "type" : "sword" ,
+ "weight" : 1500
+ } ,
+ {
+ "type" : "shield" ,
+ "weight" : 2500
+ }
+ ]
+ } ,
+ {
+ "name" : "bob" ,
+ "items" : [
+ {
+ "type" : "flower" ,
+ "weight" : 15
+ }
+ ]
+ }
+ ]
+}
+
+Mapping
+@prefix rml : <http ://w3id.org/rml/> .
+@prefix : <http ://example.org/> .
+
+:jsonSource a rml :LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.json" ;
+ ] ;
+ rml:referenceFormulation rml:JSONPath ;
+ rml:iterator "$.people[*]" .
+
+:jsonView a rml:LogicalView ;
+ rml:viewOn :jsonSource ;
+ rml:field :field1 .
+
+:field1 a rml:IterableField ;
+ rml:fieldName "item" ;
+ rml:referenceFormulation rml:JSONPath ;
+ rml:iterator "$.items[*]" ;
+ rml:field :field2.
+
+:field2 a rml:ExpressionField ;
+ rml:fieldName "type" ;
+ rml:reference "$.type" ;
+ rml:field :field1.
+
+
+
+Title : Name collision: between Fields with the same Parent
+Description : Test a name collision between fields with the same parent
+Error expected? Yes
+Input
+{
+ "people" : [
+ {
+ "givenName" : "Alice" ,
+ "familyName" : "Smith"
+ } ,
+ {
+ "givenName" : "Bob" ,
+ "familyName" : "Johnson"
+ }
+ ]
+}
+
+Mapping
+@prefix rml : <http://w3id.org/rml/> .
+@prefix : <http://example.org/> .
+
+:jsonSource a rml :LogicalSource ;
+ rml :source [
+ a rml :RelativePathSource , rml :Source ;
+ rml :root rml :MappingDirectory ;
+ rml :path "people.json" ;
+ ] ;
+ rml :referenceFormulation rml :JSON Path ;
+ rml :iterator "$.people[*]" .
+
+:jsonView a rml :LogicalView ;
+ rml :viewOn :jsonSource ;
+ rml :field [
+ a rml :ExpressionField ;
+ rml :fieldName "name" ;
+ rml :reference "$.givenName" ;
+ ], [
+ a rml :ExpressionField ;
+ rml :fieldName "name" ;
+ rml :reference "$.familyName" ;
+ ] .
+
+:triplesMapPerson a rml :TriplesMap ;
+ rml :logicalSource :jsonView ;
+ rml :subjectMap [
+ rml :template "http://example.org/person/{name}" ;
+ ] ;
+ rml :predicateObjectMap [
+ rml :predicate :hasName ;
+ rml :objectMap [
+ rml :reference "name" ;
+ ] ;
+ ] .
+
+
+
+Title : Name collision: caused by Field from a Join
+Description : Test a name collision caused by a field from a join
+Error expected? Yes
+Input
+{
+ "people" : [
+ {
+ "givenName" : "alice" ,
+ "familyName" : "smith" ,
+ "items" : [
+ "sword" ,
+ "shield"
+ ]
+ } ,
+ {
+ "givenName" : "bob" ,
+ "familyName" : "johnson" ,
+ "items" : [
+ "flower"
+ ]
+ }
+ ]
+}
+
+Input 1
+name,birthyear
+alice,1995
+bob,1999
+tobias,2005
+
+Mapping
+@prefix rml: <http://w3id.org/rml/> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+@prefix : <http://example.org/> .
+
+:jsonSource a rml:LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.json" ;
+ ] ;
+ rml:referenceFormulation rml:JSONPath ;
+ rml:iterator "$.people[*]" .
+
+:jsonView a rml:LogicalView ;
+ rml:viewOn :jsonSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "givenName" ;
+ rml:reference "$.givenName" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "familyName" ;
+ rml:reference "$.familyName" ;
+ ] .
+
+:csvSource a rml:LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.csv" ;
+ ] ;
+ rml:referenceFormulation rml:CSV .
+
+:csvView a rml:LogicalView ;
+ rml:viewOn :csvSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "birthyear" ;
+ rml:reference "birthyear" ;
+ ] ;
+ rml:leftJoin [
+ rml:parentLogicalView :jsonView ;
+ rml:joinCondition [
+ rml:parent "givenName" ;
+ rml:child "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "familyName" ;
+ ] ;
+ ] .
+
+
+:triplesMapPerson a rml:TriplesMap ;
+ rml:logicalSource :csvView ;
+ rml:subjectMap [
+ rml:template "http://example.org/person/{name}" ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasBirthYear ;
+ rml:objectMap [
+ rml:reference "birthyear" ;
+ rml:datatype xsd:gYear ;
+ ] ;
+ ] .
+
+
+
+Title : Name collision: between Fields from different Joins
+Description : Test a name collision between fields from different joins
+Error expected? Yes
+Input
+{
+ "people" : [
+ {
+ "name" : "alice" ,
+ "items" : [
+ "sword" ,
+ "shield"
+ ]
+ } ,
+ {
+ "name" : "bob" ,
+ "items" : [
+ "flower"
+ ]
+ }
+ ]
+}
+
+Input 1
+name,id
+alice,123
+bob,456
+tobias,789
+
+Input 2
+name,item
+alice,lantern
+bob,leaf
+
+Mapping
+@prefix rml: <http://w3id.org/rml/> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+@prefix : <http://example.org/> .
+
+:jsonSource a rml:LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.json" ;
+ ] ;
+ rml:referenceFormulation rml:JSONPath ;
+ rml:iterator "$.people[*]" .
+
+:jsonView a rml:LogicalView ;
+ rml:viewOn :jsonSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "$.name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "jsonitem" ;
+ rml:reference "$.items[*]" ;
+ ] .
+
+:additionalCsvSource a rml:LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people2.csv" ;
+ ] ;
+ rml:referenceFormulation rml:CSV .
+
+:additionalCsvView a rml:LogicalView ;
+ rml:viewOn :additionalCsvSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "csvitem" ;
+ rml:reference "item" ;
+ ] ;
+.
+
+:csvSource a rml:LogicalSource ;
+ rml:source [
+ a rml:RelativePathSource , rml:Source ;
+ rml:root rml:MappingDirectory ;
+ rml:path "people.csv" ;
+ ] ;
+ rml:referenceFormulation rml:CSV .
+
+:csvView a rml:LogicalView ;
+ rml:viewOn :csvSource ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "name" ;
+ rml:reference "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "id" ;
+ rml:reference "id" ;
+ ] ;
+ rml:leftJoin [
+ rml:parentLogicalView :jsonView ;
+ rml:joinCondition [
+ rml:parent "name" ;
+ rml:child "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "item" ;
+ rml:reference "jsonitem" ;
+ ] ;
+ ] ;
+ rml:leftJoin [
+ rml:parentLogicalView :additionalCsvView ;
+ rml:joinCondition [
+ rml:parent "name" ;
+ rml:child "name" ;
+ ] ;
+ rml:field [
+ a rml:ExpressionField ;
+ rml:fieldName "item" ;
+ rml:reference "csvitem" ;
+ ] ;
+ ] .
+
+
+:triplesMapPerson a rml:TriplesMap ;
+ rml:logicalSource :csvView ;
+ rml:subjectMap [
+ rml:template "http://example.org/person/{id}" ;
+ ] ;
+ rml:predicateObjectMap [
+ rml:predicate :hasItem ;
+ rml:objectMap [
+ rml:template "http://example.org/person/{id}/item/{item}" ;
+ ] ;
+ ] .
+
+
+
+
+
+
+
+ ↑
+