代码之家  ›  专栏  ›  技术社区  ›  orosco03

在格式化节点内排序

  •  1
  • orosco03  · 技术社区  · 7 年前

    我需要显示XML,并对一天的总距离进行排序,以便首先显示公里数最多的一天 我只能算出距离的总和

    输入

    <output>
        <cars>
            <car>
              <id>1</id>
              <license>B-01-TST</license>
            </car>
            <car>
              <id>2</id>
              <license>IF-02-TST</license>
            </car>
        </cars>
        <distances>
            <distance>
              <id_car>1</id_car>
              <date>20110901</date>
              <distance>111</distance>
            </distance>     
            <distance>
              <id_car>1</id_car>
              <date>20110903</date>
              <distance>56</distance>
            </distance>
            <distance>
              <id_car>2</id_car>
              <date>20110901</date>
              <distance>92</distance>
            </distance>
            <distance>
              <id_car>2</id_car>
              <date>20110902</date>
              <distance>97</distance>
            </distance>
        </distances>
    </output>
    

    预期输出

    <output>
    <cars>
        <car>
            <id>1</id>
            <license>B-01-TST</license>
            <distance totalKm="Day 01: 111"/>
            <distance totalKm="Day 03: 56"/>
        </car>
        <car>
            <id>2</id>
            <license>IF-02-TST</license>
            <distance totalKm="Day 01: 92"/>
            <distance totalKm="Day 02: 97"/>
        </car>
    </cars>
    

    我无法复制所有XSL,因为对于这个问题来说,它的代码太多了, 主要信息是

    到目前为止,XSL如下所示:

    <xsl:key name="byCarIdAndDate" match="distance" use="concat(id_car, '|', date)"/>
    <xsl:key name="byCarId" match="distance" use="id_car"/>
    <xsl:template match="car">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
                <xsl:apply-templates select="key('byCarId', id)"/>
            </xsl:copy>
        </xsl:template>
    <xsl:template match="distance[generate-id()= generate-id(key('byCarIdAndDate', concat(id_car, '|', date))[1])]">
        <xsl:variable name="thisDate" select="key('byCarIdAndDate', concat(id_car, '|', date))"/>
        <xsl:variable name="sum" select="sum($thisDate/distance)"/>
        <!--make some sort by higher value -->
        <distance totalKm="Day {substring(date, 7, 2)}: {$sum}"/>
    </xsl:template>
    

    模板匹配=“距离|距离”

    1 回复  |  直到 7 年前
        1
  •  1
  •   Martin Honnen    7 年前

    我认为最好求助于 xsl:for-each-group 然后按日期分组,以便我们轻松地对组进行求和:

    <?xml version="1.0" encoding="UTF-8" ?>
    <xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    
        <xsl:output indent="yes"/>
        <xsl:strip-space elements="*"/>
    
        <xsl:key name="byCarId" match="distances/distance" use="id_car"/>
    
        <xsl:template match="@*|node()">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:template>
    
        <xsl:template match="distances"/>
    
        <xsl:template match="car">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
                <xsl:for-each-group select="key('byCarId', id)" group-by="date">
                    <xsl:sort select="sum(current-group()/distance)" order="descending"/>
                    <xsl:apply-templates select="."/>
                </xsl:for-each-group>
            </xsl:copy>
        </xsl:template>
    
        <xsl:template match="distance">
            <distance totalKm="Day {substring(date, 7, 2)}: {sum(current-group()/distance)}"/>
        </xsl:template>
    
    </xsl:transform>
    

    http://xsltransform.net/3MvmrAX