Search code examples
xmlxsltxpathxslt-2.0xpath-2.0

XSLT, XPath: How to get attribute of parent element with reference on attribute of his child?


My problem is very complicated and I didn´t know how to get that to one sentence-question. So I try to explain: I am working with connector (you can see in code xml input below). As source I have attribute (xmi:id) of element "ownedBehavior" which is child of element "subgroup" and that element "subgroup" has reference in other element "group/node" and I need get the attribute of that element group.

Sample of XML input:


<packagedElement>
    <group xmi:type="ActivityPartition" xmi:id="EAID_LIFELINE_1" name="Course manager">
        <node xmi:idref="EAID_SUBGROUP_1"/>
    </group>
    <subgroup xmi:type="LoopNode" xmi:id="EAID_SUBGROUP_1" name="Loop Node">
        <ownedBehavior xmi:type="Activity" xmi:id="EAID_ACTIVITY_1" name="for each course"/>
        <ownedBehavior xmi:type="Activity" xmi:id="EAID_ACTIVITY_2" name="getCourse"/>
        <containedEdge xmi:type="ControlFlow" xmi:id="EAID_CONNECTOR1" source="EAID_ACTIVITY_2" target="EAID_ACTIVITY_3"/>
    </subgroup>
    <group xmi:type="ActivityPartition" xmi:id="EAID_LIFELINE_2" name="Course">
        <node xmi:idref="EAID_ACTIVITY_3"/>
    </group>
    <packagedElement xmi:type="Activity" xmi:id="EAID_ACTIVITY_3" name="selectCourse"/>
</packagedElement>
...
<connectors>
    <connector xmi:idref="EAID_CONNECTOR1">
        <source xmi:idref="EAID_ACTIVITY_2"/>
        <target xmi:idref="EAID_ACTIVITY_3"/>
    </connector>
</connectors>
...

But in output i just want connectors with the correct source and target what is some element "group" with attribute id (EAID_LIFELINE_1 or EAID_LIFELINE_2). So xml output should looks like that:

<connectors>
    <connector xmi:idref="EAID_CONNECTOR1">
        <source xmi:idref="EAID_LIFELINE_1"/>
        <target xmi:idref="EAID_LIFELINE_2"/>
    </connector>
</connectors>

I tried to do it with using key function and this XSLT:

<xsl:key name="grp" match="group" use="node/@xmi:idref" />
<xsl:key name="subact" match="subgroup/ownedBehavior[@xmi:type='Activity']" use="@xmi:id" />
...
<connector xmi:idref="EAID_CONNECTOR{position()}">
     <source xmi:idref="{key('grp',../(key('subact',@source))/@xmi:id)/@xmi:id}"/> <!--This is place where I don´t know how to write that code to get to group...-->
     <target xmi:idref="{key('grp', @target)/@xmi:id}"/>
</connector>

Target is correct, it shows what I want (EAID_LIFELINE_2) but for source I do not know how to write that xpath to get lifeline. Could you help me anyone? Thanks.


Solution

  • You were just missing to go up one level from ownedBehavior to subgroup to get the right xmi:id. So change your connector code to

    <connector xmi:idref="EAID_CONNECTOR{position()}">
         <source xmi:idref="{key('grp',key('subact', @source)/../@xmi:id)/@xmi:id}"/> 
         <target xmi:idref="{key('grp', @target)/@xmi:id}"/>
    </connector>
    

    Output is:

    <connector xmlns:xmi="urn:abc" xmi:idref="EAID_CONNECTOR6">
        <source xmi:idref="EAID_LIFELINE_1"/>
        <target xmi:idref="EAID_LIFELINE_2"/>
    </connector>