Reputation: 61
I have an xml file similar to the one below and I want to group the correct teams and players together using XSLT 1.0. But instead of displaying the correct players under their relevant teams, it displays all players under all teams.
I know it has different node sets inside the root element which is possibly the reason the grouping is not working, I'm not even sure if this is possible, the examples of muenchian grouping all seem to have a single node set inside the root element.
The XML
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="football.xslt"?>
<football>
<!-- team details go here -->
<teams>
<team teamCode="#ASNL">
<teamName>Arsenal</teamName>
<stadium>Emirates Stadium</stadium>
<location>North London</location>
</team>
<team teamCode="#NUTD">
<teamName>Newcastle United</teamName>
<stadium>St James' Park</stadium>
<location>Newcastle Upon Tyne</location>
</team>
</teams>
<!-- end of teams -->
<!-- player details go here -->
<players>
<player teamID="#ASNL">
<playerFirstName>Hector</playerFirstName>
<playerSurname>Bellerin</playerSurname>
<position>RB</position>
<goals>3</goals>
<assists>5</assists>
</player>
<player teamID="#ASNL">
<playerFirstName>Mesut</playerFirstName>
<playerSurname>Ozil</playerSurname>
<position>CAM</position>
<goals>10</goals>
<assists>20</assists>
</player>
<player teamID="#NUTD">
<playerFirstName>Papiss</playerFirstName>
<playerSurname>Cisse</playerSurname>
<position>CF</position>
<goals>15</goals>
<assists>5</assists>
</player>
<player teamID="#NUTD">
<playerFirstName>Tim</playerFirstName>
<playerSurname>Krul</playerSurname>
<position>GK</position>
<goals>0</goals>
<assists>3</assists>
</player>
</players>
<!-- end of players -->
</football>
The XSLT
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:key name="teamKey" match="team" use="@teamCode"/>
<xsl:template match="/">
<xsl:for-each select="/football/teams/team[generate-id(.)=generate-id(key('teamKey', @teamCode)[1])]">
<xsl:sort select="teamName"/>
<teamDetails>
<br />
<b>Team Name: </b>
<xsl:value-of select="teamName"/>
<br />
<b>Stadium: </b>
<xsl:value-of select="stadium"/>
<br />
<b>Location: </b>
<xsl:value-of select="location"/>
<br />
</teamDetails>
<table>
<br />
<tr>
<th>First Name</th>
<th>Surname</th>
<th>Position</th>
<th>Goals</th>
<th>Assists</th>
</tr>
<xsl:for-each select="/football/players/player[key('teamKey', @teamID)]">
<tr>
<td>
<xsl:value-of select="playerFirstName"/>
</td>
<td>
<xsl:value-of select="playerSurname"/>
</td>
<td>
<xsl:value-of select="position"/>
</td>
<td>
<xsl:value-of select="goals"/>
</td>
<td>
<xsl:value-of select="assists"/>
</td>
</tr>
</xsl:for-each>
</table>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Upvotes: 0
Views: 115
Reputation: 116959
I'd suggest you do it this way:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="UTF-8"/>
<xsl:key name="player-by-team" match="player" use="@teamID"/>
<xsl:template match="/football">
<xsl:for-each select="teams/team">
<xsl:sort select="teamName"/>
<b>Team Name: </b>
<xsl:value-of select="teamName"/>
<br />
<b>Stadium: </b>
<xsl:value-of select="stadium"/>
<br />
<b>Location: </b>
<xsl:value-of select="location"/>
<br />
<table>
<tr>
<th>First Name</th>
<th>Surname</th>
<th>Position</th>
<th>Goals</th>
<th>Assists</th>
</tr>
<xsl:for-each select="key('player-by-team', @teamCode)">
<tr>
<td>
<xsl:value-of select="playerFirstName"/>
</td>
<td>
<xsl:value-of select="playerSurname"/>
</td>
<td>
<xsl:value-of select="position"/>
</td>
<td>
<xsl:value-of select="goals"/>
</td>
<td>
<xsl:value-of select="assists"/>
</td>
</tr>
</xsl:for-each>
</table>
<br />
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1
Reputation: 9627
No need for any muenchian grouping her:
Change the first loop for the teams to (and have a variable for the current team):
<xsl:for-each select="/football/teams/team">
<xsl:sort select="teamName"/>
<xsl:variable name="thisTeam" select="." />
And than the second loop for players within the team to:
<xsl:for-each
select="/football/players/player[ @teamID = $thisTeam/@teamCode ]">
Upvotes: 1