Sitelet https://github.com/RMLio/rmlmapper-java/issues/235
Skip to content

XML predicate mapping repeating child elements getting concatenated if reference includes concatenation #235

Description

@schivmeister

Environment

rmlmapper v6.5.1 (reproducible also as far back as v6.1.3)
Linux/WSL2
Java 17, 11

Namespaces

@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rr: <http://www.w3.org/ns/r2rml#> .
@prefix rml: <http://semweb.mmlab.be/ns/rml#> .
@prefix ql: <http://semweb.mmlab.be/ns/ql#> .
@prefix ex: <http://data.example.org/resource/> .
@prefix org: <http://www.w3.org/ns/org#> .
@prefix skos: <http://www.w3.org/2004/02/skos/core#> .
@prefix fnml:   <http://semweb.mmlab.be/ns/fnml#> .
@prefix fno: <https://w3id.org/function/ontology#> .
@prefix idlab-fn: <http://example.com/idlab/function/> .

Problem

Given the following kind of input XML with two Organization elements, where the first has two child Name elements:

<Directory>
	<Organization>
		<ID>123</ID>
		<Name>ABC Fast Company</Name>
		<Name>ABC FastCo</Name>
	</Organization>
	<Organization>
		<ID>456</ID>
		<Name>XYZ Inc.</Name>
	</Organization>	
</Directory>

and the following kind of RML mapping involving a custom concatenated value in the source reference:

ex:Organizations a rr:TriplesMap;
    rml:logicalSource [
        rml:source "test.xml";
        rml:iterator "/Directory/Organization";
        rml:referenceFormulation ql:XPath
    ];
    rr:subjectMap [
        rr:template "http://data.example.org/resource/Organization_{ID}";
        rr:class org:Organization
    ];
    rr:predicateObjectMap [
        rr:predicate org:name;
        rr:objectMap
            [
                rml:reference "'CustomPrefix ' || Name || ' CustomSuffix'"
            ];
    ]
.

Actual

Results in an unexpected output of the first resource's name concatenating the repeating values in between the prefix and suffix, instead of multiple comma-separated RDF/Turtle values:

ex:Organization_123 a org:Organization;
  org:name "CustomPrefix ABC Fast CompanyABC FastCo CustomSuffix" . # these are values from two Name elements

# the second resource remains unaffected (correctly formed)
ex:Organization_456 a org:Organization;
  org:name "CustomPrefix XYZ Inc. CustomSuffix" .

Expected

Should result in multiple comma-separated values mapped from the XML child elements, adhering to the condition of the reference:

ex:Organization_123 a org:Organization;
  org:name "CustomPrefix ABC Fast Company CustomSuffix", "CustomPrefix ABC FastCo CustomSuffix" .

Workaround

Template bypassing XPath expressions

This is perhaps the closest thing to an actual solution (if you don't need additional XPath complexity):

        rr:objectMap
            [
                rr:template "CustomPrefix {Name} CustomSuffix" ;
                rr:datatype xsd:string ; # an explicit type is required otherwise termType IRI is inferred and error raised
            ];

producing the correct result:

ex:Organization_123 a org:Organization;
  org:name "CustomPrefix ABC Fast Company CustomSuffix", "CustomPrefix ABC FastCo CustomSuffix" .

ex:Organization_456 a org:Organization;
  org:name "CustomPrefix XYZ Inc. CustomSuffix" .

Plain reference with out-of-band strategies

One could skip using the reference altogether and employ a different technique, with something external, to replicate the desired outcome, for e.g. using (custom) functions, or even just looking up a mapping table using a parentTriplesMap.

Removing the concatenation obviously makes it work:

        rr:objectMap
            [
                rml:reference "Name"
            ];

resulting in:

ex:Organization_123 a org:Organization;
  org:name "ABC Fast Company", "ABC FastCo" .

Reoriented iterator

Using an iterator on the child element which repeats but creating the subject using the ancestor element appears to work:

ex:Organizations a rr:TriplesMap;
    rml:logicalSource [
        rml:source "test.xml";
        rml:iterator "/Directory/Organization/Name";
        rml:referenceFormulation ql:XPath
    ];
    rr:subjectMap [
        rr:template "http://data.example.org/resource/Organization_{../ID}";
        rr:class org:Organization
    ];
    rr:predicateObjectMap [
        rr:predicate org:name;
        rr:objectMap
            [
                rml:reference "'CustomPrefix ' || . || ' CustomSuffix'"
            ];
    ]
.

However, this is unintuitive and convoluted. The correct solution would be if repeating child elements were also repeated as values for a predicateObjectMap, as they normally are with a plain reference (or template).

MWE

rml-mwe-concat-multivalue.zip (excludes template example)

Context

This may or may not be related to #227 #228.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions