Nested XML to Turtle mapping using RMLMapper

316 views Asked by At

I'm trying to create nested mappings between XML and Turtle. I'm using the RMLMapper v4.9.0 for this purpose.

Here is a sample XML file that I would like to map:

<?xml version="1.0" encoding="utf-8"?>
<persons>
    <person>
        <name>JohnDoe</name>
        <address>
            <number>123</number>
            <street>Main</street>
            <city>Anytown</city>
        </address>
        <address>
            <number>1234</number>
            <street>Second</street>
            <city>Anytown</city>
        </address>
    </person>
    <person>
        <name>JaneDoe</name>
    </person>
</persons>

Here is the Turtle output that I would like to generate:

@prefix ex: <http://example.com/> .

<http://example.com/ns#JaneDoe> a ex:Person .

<http://example.com/ns#JohnDoe> a ex:Person;
    ex:has_address [
        a ex:Address ;
        ex:has_city "Anytown";
        ex:has_number "123";
        ex:has_street "Main" .
    ] ;
    ex:has_address [
        a ex:Address ;
        ex:has_city "Anytown";
        ex:has_number "1234";
        ex:has_street "Second" .
    ] ;
.  

How can I achieve this type of nesting/format?

I've achieved a somewhat similar output by creating the subjects of the address triples as rr:termType rr:BlankNode.
However, I would prefer the subject to not be repeated and the output of square brackets instead of BlankNodes.

@prefix ex: <http://example.com/> .

<http://example.com/ns#JaneDoe> a ex:Person .

<http://example.com/ns#JohnDoe> a ex:Person;
  ex:has_address _:0 .

_:0 a ex:Address;
  ex:has_city "Anytown";
  ex:has_number "123";
  ex:has_street "Main" .

<http://example.com/ns#JohnDoe> ex:has_address _:1 .

_:1 a ex:Address;
  ex:has_city "Anytown";
  ex:has_number "1234";
  ex:has_street "Second" .

I've used the following map:

@prefix rml: <http://semweb.mmlab.be/ns/rml#>.
@prefix ql: <http://semweb.mmlab.be/ns/ql#>.
@prefix rr: <http://www.w3.org/ns/r2rml#>.
@prefix ex: <http://example.com/> .
@base <http://example.com/ns#> .


_:personMap a rr:TriplesMap ;

    # XML source file with xPath iterator
    rml:logicalSource [
        rml:source "example.xml" ;
        rml:referenceFormulation ql:XPath ;
        rml:iterator "//*[local-name()='person']"
    ] ;

    rr:subjectMap   [
                        rml:reference "name" ;
                        rr:class ex:Person ;
                    ] ;

    # address
    rr:predicateObjectMap   [   
                                rr:predicateMap [ rr:constant ex:has_address ] ;
                                rr:objectMap    [ 
                                                  rr:parentTriplesMap _:addressMap ;
                                                  rr:joinCondition [
                                                    rr:child "name" ;
                                                    rr:parent "ancestor::*/name" ;
                                                  ] ;
                                                ] ;
                            ] ;
    .


_:addressMap a rr:TriplesMap ;

    # XML source file with xPath iterator
    rml:logicalSource [
        rml:source "example.xml" ;
        rml:referenceFormulation ql:XPath ;
        rml:iterator "//*[local-name()='address']"
    ] ; 
    
    rr:subjectMap   [   
                        rr:termType rr:BlankNode ;
                        rr:class ex:Address
                    ] ;
    
    # city
    rr:predicateObjectMap   [   
                                rr:predicateMap [ rr:constant ex:has_city ] ;
                                rr:objectMap    [ rml:reference "city" ] ;
                            ] ;

    # street
    rr:predicateObjectMap   [   
                                rr:predicateMap [ rr:constant ex:has_street ] ;
                                rr:objectMap    [ rml:reference "street" ] ;
                            ] ;

    # number
    rr:predicateObjectMap   [   
                                rr:predicateMap [ rr:constant ex:has_number ] ;
                                rr:objectMap    [ rml:reference "number" ] ;
                            ] ;
    .
0

There are 0 answers