XSLT:基于来自其他节点的值的总和进行排序 [英] XSLT: Sorting based on sum of values from other nodes

查看:20
本文介绍了XSLT:基于来自其他节点的值的总和进行排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对编写 xslt 还是比较陌生,并且在尝试执行以下操作时遇到了困难.

我有一个 xml 文件,其中包含分为两个主要部分的马匹育种信息.1. Horses 节点有个别马匹的表现细节以及他们的父亲是谁的id.2. Sires节点是拥有育种特定统计数据的Sires列表.

我需要根据他们的小马驹(即在马节点中)赢得的赌注"总和来对公牛列表进行排序.

所以一个精简的 xml 文件看起来像这样:

<马><ID>1</ID><姓名>hrsA</姓名><SireID>101</SireID><节奏><本金>4800</本金></步速></马><马><ID>2</ID><姓名>hrsB</姓名><SireID>102</SireID><节奏><本金>3600</本金></步速></马><马><ID>3</ID><姓名>hrsC</姓名><SireID>102</SireID><节奏><本金>2800</本金></步速></马><马><ID>4</ID><姓名>hrsD</姓名><SireID>101</SireID><节奏><赌注>56</赌注></步速></马><马><ID>5</ID><姓名>hrsE</姓名><SireID>100</SireID><节奏><赌注>20000</赌注></步速></马><马><ID>6</ID><姓名>hrsF</姓名><SireID>101</SireID><小跑><赌注>20000</赌注></马><马><ID>7</ID><姓名>hrsG</姓名><SireID>101</SireID><小跑><赌注>559</赌注></马><马><ID>8</ID><姓名>hrsH</姓名><SireID>102</SireID><节奏><赌注>386</赌注></步速><小跑><本金>10000</本金></马></马匹><公会><陛下><ID>100</ID><姓名>srA</姓名><LiveFoalsALL>117</LiveFoalsALL></陛下><陛下><ID>101</ID><姓名>srB</姓名><LiveFoalsALL>774</LiveFoalsALL></陛下><陛下><ID>102</ID><名称>srC</名称><LiveFoalsALL>43</LiveFoalsALL></陛下></Sires>

因此将各种赌注相加,输出将具有以下顺序:

Sire 101 (srB) 赌注:$25415爵士 100 (srA) 赌注:20000 美元Sire 103 (srC) 赌注:$16768.

当我刚刚为其他网页汇总和订购单个马匹时,我可以使用:

<xsl:sort select="sum(descendant::Stakes)" data-type="number"order="降序"/></xsl:apply-templates>

我只是不知道如何对引用马节点的公牛做同样的事情来求和以获得正确的排序......可能是这样的,我试图说公牛/ID等于马/SireID:

<xsl:sort select="sum(//Horses/Horse[@SireID=ID]/descendant::Stakes)"数据类型=数字"顺序=降序"/></xsl:apply-templates>

但这不起作用,调试器在遇到排序行时直接跳出当前模板,因此我的语法一定无效.我一直在尝试改变这个主题,但没有成功.

谁能告诉我如何调用我的 Sire 模板并获得正确的排序?

谢谢,

布莱斯·斯坦伯格

解决方案

这种转变:

<xsl:output omit-xml-declaration="yes" indent="yes"/><xsl:key name="kOffspring" match="Horse" use="SireID"/><xsl:template match="/*"><xsl:apply-templates select="Sires/Sire"><xsl:sort select="sum(key('kOffspring', ID)/*/Stakes)"数据类型=数字"顺序=降序"/></xsl:apply-templates></xsl:模板><xsl:template match="Sire">陛下 <xsl:value-of select="concat(ID,' (', Name, ') Stakes: ')"/><xsl:value-of select="sum(key('kOffspring', ID)/*/Stakes)"/></xsl:模板><xsl:template match="text()"/></xsl:stylesheet>

应用于提供的 XML 文档时:

