按XSLT

时间:2015-12-04 21:43:33

标签: xml sorting xslt

我一直在研究使用<xsl:sort>和变量对XML进行排序的线程,但仍无法让我的排序工作。这是上下文的一些XML结构:

<?xml version="1.0" encoding="UTF-8"?>
<tournament>
    <match date="2015-12-18">
        <team name="FIRST" score="1" />
        <team name="SECOND" score="0" />
    </match>
    <match date="2015-12-20">
        <team name="FIRST" score="1" />
        <team name="THIRD" score="3" />
    </match>

    <match date="2015-12-23">
        <team name="THIRD" score="5" />
        <team name="SECOND" score="1" />
    </match>
</tournament>

我希望显示球队和总分的列表(一场比赛赢得了两分,一场比赛输了零点,两队平等一分)我使用这段代码:

<xsl:variable name="matches" select="//match"/>
<table border="1" width="100%">
    <tr>
       <th>TEAMS</th>
       <th>POINTS</th>
    </tr>

    <xsl:for-each select="distinct-values(tournament/match/team/@name)">
       <xsl:variable name="this" select="."/>

       <xsl:variable name="points" select="sum($matches/team[@name=$this and (@score&gt;following-sibling::*/@score
       or @score&gt;preceding-sibling::*/@score)]/2) + sum($matches/team[@name=$this
       and (@score=following-sibling::*/@score or @score=preceding-sibling::*/@score)]/1) "/>

        <tr>
            <td><xsl:value-of select="."/></td>
            <td><xsl:value-of select="$points"/></td>
        </tr>

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

这有助于我展示:

   |   TEAMS     |    POINTS  |
   |--------------------------|
   |   FIRST     |      2     |
   |   SECOND    |      1     |
   |   THIRD     |      3     |

现在,我想通过点对此结果进行排序以显示:

   |   TEAMS     |    POINTS  |
   |--------------------------|
   |   THIRD     |      3     |
   |   FIRST     |      2     |
   |   SECOND    |      1     |

那么,我如何通过变量<xsl:for-each>

$points进行排序

1 个答案:

答案 0 :(得分:2)

您无法按变量排序。为了避免两次计算得分,我会在两次通过中做到这一点:

XSLT 2.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" version="1.0" encoding="utf-8" indent="yes"/>

<xsl:key name="wins" match="team[@score > ancestor::match/team/@score]" use="@name"/>
<xsl:key name="draws" match="team[not(@score!=ancestor::match/team/@score)]" use="@name"/>

<xsl:template match="/tournament">
    <!-- first pass -->
    <xsl:variable name="teams">
        <xsl:for-each-group select="match/team" group-by="@name">
            <team name="{@name}" points="{2 * count(key('wins', @name)) + count(key('draws', @name))}"/>
        </xsl:for-each-group>
    </xsl:variable>
    <!-- output -->
    <table border="1" width="100%">
        <tr>
           <th>TEAMS</th>
           <th>POINTS</th>
        </tr>
        <xsl:for-each select="$teams/team">
            <xsl:sort select="@points" data-type="number" order="descending"/>
            <tr>
                <td><xsl:value-of select="@name"/></td>
                <td><xsl:value-of select="@points"/></td>
            </tr>
        </xsl:for-each> 
    </table>    
</xsl:template>

</xsl:stylesheet>