Reputation: 1131
I need to copy a node according to an attribute in another node in the same element. An example input XML is as follows:
<?xml version="1.0"?>
<Company>
<Department id="Marketing">
<depName>Marketing</depName>
<position>Marketer</position>
</Department>
<Employee id="e1" level="l1">
<First>John</First>
<Dep code="Marketing"></Dep>
</Employee>
<Employee id="e2" level="l1">
<First>Jane</First>
<Dep code="Marketing"></Dep>
</Employee>
<Boss id="e3" level="l2">
<First>Ben</First>
<Dep code="Marketing"></Dep>
</Boss>
</Company>
The output XML should look as follows:
<?xml version="1.0"?>
<Company>
<Department id="Marketing">
<depName>Marketing</depName>
<position>Marketer</position>
</Department>
<Employee id="e1" level="l1">
<First>John</First>
<Dep code="Marketing"></Dep>
<position>Marketer</position>
</Employee>
<Employee id="e2" level="l1">
<First>Jane</First>
<Dep code="Marketing"></Dep>
<position>Marketer</position>
</Employee>
<Boss id="e3" level="l2">
<First>Ben</First>
<Dep code="Marketing"></Dep>
</Boss>
</Company>
Of course there can be many more employees and departments.
I need to copy the position element from the Department to each of the Employees that work in the Department (e.g. for Marketing have <Dep code="Marketing">
), but not to the Bosses. The department can be checked using its id
attribute or depName
element, they should be identical.
I'm new to an XSLT so just have a basic idea how to select the element but don't really know how to go on from here (copy it to the correct place):
<xsl:template match="Department">
<xsl:copy>
<xsl:copy-of select="position"/>
</xsl:copy>
</xsl:template>
Edit: Added attributes to employees, they need to be retained in the output
Upvotes: 0
Views: 464
Reputation: 167471
Declare a key
<xsl:key name="dep" match="Department" use="@id"/>
and then write the template for Employee
<xsl:template match="Employee">
<xsl:copy>
<xsl:copy-of select="@*, node(), key('dep', Dep/@code)/position"/>
</xsl:copy>
</xsl:template>
The comma operator ,
is availble with XSLT 2 or 3 processors, for an XSLT 1 processor use two separate
<xsl:copy-of select="@* | node()"/>
<xsl:copy-of select="key('dep', Dep/@code)/position"/>
Upvotes: 1