<马><马><ID>1</ID><姓名>hrsA</姓名><SireID>101</SireID><节奏><本金>4800</本金></步速></马><马><ID>2</ID><姓名>hrsB</姓名><SireID>102</SireID><节奏><本金>3600</本金></步速></马><马><ID>3</ID><姓名>hrsC</姓名><SireID>102</SireID><节奏><本金>2800</本金></步速></马><马><ID>4</ID><姓名>hrsD</姓名><SireID>101</SireID><节奏><赌注>56</赌注></步速></马><马><ID>5</ID><姓名>hrsE</姓名><SireID>100</SireID><节奏><赌注>20000</赌注></步速></马><马><ID>6</ID><姓名>hrsF</姓名><SireID>101</SireID><小跑><赌注>20000</赌注></马><马><ID>7</ID><姓名>hrsG</姓名><SireID>101</SireID><小跑><赌注>559</赌注></马><马><ID>8</ID><姓名>hrsH</姓名><SireID>102</SireID><节奏><赌注>386</赌注></步速><小跑><本金>10000</本金></马></马匹><公会><陛下><ID>100</ID><姓名>srA</姓名><LiveFoalsALL>117</LiveFoalsALL></陛下><陛下><ID>101</ID><姓名>srB</姓名><LiveFoalsALL>774</LiveFoalsALL></陛下><陛下><ID>102</ID><名称>srC</名称><LiveFoalsALL>43</LiveFoalsALL></陛下></Sires></t>

产生想要的、正确的结果:

 Sire 101 (srB) 赌注:25415Sir 100 (srA) 赌注:20000Sire 102 (srC) 赌注:16786

说明:

  1. 我们定义了一个键,该键将Horse 指定为其SireID 的函数.这对于选择给定 Sire 的所有后代非常有用,只需在调用标准 XSLT key() 函数——像这样:key('kOffspring', ID).

  2. 同样,给定 Sire 的所有后代的 Stakes 总和是: sum(key('kOffspring', ID)/*/赌注) .

  3. 我们将模板应用于 XML 文档中的所有 Sire 元素,并按其后代 Stakes 总和的递减值对这些元素进行排序.>

  4. 对于每个Sire,我们输出它的IDName和它的Stakes的总和后代.

I'm rather new to coding xslt and have got rather stuck trying to do the following.

I have an xml file that has breeding info for horses broken into two main sections. 1. Horses node has the performance details of individual horses as well as an id to who their sire was. 2. Sires node is list of the Sires also holding breeding specific statistics.

I need to sort the list of sires based on the sum of the 'stake' money won by their foals (i.e. in the horses node).

So a cut down xml file looks like this:

<Horses>
    <Horse>
        <ID>1</ID>
        <Name>hrsA</Name>
        <SireID>101</SireID>
        <Pace>
            <Stakes>4800</Stakes>
        </Pace>
    </Horse>
    <Horse>
        <ID>2</ID>
        <Name>hrsB</Name>
        <SireID>102</SireID>
        <Pace>
            <Stakes>3600</Stakes>
        </Pace>
    </Horse>
    <Horse>
        <ID>3</ID>
        <Name>hrsC</Name>
        <SireID>102</SireID>
        <Pace>
            <Stakes>2800</Stakes>
        </Pace>
    </Horse>
    <Horse>
        <ID>4</ID>
        <Name>hrsD</Name>
        <SireID>101</SireID>
        <Pace>
            <Stakes>56</Stakes>
        </Pace>
    </Horse>
    <Horse>
        <ID>5</ID>
        <Name>hrsE</Name>
        <SireID>100</SireID>
        <Pace>
            <Stakes>20000</Stakes>
        </Pace>
    </Horse>
    <Horse>
        <ID>6</ID>
        <Name>hrsF</Name>
        <SireID>101</SireID>
        <Trot>
            <Stakes>20000</Stakes>
        </Trot>
    </Horse>
    <Horse>
        <ID>7</ID>
        <Name>hrsG</Name>
        <SireID>101</SireID>
        <Trot>
            <Stakes>559</Stakes>
        </Trot>
    </Horse>
    <Horse>
        <ID>8</ID>
        <Name>hrsH</Name>
        <SireID>102</SireID>
        <Pace>
            <Stakes>386</Stakes>
        </Pace>
        <Trot>
            <Stakes>10000</Stakes>
        </Trot>
    </Horse>
</Horses>
<Sires>
    <Sire>
        <ID>100</ID>
        <Name>srA</Name>
        <LiveFoalsALL>117</LiveFoalsALL>
    </Sire>
    <Sire>
        <ID>101</ID>
        <Name>srB</Name>
        <LiveFoalsALL>774</LiveFoalsALL>
    </Sire>
    <Sire>
        <ID>102</ID>
        <Name>srC</Name>
        <LiveFoalsALL>43</LiveFoalsALL>
    </Sire>
</Sires>

So summing the various stakes the output would have this ordering:

Sire 101 (srB) Stakes: $25415
Sire 100 (srA) Stakes: $20000
Sire 103 (srC) Stakes: $16768.

When I was just summing and ordering the individual horse stakes for other web pages I was able to use:

<xsl:apply-templates select="Horse">
    <xsl:sort select="sum(descendant::Stakes)" data-type="number"
        order="descending"/>
</xsl:apply-templates>

I just can't figure out how to do the same for the sires referencing the horse node for summing to get the right ordering... possibly something like this where I try to say the Sire/ID is equal to the Horse/SireID:

<xsl:apply-templates select="Sire">
    <xsl:sort select="sum(//Horses/Horse[@SireID=ID]/descendant::Stakes)" 
        data-type="number" order="descending"/>
</xsl:apply-templates>

But that doesn't work, the debugger jumps straight out of the current template when it hits the sort line so my syntax must be invalid. I've been trying variations on this theme without success.

Can anyone please give me a pointer of how to call my Sire template and get the correct ordering?

Thanks,

Bryce Stenberg

解决方案

This transformation:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:key name="kOffspring" match="Horse" use="SireID"/>

 <xsl:template match="/*">
  <xsl:apply-templates select="Sires/Sire">
   <xsl:sort select="sum(key('kOffspring', ID)/*/Stakes)"
             data-type="number" order="descending"/>
  </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="Sire">
     Sire <xsl:value-of select="concat(ID,' (', Name, ') Stakes: ')"/>
   <xsl:value-of select="sum(key('kOffspring', ID)/*/Stakes)"/>
 </xsl:template>
 <xsl:template match="text()"/>
