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" ] ;
] ;
.