Nili
Nili

Reputation: 333

How to map children element of an xml file using RML to create an RDF?

I'd like to create an RDF using RML mapping. The XML part is shown below. I have made a triple map for "Attribute" and "FB". One of the FB has a child "Attribute", but in the result, each "FB" Triples has "Attribute". Is there any solution for that to make the child "Attribute" unique for just one "FB" element?

  <Application ID="A4ABD8400116F035" Name="HotWater">
<SubAppNetwork>
  <FB ID="3D77F5AE3E23F522" Name="HW_setpoint" Type="CAThmiInput" x="360" y="880" Namespace="nxtControl.Tutorial" />
  <FB ID="38615A5C87F12AA3" Name="HW_pump1" Type="CATmotor" x="2760" y="260" Namespace="nxtControl.Tutorial" />
  <FB ID="3632883FE07D2F09" Name="HW_pump2" Type="CATmotor" x="2760" y="860" Namespace="nxtControl.Tutorial">
    <Parameter Name="AutoOn" Value="TRUE" />
  </FB>
  <FB ID="FB64994118EB2489" Name="HW_pidController" Type="CATpidController" x="1000" y="260" Namespace="nxtControl.Tutorial" />
  <FB ID="1C32C8BEDD84AAA7" Name="HW_sensor" Type="CATsensor" x="360" y="260" Namespace="nxtControl.Tutorial" />
  <FB ID="97DE5397424C589F" Name="HW_valve" Type="CATvalve" x="1620" y="260" Namespace="nxtControl.Tutorial" />
  <FB ID="3A265436F99A7B87" Name="HW_compare" Type="COMPARE_1990CFD1468AAE4A6" x="2220" y="260" Namespace="Main">
    <Attribute Name="Configuration.GenericFBType.InterfaceParams" Value="Runtime.Standard#CNT:=2;IN${CNT}:LREAL" />
    <Parameter Name="IN2" Value="0.0" />
  </FB>
  <EventConnections>
    <Connection Source="HW_sensor.CNF" Destination="HW_pidController.REQ" />
    <Connection Source="HW_setpoint.CNF" Destination="HW_pidController.REQ" dx1="110.7709">
      <AvoidsNodes>false</AvoidsNodes>
    </Connection>
    <Connection Source="HW_pidController.CNF" Destination="HW_valve.REQ" />
    <Connection Source="HW_valve.CNF" Destination="HW_compare.REQ" />
    <Connection Source="HW_compare.CNF" Destination="HW_pump1.REQ" />
  </EventConnections>
  <DataConnections>
    <Connection Source="HW_sensor.outValue" Destination="HW_pidController.pv" dx1="41.3125" />
    <Connection Source="HW_setpoint.value" Destination="HW_pidController.sp" dx1="170.7709">
      <AvoidsNodes>false</AvoidsNodes>
    </Connection>
    <Connection Source="HW_pidController.cp" Destination="HW_valve.AutoSP" />
    <Connection Source="HW_compare.GT" Destination="HW_pump1.AutoOn" dx1="70" />
    <Connection Source="HW_valve.cp" Destination="HW_compare.IN1" />
  </DataConnections>
</SubAppNetwork>

Mapping:

  <#AttributeMapping>
  a rr:TriplesMap;
  rml:logicalSource [
    rml:source "System.xml" ;
    rml:iterator "/System/Application/SubAppNetwork/FB/Attribute";
    rml:referenceFormulation ql:XPath
  ];

rr:subjectMap [
rr:template "http://sth/example#/SubAppNetwork/FB/Attribute-{@Name}";
rr:class iec61499:Attribute
];

rr:predicateObjectMap [
rr:predicate iec61499:hasName;
rr:objectMap [
  rml:reference "@Name"
];
];

rr:predicateObjectMap [
rr:predicate iec61499:hasValue;
rr:objectMap [
  rml:reference "@Value"
];
].


<#FBMapping>
a rr:TriplesMap;
rml:logicalSource [
rml:source "System.xml" ;
rml:iterator "/System/Application/SubAppNetwork/FB";
rml:referenceFormulation ql:XPath
];

rr:subjectMap [
rr:template "http://sth/example#/SubAppNetwork/FB-{../../../@Name}-{@ID}";
rr:class iec61499:FB
];

rr:predicateObjectMap [
rr:predicate iec61499:hasID;
rr:objectMap [
  rml:reference "@ID"
];
];

rr:predicateObjectMap [
rr:predicate iec61499:hasName;
rr:objectMap [
  rml:reference "@Name"
];
];