</xsl:stylesheet>

when applied on the provided XML document:

<t>
    <Horses>
        <Horse>
            <ID>1</ID>
            <Name>hrsA</Name>
            <SireID>101</SireID>
            <Pace>
                <Stakes>4800</Stakes>
            </Pace>
        </Horse>
        <Horse>
            <ID>2</ID>
            <Name>hrsB</Name>
            <SireID>102</SireID>
            <Pace>
                <Stakes>3600</Stakes>
            </Pace>
        </Horse>
        <Horse>
            <ID>3</ID>
            <Name>hrsC</Name>
            <SireID>102</SireID>
            <Pace>
                <Stakes>2800</Stakes>
            </Pace>
        </Horse>
        <Horse>
            <ID>4</ID>
            <Name>hrsD</Name>
            <SireID>101</SireID>
            <Pace>
                <Stakes>56</Stakes>
            </Pace>
        </Horse>
        <Horse>
            <ID>5</ID>
            <Name>hrsE</Name>
            <SireID>100</SireID>
            <Pace>
                <Stakes>20000</Stakes>
            </Pace>
        </Horse>
        <Horse>
            <ID>6</ID>
            <Name>hrsF</Name>
            <SireID>101</SireID>
            <Trot>
                <Stakes>20000</Stakes>
            </Trot>
        </Horse>
        <Horse>
            <ID>7</ID>
            <Name>hrsG</Name>
            <SireID>101</SireID>
            <Trot>
                <Stakes>559</Stakes>
            </Trot>
        </Horse>
        <Horse>
            <ID>8</ID>
            <Name>hrsH</Name>
            <SireID>102</SireID>
            <Pace>
                <Stakes>386</Stakes>
            </Pace>
            <Trot>
                <Stakes>10000</Stakes>
            </Trot>
        </Horse>
    </Horses>
    <Sires>
        <Sire>
            <ID>100</ID>
            <Name>srA</Name>
            <LiveFoalsALL>117</LiveFoalsALL>
        </Sire>
        <Sire>
            <ID>101</ID>
            <Name>srB</Name>
            <LiveFoalsALL>774</LiveFoalsALL>
        </Sire>
        <Sire>
            <ID>102</ID>
            <Name>srC</Name>
            <LiveFoalsALL>43</LiveFoalsALL>
        </Sire>
    </Sires>
</t>

produces the wanted, correct result:

 Sire 101 (srB) Stakes: 25415
 Sire 100 (srA) Stakes: 20000
 Sire 102 (srC) Stakes: 16786

Explanation:

  1. We define a key that specifies a Horse as a function of its SireID. This is useful in selecting all offspring of a given Sire just by providing its ID in a call to the standard XSLT key() function -- like this: key('kOffspring', ID).

  2. Similarly, the sum of Stakes of all offspring of a given Sire is: sum(key('kOffspring', ID)/*/Stakes) .

  3. We apply templates to all Sire elements in the XML document and sort these by the decreasing values of the sums of the Stakes of their offsprings.

  4. For each Sire we output its ID, Name and the sum of Stakes of its offspring.

这篇关于XSLT:基于来自其他节点的值的总和进行排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