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 sectio
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:
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)
.
Similarly, the sum of Stakes
of all offspring of a given Sire
is: sum(key('kOffspring', ID)/*/Stakes)
.
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.
For each Sire
we output its ID
, Name
and the sum of Stakes
of its offspring.
You need to use current()
:
<xsl:apply-templates select="Sire">
<xsl:sort select="sum(//Horses/Horse[SireID = current()/ID]//Stakes)"
data-type="number" order="descending"/>
current()
gives you the context node as it is outside of the current XPath expression; in this case, the current <Sire>
element selected by xsl:apply-templates
. Inside the predicate, the context node is the <Horse>
element that's being tested against the predicate expression.
Notes:
@
in there that you don't want; @ID
refers to an ID attribute.descendant::/
with //
//foo[barID = current()/ID]
.