rr:predicateObjectMap [
rr:predicate iec61499:hasType;
rr:objectMap [
  rml:reference "@Type"
];
];

rr:predicateObjectMap [
rr:predicate iec61499:hasX;
rr:objectMap [
  rml:reference "@x"
];
];

rr:predicateObjectMap [
rr:predicate iec61499:hasY;
rr:objectMap [
  rml:reference "@y"
];
];

rr:predicateObjectMap [
rr:predicate iec61499:hasNamespace;
rr:objectMap [
  rml:reference "@Namespace"
];
];

rr:predicateObjectMap [
rr:predicate iec61499:hasAttribute;
rr:objectMap [
  rr:parentTriplesMap <#AttributeMapping>
];
].

Upvotes: 1

Views: 361

Answers (1)

Dylan Van Assche
Dylan Van Assche

Reputation: 540

You can link a child to its parent in RML with an rr:joinCondition:

rr:predicateObjectMap [
        rr:predicate iec61499:hasAttribute;
        rr:objectMap [
            rr:parentTriplesMap <#AttributeMapping>;
            rr:joinCondition [
                rr:child "@Name";
                rr:parent "../@Name"
            ];
        ];
    ].

The rr:joinCondition will make sure that the join only happens when the values of rr:child and rr:parent are equal to each other.

I modified your data since the XML was invalid, the </Application> end tag was missing, you can find the new data below:

<Application ID="A4ABD8400116F035" Name="HotWater">
    <SubAppNetwork>
        <FB ID="3D77F5AE3E23F522" Name="HW_setpoint" Type="CAThmiInput" x="360" y="880" Namespace="nxtControl.Tutorial" />
        <FB ID="38615A5C87F12AA3" Name="HW_pump1" Type="CATmotor" x="2760" y="260" Namespace="nxtControl.Tutorial" />
        <FB ID="3632883FE07D2F09" Name="HW_pump2" Type="CATmotor" x="2760" y="860" Namespace="nxtControl.Tutorial">
            <Parameter Name="AutoOn" Value="TRUE" />
        </FB>
        <FB ID="FB64994118EB2489" Name="HW_pidController" Type="CATpidController" x="1000" y="260" Namespace="nxtControl.Tutorial" />
        <FB ID="1C32C8BEDD84AAA7" Name="HW_sensor" Type="CATsensor" x="360" y="260" Namespace="nxtControl.Tutorial" />
        <FB ID="97DE5397424C589F" Name="HW_valve" Type="CATvalve" x="1620" y="260" Namespace="nxtControl.Tutorial" />
        <FB ID="3A265436F99A7B87" Name="HW_compare" Type="COMPARE_1990CFD1468AAE4A6" x="2220" y="260" Namespace="Main">
            <Attribute Name="Configuration.GenericFBType.InterfaceParams" Value="Runtime.Standard#CNT:=2;IN${CNT}:LREAL" />
            <Parameter Name="IN2" Value="0.0" />
        </FB>
        <EventConnections>
            <Connection Source="HW_sensor.CNF" Destination="HW_pidController.REQ" />
            <Connection Source="HW_setpoint.CNF" Destination="HW_pidController.REQ" dx1="110.7709">
                <AvoidsNodes>false</AvoidsNodes>
            </Connection>
            <Connection Source="HW_pidController.CNF" Destination="HW_valve.REQ" />
            <Connection Source="HW_valve.CNF" Destination="HW_compare.REQ" />
            <Connection Source="HW_compare.CNF" Destination="HW_pump1.REQ" />
        </EventConnections>
        <DataConnections>
            <Connection Source="HW_sensor.outValue" Destination="HW_pidController.pv" dx1="41.3125" />
            <Connection Source="HW_setpoint.value" Destination="HW_pidController.sp" dx1="170.7709">
                <AvoidsNodes>false</AvoidsNodes>
            </Connection>
            <Connection Source="HW_pidController.cp" Destination="HW_valve.AutoSP" />
            <Connection Source="HW_compare.GT" Destination="HW_pump1.AutoOn" dx1="70" />
            <Connection Source="HW_valve.cp" Destination="HW_compare.IN1" />
        </DataConnections>
    </SubAppNetwork>
</Application>

I reduced your example to the bare minimum and added the rr:joinCondition to perform the join only when the Name attribute of FB matches for the parent and its child:

