Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Kyle 24 posts 63 karma points
    Oct 07, 2013 @ 20:05
    Kyle
    0

    Counting property values and totalling

    Hi,

    I'm creating a football league website and need to produce a results table.

    I've got 75% of the table done so far but...

    Issue 1:
    I'm struggling to come up with a method to total multiple property values for the total goals scored by a club / scored against that club and the difference between the 2.

    Issue 2:
    I need to then sort the table by the points Descending , then Goal difference.

    My structure is like so:

    • Clubs
      - Club 1
      - Club 2
      - Club 3
      - And so on...
    • Fixtures And Results
      - Game 1 (homeTeam / homeGoals / awayTeam / awayGoals)
      - Game 2
      - Game 3
      - And so on...

    Any help would be greatly appreciated as I've hit a brick wall. My XSLT so far is below. Also if there is anything suspect in my method below please let me know :)

    Thanks you Kyle.

    <!-- Clubs & Results -->
    <xsl:param name="Source" select="umbraco.library:GetXmlNodeById($currentPage/selectedNode)/Clubs" />
    <xsl:param name="Results" select="umbraco.library:GetXmlNodeById($currentPage/selectedNode)/FixturesAndResults" />
     
      <table>
      <tr>
        <td>Team</td>
        <td>Played</td>
        <td>HW</td>
        <td>HD</td>
        <td>HL</td>
        <td>AW</td>
        <td>AD</td>
        <td>AL</td>
        <td>W</td>
        <td>D</td>
        <td>L</td>
        <td>GF</td>
        <td>GA</td>
        <td>GD</td>
        <td>Pts</td>
      </tr>
       
      <xsl:for-each select="$Source/Club">   
       
      <xsl:variable name="parentId" select="@id"/>
      <!-- Games Played -->
      <xsl:variable name="played" select="count($Results/descendant::FixtureOrResult [@isDoc and ./publishResult = 1 and (./homeTeam = $parentId or ./awayTeam = $parentId)])"/>
      <!-- Home Games -->
      <xsl:variable name="homeGames" select="$Results/descendant::FixtureOrResult [@isDoc and ./publishResult = 1 and (./homeTeam = $parentId)]"/>
      <xsl:variable name="homeWins" select="count($homeGames [./homeTeamGoals &gt; ./awayTeamGoals])"/>
      <xsl:variable name="homeDraws" select="count($homeGames [./homeTeamGoals = ./awayTeamGoals])"/>
      <xsl:variable name="homeLose" select="count($homeGames [./homeTeamGoals &lt; ./awayTeamGoals])"/>
      <!-- Away Games -->
      <xsl:variable name="awayGames" select="$Results/descendant::FixtureOrResult [@isDoc and ./publishResult = 1 and (./awayTeam = $parentId)]"/>
      <xsl:variable name="awayWins" select="count($awayGames [./homeTeamGoals &lt; ./awayTeamGoals])"/>
      <xsl:variable name="awayDraws" select="count($awayGames [./homeTeamGoals = ./awayTeamGoals])"/>
      <xsl:variable name="awayLose" select="count($awayGames [./homeTeamGoals &gt; ./awayTeamGoals])"/>
      <!-- Totals -->
      <xsl:variable name="totalWins" select="$homeWins + $awayWins"/>
      <xsl:variable name="totalDraws" select="$homeDraws + $awayDraws"/>
      <xsl:variable name="totalLose" select="$homeLose + $awayLose"/>
      <!-- Goals -->
      <xsl:variable name="goalsFor" select="1"/>
      <!-- Points -->
      <xsl:variable name="points" select="($totalWins * 3) + ($totalDraws)"/>
     
        <tr>
          <td>
            <xsl:value-of select="@nodeName"/>
          </td>
          <td>
            <xsl:value-of select="$played"/>
          </td>
          <td>
            <xsl:value-of select="$homeWins"/>
          </td>
          <td>
            <xsl:value-of select="$homeDraws"/>
          </td>
          <td>
            <xsl:value-of select="$homeLose"/>
          </td>
          <td>
            <xsl:value-of select="$awayWins"/>
          </td>
          <td>
            <xsl:value-of select="$awayDraws"/>
          </td>
          <td>
            <xsl:value-of select="$awayLose"/>
          </td>
          <td>
            <xsl:value-of select="$totalWins"/>
          </td>
          <td>
            <xsl:value-of select="$totalDraws"/>
          </td>
          <td>
            <xsl:value-of select="$totalLose"/>
          </td>
          <td>
            Goals For
          </td>
          <td>
            Goals Against
          </td>
          <td>
            Goal Difference
          </td>
          <td>
            <xsl:value-of select="$points"/>
          </td>
        </tr>
      </xsl:for-each>
    </table>

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Oct 07, 2013 @ 20:52
    Chriztian Steinmeier
    100

    Hi Kyle - welcome to Our !

    To calculate all the goals you can use the sum() function, e.g. something like this (taking a qualified guess):

    <!-- Goals -->
    <xsl:variable name="goalsFor" select="sum($homeGames/homeTeamGoals | $awayGames/homeTeamGoals)"/>
    <xsl:variable name="goalsAgainst" select="sum($homeGames/awayTeamGoals | $awayTeamGoals/awayTeamGoals)"/>
    <xsl:variable name="goalsDiff" select="$goalsFor - $goalsAgainst"/>
    

    (The pipe - | - joins two or more nodesets)

    You can perform a couple of "optimizations" that makes the code read a little better:

    • ./ is not necessary, so you can remove all those (e.g.: count($homeGames [./homeTeamGoals &lt; ./awayTeamGoals]) => count($homeGames[homeTeamGoals &lt; awayTeamGoals]))

    • /descendant:: can be shortened to // (e.g.: $Results/descendant::FixtureOrResult => $Results//FixtureOrResult

    Hope that helps (and that the home team wins!)

    /Chriztian

  • Kyle 24 posts 63 karma points
    Oct 08, 2013 @ 00:41
    Kyle
    0

    Thanks Chriztian,

    That was spot on and I've done my house keeping, a couple of nice tips thanks.

    Must say I'm really liking the flexibility of Umbraco especially for a front end guy like me.

    Still stuck with the my second issue now I have all the values in the table I need to sort the data and put the club with the most points at the top and descending down.

    I've spent some time searching and can see that you can't use a variable i.e $points, <xsl:sort select="$points" order="descending"/>, do you have any clue how this could be done or a similar post that could help?

    Kind Regards,

    Kyle

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Oct 08, 2013 @ 09:29
    Chriztian Steinmeier
    0

    Hi Kyle,

    So you could extract all the variables back into a giant sort selection that didn't use variables, but it would be hard to read and understand before you'd have finished the rest of the site - so here's a better/nicer approach:

    When dealing with large sets of data like that, it can be much more efficient to simply pre-calculate the results and create an XML variable with those, and use that instead for rendering the table - e.g., having something like this (for every team):

    <result club="1337" name="Liverpool Rangers">
        <played>13</played>
    
        <homeWins>3</homeWins>
        <homeDraws>2</homeDraws>
        <homeLose>1</homeLose>
    
        <awayWins>7</awayWins>
        <awayDraws>0</awayDraws>
        <awayLose>0</awayLose>
    
        <totalWins>10</totalWins>
        <totalDraws>2</totalDraws>
        <totalLose>1</totalLose>
    
        <goalsFor>12</goalsFor>
        <goalsAgainst>3</goalsAgainst>
        <goalsDiff>9</goalsDiff>
    
        <points>32</points>
    </result>
    

    As you can see, it should then be easy as pie to sort on any of all those bits (though you'd probably be better off using some sort of "sortable table" JS plugin for that).

    Here's a crude version of how you'd do something like the above:

    <xsl:stylesheet
        version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:umbraco.library="urn:umbraco.library"
        exclude-result-prefixes="umbraco.library"
    >
    
        <xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
    
        <xsl:param name="currentPage" />
    
        <!-- Index the published resultnodes by team for speedy lookup -->
        <xsl:key name="homeGamesForTeam" match="FixtureOrResult[publishResult = 1]" use="homeTeam" />
        <xsl:key name="awayGamesForTeam" match="FixtureOrResult[publishResult = 1]" use="awayTeam" />
    
        <xsl:variable name="$Source" select="umbraco.library:GetXmlNodeById($currentPage/selectedNode)/Clubs" />
    
        <xsl:template match="/">
            <!-- Process the Clubs node in the selected section -->
            <xsl:apply-templates select="$Source" />
        </xsl:template>
    
        <!-- Template for the Clubs node -->
        <xsl:template match="Clubs">
            <xsl:variable name="resultsProxy">
                <!-- Run through all the teams -->
                <xsl:for-each select="Club">
                    <!-- Scope these to the current team to reduce number of nodes searched -->
                    <xsl:variable name="homeGames" select="key('homeGamesForTeam', @id)" />
                    <xsl:variable name="awayGames" select="key('awayGamesForTeam', @id)" />
    
                    <!-- Collect all the results -->
                    <xsl:variable name="homeWins"  select="count($homeGames[homeTeamGoals &gt; awayTeamGoals])"/>
                    <xsl:variable name="homeDraws" select="count($homeGames[homeTeamGoals = awayTeamGoals])"/>
                    <xsl:variable name="homeLose"  select="count($homeGames[homeTeamGoals &lt; awayTeamGoals])"/>
                    <!-- Away Games -->
                    <xsl:variable name="awayWins"  select="count($awayGames [homeTeamGoals &lt; awayTeamGoals])"/>
                    <xsl:variable name="awayDraws" select="count($awayGames [homeTeamGoals = awayTeamGoals])"/>
                    <xsl:variable name="awayLose"  select="count($awayGames [homeTeamGoals &gt; awayTeamGoals])"/>
                    <!-- Totals -->
                    <xsl:variable name="totalWins"  select="$homeWins + $awayWins"/>
                    <xsl:variable name="totalDraws" select="$homeDraws + $awayDraws"/>
                    <xsl:variable name="totalLose"  select="$homeLose + $awayLose"/>
                    <!-- Goals -->
                    <xsl:variable name="goalsFor"     select="sum($homeGames/homeTeamGoals | $awayGames/homeTeamGoals)"/>
                    <xsl:variable name="goalsAgainst" select="sum($homeGames/awayTeamGoals | $awayTeamGoals/awayTeamGoals)"/>
                    <xsl:variable name="goalsDiff"    select="$goalsFor - $goalsAgainst"/>
                    <!-- Points -->
                    <xsl:variable name="points" select="($totalWins * 3) + ($totalDraws)"/>
    
                    <!-- Wrap everything in a precalculated <result> for this team -->
                    <result club="{@id}" name="{@nodeName}">
                        <played><xsl:value-of select="count($homeGames | $awayGames)"/></played>
    
                        <homeWins><xsl:value-of  select="$homeWins" /></homeWins>
                        <homeDraws><xsl:value-of select="$homeDraws" /></homeDraws>
                        <homeLose><xsl:value-of  select="$homeLose" /></homeLose>
    
                        <awayWins><xsl:value-of  select="$awayWins" /></awayWins>
                        <awayDraws><xsl:value-of select="$awayDraws" /></awayDraws>
                        <awayLose><xsl:value-of  select="$awayLose" /></awayLose>
    
                        <totalWins><xsl:value-of select="$homeWins + $awayWins" /></totalWins>
                        <totalDraws><xsl:value-of select="$homeDraws + $awayDraws" /></totalDraws>
                        <totalLose><xsl:value-of select="$homeLose + $awayLose" /></totalLose>
    
                        <goalsFor><xsl:value-of select="$goalsFor" /></goalsFor>
                        <goalsAgainst><xsl:value-of select="$goalsAgainst" /></goalsAgainst>
                        <goalsDiff><xsl:value-of select="$goalsDiff" /></goalsDiff>
    
                        <points><xsl:value-of select="$points" /></points>
                    </result>
                </xsl:for-each>
            </xsl:variable>
            <!-- (This is needed to get an "XPath-navigable" variable) -->
            <xsl:variable name="results" select="make:node-set($resultsProxy)/result" />
    
            <!-- Output table of results -->
            <table>
                <tr>
                    <th>Team</th>
                    <th>Played</th>
                    <th>HW</th>
                    <th>HD</th>
                    <th>HL</th>
                    <th>AW</th>
                    <th>AD</th>
                    <th>AL</th>
                    <th>W</th>
                    <th>D</th>
                    <th>L</th>
                    <th>GF</th>
                    <th>GA</th>
                    <th>GD</th>
                    <th>Pts</th>
                </tr>
    
                <!-- Run through the results, sorted backwards by points scored -->
                <xsl:apply-templates select="$results">
                    <xsl:sort select="points" data-type="number" order="descending" />
                </xsl:apply-templates>
            </table>
        </xsl:template>
    
        <!-- Template for a single <result> -->
        <xsl:template match="result">
            <!-- Just pick the pre-calculated results one by one -->
            <tr>
                <td><xsl:value-of select="@name" /></td>
                <td><xsl:value-of select="played" /></td>
                <td><xsl:value-of select="homeWins" /></td>
                <td><xsl:value-of select="homeDraws" /></td>
                <td><xsl:value-of select="homeLose" /></td>
                <!-- etc. -->
            </tr>
        </xsl:template>
    
    </xsl:stylesheet>
    

    /Chriztian

  • Kyle 24 posts 63 karma points
    Oct 09, 2013 @ 09:05
    Kyle
    0

    Hi Chriztian,

    Thanks again, a minor tweak and it worked a treat. Another really handy method.

    I changed the "make:"

    <xsl:variable name="results" select="make:node-set($resultsProxy)/result" />
    

    To

    <xsl:variable name="results" select="msxml:node-set($resultsProxy)/result" />
    

    Kind Regards,

    Kyle

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Oct 09, 2013 @ 09:12
    Chriztian Steinmeier
    0

    Hi Kyle,

    Ha :) Good catch - I do forget to change that, from time to time :-)

    /Chriztian

Please Sign in or register to post replies

Write your reply to:

Draft