mctuna
mctuna

Reputation: 871

XSL Fetch All Items From Child Nodes and Get the First 2 Data with the Nearest Date

What I am trying to achieve is to fetch all matches (participant) from nodes and sort them according to the date and get the 2 oldest matches. What I have achieved so far fetching 2 matches from each fixtures nodes separately.

<spocosy version="1.0">
<fixtures id="820745" ut="2011-03-01" sport="Football" template="England Premier League" tournament="2010/2011" league="Premier League">
<fixture id="839993" name="Chelsea-Manchester United" date="2011-03-01 20:45:00" round="18" status="Not started">
<participants>
<participant participantid="8455" participantname="Chelsea"/>
<participant participantid="10260" participantname="Manchester United"/>
</participants>
</fixture>
<fixture id="840142" name="Birmingham-West Bromwich" date="2011-03-05 13:45:00" round="29" status="Not started">
<participants>
<participant participantid="8658" participantname="Birmingham"/>
<participant participantid="8659" participantname="West Bromwich"/>
</participants>
</fixture>
<fixture id="840143" name="Bolton-Aston Villa" date="2011-03-05 16:00:00" round="29" status="Not started">
<participants>
<participant participantid="8559" participantname="Bolton"/>
<participant participantid="10252" participantname="Aston Villa"/>
</participants>
</fixture>
</fixtures>

<fixtures id="821290" ut="2011-03-01" sport="Football" template="Spain LIGA BBVA" tournament="2010/2011" league="LIGA BBVA">
<fixture id="875757" name="Espanyol-Mallorca" date="2011-03-01 20:00:00" round="26" status="Not started">
<participants>
<participant participantid="8558" participantname="Espanyol"/>
<participant participantid="8661" participantname="Mallorca"/>
</participants>
</fixture>
<fixture id="875739" name="Sevilla-Gijon" date="2011-03-01 22:00:00" round="26" status="Not started">
<participants>
<participant participantid="8302" participantname="Sevilla"/>
<participant participantid="9869" participantname="Gijon"/>
</participants>
</fixture>
<fixture id="875737" name="Zaragoza-Athletic Bilbao" date="2011-03-02 20:00:00" round="26" status="Not started">
<participants>
<participant participantid="8394" participantname="Zaragoza"/>
<participant participantid="8315" participantname="Athletic Bilbao"/>
</participants>
</fixture>
<fixture id="875743" name="Getafe-Atletico Madrid" date="2011-03-02 20:00:00" round="26" status="Not started">
<participants>
<participant participantid="8305" participantname="Getafe"/>
<participant participantid="9906" participantname="Atletico Madrid"/>
</participants>
</fixture>
<fixture id="875746" name="Villarreal-Hercules" date="2011-03-02 20:00:00" round="26" status="Not started">
<participants>
<participant participantid="10205" participantname="Villarreal"/>
<participant participantid="10278" participantname="Hercules"/>
</participants>
</fixture>
</fixtures>

there are 5 fixtures
<xsl:template match="fixtures">

 <xsl:for-each select="//fixture">
    <xsl:sort select="@date" data-type="text" order="ascending"/>
    <xsl:if test="position() &lt; 3">

       <xsl:variable name="eventid" select="@id"/>
    <table class="default soccer">
        <tbody>
            <tr class="finished livestats event_row">
                <td class="status tz_field" data-format="short_datetime"><xsl:value-of select="@date"></xsl:value-of></td>
                <td class="team_1">
                    <div class="of_wrapper">
                    <span />
                    <xsl:value-of select="//participant[position()=1]/@participantname"></xsl:value-of>
                    </div>
                </td>
                <td id="res_{$eventid}" class="result bold link popup">
                     - 
                </td>
                <td class="team_2">
                    <div class="of_wrapper">
                    <span />
                    <xsl:value-of select="//participant[position()=2]/@participantname"></xsl:value-of>                 
                    </div>
                </td>               
            </tr>
        </tbody>
        </table>


    </xsl:if>
  </xsl:for-each>

And here is the output of it

enter image description here

In that output, dates are the oldest 2 which is what I want to achieve but they are displayed for each fixtures again and again (there are 5 fixtures and the dates are displayed totally 10 times instead of 2) and the teams are not related to the dates, teams are displayed from the first participants node.

I don't necessarily want exact code, any approaches would be also appreciated. So briefly I want to fetch all matches then sort them according to the date and display the oldest 2 machtes with the exact dates.

Upvotes: 1

Views: 381

Answers (2)

Ian Roberts
Ian Roberts

Reputation: 122394

Your problem is the absolute paths. You have the

<xsl:for-each select="//fixture">

inside a template matching fixtures, so for each fixtures element you are pulling out the first two fixture elements from the whole document (not just from inside that particular fixtures) and creating a table row for each one. Then for each row you're taking the team names from the very first participants element in the document (//participant[position()=1]/@participantname gives you the names of all the participant elements in the whole document that are the first child with that name within their respective parent element, and value-of gives the value of the first of these in document order).

You need to move the logic up from the <xsl:template match="fixtures"> into somewhere where their common parent element is the context node and use a single for-each over all the fixture elements in one go rather than one for-each per fixtures:

 <xsl:for-each select="fixtures/fixture">
    <xsl:sort select="@date" data-type="text" order="ascending"/>
    <xsl:if test="position() &lt; 3">

and use relative paths participants/participant[1] and participants/participant[2] for team 1 and 2 respectively.

Upvotes: 1

Martin Honnen
Martin Honnen

Reputation: 167696

<xsl:template match="root">
  <xsl:for-each select="//data">
    <xsl:sort select="@date" data-type="text" order="descending"/>
    <xsl:if test="position() &lt; 3">
      <xsl:copy-of select="."/>
    </xsl:if>
  </xsl:for-each>
</xsl:template>

returns the two data elelements with the most recent date attributes.

Upvotes: 1

Related Questions