Reputation: 989
How can you apply different templates to different sub nodes that have the same name?
I am given an xml that I cannot change.
To oversimplify with an example (the real xml is much more complicated than this), I want to apply different templates to Employees and Managers, but their subnodes are both "Employees". The xslt below will not work because there are 2 Employee templates.
FYI, I'm a newbie with xslts so I apologize if this turns out to be very easy to solve.
Thanks in advance! Any help will be appreciated.
XML
<Company>
<CompanyId>1</CompanyId>
<CompanyName>Company B</CompanyName>
<Employees>
<Employee>
<EmployeeId>1</EmployeeId>
<FirstName>Jane</FirstName>
<LastName>Doe</LastName>
</Employee>
<Employee>
<EmployeeId>2</EmployeeId>
<FirstName>James</FirstName>
<LastName>Smith</LastName>
</Employee>
</Employees>
<Managers>
<Employee>
<EmployeeId>3</EmployeeId>
<FirstName>Michael</FirstName>
<LastName>Johnson</LastName>
<DepartmentName>Sales</DepartmentName>
<NumberOfStaff>20</NumberOfStaff>
</Employee>
<Employee>
<EmployeeId>2</EmployeeId>
<FirstName>James</FirstName>
<LastName>Smith</LastName>
<DepartmentName>IT</DepartmentName>
<NumberOfStaff>50</NumberOfStaff>
</Employee>
</Managers>
</Company>
XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ms="urn:schemas-microsoft-com:xslt"
xmlns:dt="urn:schemas-microsoft-com:datatypes">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="/Company"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Company">
COMPANY INFO<br />
Company Id: <xsl:value-of select="CompanyId" /><br />
Company Name: <xsl:value-of select="CompanyName" /><br />
<br />
EMPLOYEES<br />
<xsl:apply-templates select="/Company/Employees/Employee"/>
<br />
MANAGERS<br />
<xsl:apply-templates select="/Company/Managers/Employee"/>
<br />
</xsl:template>
<xsl:template match="Employee">
<br />
Employee Id: <xsl:value-of select="EmployeeId" /><br />
Employee Name: <xsl:value-of select="LastName" />,<xsl:value-of select="FirstName" /><br />
</xsl:template>
<xsl:template match="Employee">
<br />
Manager Id: <xsl:value-of select="EmployeeId" /><br />
Manager Name: <xsl:value-of select="LastName" />,<xsl:value-of select="FirstName" /><br />
Department Name: <xsl:value-of select="DepartmentName" /><br />
Number of Staff: <xsl:value-of select="NumberOfStaff" /><br />
</xsl:template>
</xsl:stylesheet>
DESIRED OUTPUT
COMPANY INFO
Company Id: 1
Company Name: Company B
EMPLOYEES
Employee Id: 1
Employee Name: Doe,Jane
Employee Id: 2
Employee Name: Smith,James
MANAGERS
Manager Id: 3
Manager Name: Johnson,Michael
Department Name: Sales
Number of Staff: 20
Manager Id: 2
Manager Name: Smith,James
Department Name: IT
Number of Staff: 50
Upvotes: 1
Views: 1609
Reputation: 70598
You can specify the parent in the match attribute on the template
For Managers...
<xsl:template match="Managers/Employee">
For Employees...
<xsl:template match="Employees/Employee">
Note that, although not necessarily in this instance, another option would be to make us of "modes"
<xsl:apply-templates select="/Company/Employees/Employee" mode="Employees" />
<xsl:apply-templates select="/Company/Managers/Employee" mode="Managers" />
Then you could write your template matches like this:
<xsl:template match="Employee" mode="Employees">
<xsl:template match="Employee" mode="Managers">
Upvotes: 6