@base <http://example.org/> .
@prefix rml: <http://semweb.mmlab.be/ns/rml#> .
@prefix rr: <http://www.w3.org/ns/r2rml#> .
@prefix ql: <http://semweb.mmlab.be/ns/ql#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix schema: <http://schema.org/> .
@prefix dbo: <http://dbpedia.org/ontology/> .
@prefix iec61499: <http://example.org/iec61499/> . 

<#AttributeMapping>
    a rr:TriplesMap;
    rml:logicalSource [
        rml:source "System.xml";
        rml:referenceFormulation ql:XPath;
        rml:iterator "/Application/SubAppNetwork/FB/Attribute"
    ];

    rr:subjectMap [
        rr:template "http://sth/example#/SubAppNetwork/FB/Attribute-{@Name}";
        rr:class iec61499:Attribute
    ];

    rr:predicateObjectMap [
        rr:predicate iec61499:hasName;
        rr:objectMap [
            rml:reference "@Name"
        ];
    ].

<#FBMapping>
    a rr:TriplesMap;
    rml:logicalSource [
        rml:source "System.xml" ;
        rml:iterator "/Application/SubAppNetwork/FB";
        rml:referenceFormulation ql:XPath
    ];

    rr:subjectMap [
        rr:template "http://sth/example#/SubAppNetwork/FB-{../../@Name}-{@ID}";
        rr:class iec61499:FB
    ];

    rr:predicateObjectMap [
        rr:predicate iec61499:hasName;
        rr:objectMap [
            rml:reference "@Name"
        ];
    ];

    rr:predicateObjectMap [
        rr:predicate iec61499:hasAttribute;
        rr:objectMap [
            rr:parentTriplesMap <#AttributeMapping>;
            rr:joinCondition [
                rr:child "@Name";
                rr:parent "../@Name"
            ];
        ];
    ].

If you provide an RML processor these mappings and data, you will get the following output:

<http://sth/example#/SubAppNetwork/FB/Attribute-Configuration.GenericFBType.InterfaceParams> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/iec61499/Attribute>.
<http://sth/example#/SubAppNetwork/FB/Attribute-Configuration.GenericFBType.InterfaceParams> <http://example.org/iec61499/hasName> "Configuration.GenericFBType.InterfaceParams".
<http://sth/example#/SubAppNetwork/FB-HotWater-3D77F5AE3E23F522> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/iec61499/FB>.
<http://sth/example#/SubAppNetwork/FB-HotWater-3D77F5AE3E23F522> <http://example.org/iec61499/hasName> "HW_setpoint".
<http://sth/example#/SubAppNetwork/FB-HotWater-38615A5C87F12AA3> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/iec61499/FB>.
<http://sth/example#/SubAppNetwork/FB-HotWater-38615A5C87F12AA3> <http://example.org/iec61499/hasName> "HW_pump1".
<http://sth/example#/SubAppNetwork/FB-HotWater-3632883FE07D2F09> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/iec61499/FB>.
<http://sth/example#/SubAppNetwork/FB-HotWater-3632883FE07D2F09> <http://example.org/iec61499/hasName> "HW_pump2".
<http://sth/example#/SubAppNetwork/FB-HotWater-FB64994118EB2489> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/iec61499/FB>.
<http://sth/example#/SubAppNetwork/FB-HotWater-FB64994118EB2489> <http://example.org/iec61499/hasName> "HW_pidController".
<http://sth/example#/SubAppNetwork/FB-HotWater-1C32C8BEDD84AAA7> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/iec61499/FB>.
<http://sth/example#/SubAppNetwork/FB-HotWater-1C32C8BEDD84AAA7> <http://example.org/iec61499/hasName> "HW_sensor".
<http://sth/example#/SubAppNetwork/FB-HotWater-97DE5397424C589F> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/iec61499/FB>.
<http://sth/example#/SubAppNetwork/FB-HotWater-97DE5397424C589F> <http://example.org/iec61499/hasName> "HW_valve".
<http://sth/example#/SubAppNetwork/FB-HotWater-3A265436F99A7B87> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/iec61499/FB>.
<http://sth/example#/SubAppNetwork/FB-HotWater-3A265436F99A7B87> <http://example.org/iec61499/hasName> "HW_compare".
<http://sth/example#/SubAppNetwork/FB-HotWater-3A265436F99A7B87> <http://example.org/iec61499/hasAttribute> <http://sth/example#/SubAppNetwork/FB/Attribute-Configuration.GenericFBType.InterfaceParams>.

Note: I contribute to RML and its technologies.

Upvotes: 3

Related Questions