grouping output with xml and xslt

2019-08-09 19:39发布

问题:

I have an XML file with multiple team elements. Each team element has multiple player child elements.

The basic structure is as follows

<league>
      <team>
          <!-- Team details go here -->
             <player>
                      <!-- Player details go here -->
             </player>
      </team>
</league>

The output I need is for the team details to be displayed, followed by the players in a table. Players should be sorted by surname, teams by their name.

What I'm getting instead is all of the team's details one after another, followed by all players details in a single table.

I have simplified the following xml to only a few details to make it easier to read.

This is my xml

<league xmlns:xlink="http://www.w3.org/1999/xlink">

    <team>

        <teamName>Southampton</teamName>
        <manager>Ronald Koeman</manager>
        <stadium>St. Mary's</stadium>

        <players>

            <firstName>Victor</firstName>
            <surname>Wanyama</surname>
            <squadNumber>12</squadNumber>

        </players>

        <players>

            <firstName>Shane</firstName>
            <surname>Long</surname>
            <squadNumber>7</squadNumber>
        </players>

    </team>

        <team>

        <teamName>Arsenal</teamName>
        <manager>Arsene Wenger</manager>
        <stadium>Emirates Stadium</stadium>

        <players>

            <firstName>Hector</firstName>
            <surname>Bellerin</surname>
            <squadNumber>24</squadNumber>

        </players>

        <players>

            <firstName>Santi</firstName>
            <surname>Cazorla</surname>
            <squadNumber>19</squadNumber>
        </players>

    </team>
</league>

And the xslt

<xsl:stylesheet version="2.0" 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
<html>

<head>
    <link rel="stylesheet" type="text/css" href="epl.css" />
</head>

<body>
    <xsl:for-each select="league/team">
    <xsl:sort select="teamName"/>

    <b>Name</b>
    <p><xsl:value-of select="teamName" /></p>

    <b>Manager</b>
    <p><xsl:value-of select="manager" /></p>

    <b>Stadium</b>
    <p><xsl:value-of select="Stadium" /></p>
    </xsl:for-each>

    <tr>
        <th>First Name</th>
        <th>Surname</th>
        <th>Squad Number</th>
    </tr>

    <xsl:for-each select="league/team/players">
    <xsl:sort select="surname"/>
    <tr>
    <td><xsl:value-of select="firstName"/></td>
    <td><xsl:value-of select="surname"/></td>
    <td><xsl:value-of select="squadNumber"/></td>
    </tr>
    </xsl:for-each>

</body>

</html>
</xsl:template>
</xsl:stylesheet>

I don't have enough rep to show images of what I'm getting but simply put I want the data grouped by the teams, with the player data relevant to each team in a table below that.

What I've tried.

I've tried using for-each-group in various ways. All resulting in a generic " Error loading stylesheet: Parsing an XSLT stylesheet failed." in firefox.

<xsl:for-each-group select="league" group-by="@team"> <team name="{current-grouping-key()}"> </xsl:for-each-group

This includes placing for-each-group in the beginning of the body, in it's own xsl:template, in the main xsl:template.

I've tried alternate xpath expressions for the "select" part. Like league/team, league, league/

I've tried nesting the xsl that gets the player and team data together into another for-each

I have XML Tools plugin for notepad++ installed and when trying to save the file I get: XML parsing erro at line 51: Premature end of data tag in stylesheet line 3

Line 51 only has the closing </xsl:stylesheet>

Once I remove the for-each-group it saves normally but output sequence is incorrect and as I mentioned before. All team data is shown, followed by all player data without associating players with teams in their own tables.

回答1:

I don't think you need to do grouping in your XSLT, as your player data is already grouped by team in your XML. All you need to do is move the xsl:for-each that current selects players so that is nested in the one that current selects the teams, and adjust the select statement so that the xpath expression is relative to the current team element.

Try this XSLT

<xsl:stylesheet version="1.0" 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="html" doctype-public="XSLT-compat" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />

<xsl:template match="/">
    <html>
    <head>
        <link rel="stylesheet" type="text/css" href="epl.css" />
    </head>
    <body>
        <xsl:for-each select="league/team">
        <xsl:sort select="teamName"/>
            <b>Name</b>
            <p><xsl:value-of select="teamName" /></p>
            <b>Manager</b>
            <p><xsl:value-of select="manager" /></p>
            <b>Stadium</b>
            <p><xsl:value-of select="stadium" /></p>
            <table>
            <tr>
                <th>First Name</th>
                <th>Surname</th>
                <th>Squad Number</th>
            </tr>
            <xsl:for-each select="players">
            <xsl:sort select="surname"/>
                <tr>
                <td><xsl:value-of select="firstName"/></td>
                <td><xsl:value-of select="surname"/></td>
                <td><xsl:value-of select="squadNumber"/></td>
                </tr>
            </xsl:for-each>
            </table>
            <br />
        </xsl:for-each>
    </body>
    </html>
</xsl:template>
</xsl:stylesheet>