Search code examples
xsltxslt-2.0

xsl:key filter option to show data values in different rows


I will be having xml as below:

<catalog>
    <performanceVO>
        <fAnReVal>
            <fNumber>402</fNumber>
            <rtnDate alt="12/31/1998">1998-12-31</rtnDate>
            <rtnWOSC alt="10.73">10.73</rtnWOSC>
            <rtnWSC alt="4.35">4.35</rtnWSC>
        </fAnReVal>
        <fAnReVal>
            <fNumber>402</fNumber>
            <rtnDate alt="12/31/1999">1999-12-31</rtnDate>
            <rtnWOSC alt="97.91">97.91</rtnWOSC>
            <rtnWSC alt="86.54">86.54</rtnWSC>
        </fAnReVal>
        <fAnReVal>
            <fNumber>402</fNumber>
            <rtnDate alt="12/31/2000">2000-12-31</rtnDate>
            <rtnWOSC alt="46.58">46.58</rtnWOSC>
            <rtnWSC alt="38.15">38.15</rtnWSC>
        </fAnReVal>
        <fAnReVal>
            <fNumber>402</fNumber>
            <rtnDate alt="12/31/2001">2001-12-31</rtnDate>
            <rtnWOSC alt="-20.48">-20.48</rtnWOSC>
            <rtnWSC alt="-25.05">-25.05</rtnWSC>
        </fAnReVal>
        <fAnReVal>
            <fNumber>402</fNumber>
            <rtnDate alt="12/31/2002">2002-12-31</rtnDate>
            <rtnWOSC alt="-42.48">-42.48</rtnWOSC>
            <rtnWSC alt="-45.79">-45.79</rtnWSC>
        </fAnReVal>
        <fAnReVal>
            <fNumber>402</fNumber>
            <rtnDate alt="12/31/2003">2003-12-31</rtnDate>
            <rtnWOSC alt="43.55">43.55</rtnWOSC>
            <rtnWSC alt="35.28">35.28</rtnWSC>
        </fAnReVal>
        <fAnReVal>
            <fNumber>402</fNumber>
            <rtnDate alt="12/31/2004">2004-12-31</rtnDate>
            <rtnWOSC alt="11.96">11.96</rtnWOSC>
            <rtnWSC alt="5.53">5.53</rtnWSC>
        </fAnReVal>
        <fAnReVal>
            <fNumber>402</fNumber>
            <rtnDate alt="12/31/2005">2005-12-31</rtnDate>
            <rtnWOSC alt="5.55">5.55</rtnWOSC>
            <rtnWSC alt="-0.51">-0.51</rtnWSC>
        </fAnReVal>
        <fAnReVal>
            <fNumber>402</fNumber>
            <rtnDate alt="12/31/2006">2006-12-31</rtnDate>
            <rtnWOSC alt="5.03">5.03</rtnWOSC>
            <rtnWSC alt="-1.02">-1.02</rtnWSC>
        </fAnReVal>
        <fAnReVal>
            <fNumber>402</fNumber>
            <rtnDate alt="12/31/2007">2007-12-31</rtnDate>
            <rtnWOSC alt="-1.60">-1.6</rtnWOSC>
            <rtnWSC alt="-7.26">-7.26</rtnWSC>
        </fAnReVal>
        <fAnReVal>
            <fNumber>402</fNumber>
            <rtnDate alt="12/31/2008">2008-12-31</rtnDate>
            <rtnWOSC alt="-10.64">-10.64</rtnWOSC>
            <rtnWSC alt="-15.78">-15.78</rtnWSC>
        </fAnReVal>
        <fAnReVal>
            <fNumber>402</fNumber>
            <rtnDate alt="12/31/2009">2009-12-31</rtnDate>
            <rtnWOSC alt="11.83">11.83</rtnWOSC>
            <rtnWSC alt="5.41">5.41</rtnWSC>
        </fAnReVal>
        <fAnReVal>
            <fNumber>402</fNumber>
            <rtnDate alt="12/31/2010">2010-12-31</rtnDate>
            <rtnWOSC alt="17.28">17.28</rtnWOSC>
            <rtnWSC alt="10.54">10.54</rtnWSC>
        </fAnReVal>
        <fAnReVal>
            <fNumber>402</fNumber>
            <rtnDate alt="12/31/2011">2011-12-31</rtnDate>
            <rtnWOSC alt="8.35">8.35</rtnWOSC>
            <rtnWSC alt="2.12">2.12</rtnWSC>
        </fAnReVal>
        <fAnReVal>
            <fNumber>402</fNumber>
            <rtnDate alt="12/31/2012">2012-12-31</rtnDate>
            <rtnWOSC alt="29.35">29.35</rtnWOSC>
            <rtnWSC alt="21.90">21.9</rtnWSC>
        </fAnReVal>
        <fAnReVal>
            <fNumber>402</fNumber>
            <rtnDate alt="12/31/2013">2013-12-31</rtnDate>
            <rtnWOSC alt="68.64">68.64</rtnWOSC>
            <rtnWSC alt="58.95">58.95</rtnWSC>
        </fAnReVal>
        <fAnReVal>
            <fNumber>402</fNumber>
            <rtnDate alt="12/31/2014">2014-12-31</rtnDate>
            <rtnWOSC alt="33.91">33.91</rtnWOSC>
            <rtnWSC alt="26.22">26.22</rtnWSC>
        </fAnReVal>
        <fAnReVal>
            <fNumber>402</fNumber>
            <rtnDate alt="12/31/2015">2015-12-31</rtnDate>
            <rtnWOSC alt="5.50">5.5</rtnWOSC>
            <rtnWSC alt="-0.57">-0.57</rtnWSC>
        </fAnReVal>
        <fAnReVal>
            <fNumber>402</fNumber>
            <rtnDate alt="12/31/2016">2016-12-31</rtnDate>
            <rtnWOSC alt="-17.16">-17.16</rtnWOSC>
            <rtnWSC alt="-21.92">-21.92</rtnWSC>
        </fAnReVal>
        <bmCalYearDet>
               <benchMarkName>heading1</benchMarkName>
               <benchMarkOrder>1</benchMarkOrder>
               <bmCalDet>
                  <calYear>2016</calYear>
                  <val alt="11.96">11.96</val>
               </bmCalDet>
               <bmCalDet>
                  <calYear>2015</calYear>
                  <val alt="1.38">1.38</val>
               </bmCalDet>
               <bmCalDet>
                  <calYear>2014</calYear>
                  <val alt="13.69">13.69</val>
               </bmCalDet>
               <bmCalDet>
                  <calYear>2013</calYear>
                  <val alt="32.39">32.39</val>
               </bmCalDet>
               <bmCalDet>
                  <calYear>2012</calYear>
                  <val alt="16.00">16</val>
               </bmCalDet>
               <bmCalDet>
                  <calYear>2011</calYear>
                  <val alt="2.11">2.11</val>
               </bmCalDet>
               <bmCalDet>
                  <calYear>2010</calYear>
                  <val alt="15.06">15.06</val>
               </bmCalDet>
               <bmCalDet>
                  <calYear>2009</calYear>
                  <val alt="26.46">26.46</val>
               </bmCalDet>
               <bmCalDet>
                  <calYear>2008</calYear>
                  <val alt="-37.00">-37</val>
               </bmCalDet>
               <bmCalDet>
                  <calYear>2007</calYear>
                  <val alt="5.49">5.49</val>
               </bmCalDet>
            </bmCalYearDet>
            <bmCalYearDet>
            <benchMarkName>heading2</benchMarkName>
            <benchMarkOrder>2</benchMarkOrder>
            <bmCalDet>
                <calYear>2016</calYear>
                <val alt="-21.68">-21.68</val>
            </bmCalDet>
            <bmCalDet>
                <calYear>2015</calYear>
                <val alt="11.42">11.42</val>
            </bmCalDet>
            <bmCalDet>
                <calYear>2014</calYear>
                <val alt="34.32">34.32</val>
            </bmCalDet>
            <bmCalDet>
                <calYear>2013</calYear>
                <val alt="65.97">65.97</val>
            </bmCalDet>
            <bmCalDet>
                <calYear>2012</calYear>
                <val alt="32.29">32.29</val>
            </bmCalDet>
            <bmCalDet>
                <calYear>2011</calYear>
                <val alt="12.08">12.08</val>
            </bmCalDet>
            <bmCalDet>
                <calYear>2010</calYear>
                <val alt="15.25">15.25</val>
            </bmCalDet>
            <bmCalDet>
                <calYear>2009</calYear>
                <val alt="15.84">15.84</val>
            </bmCalDet>
            <bmCalDet>
                <calYear>2008</calYear>
                <val alt="-12.56">-12.56</val>
            </bmCalDet>
            <bmCalDet>
                <calYear>2007</calYear>
                <val alt="4.64">4.64</val>
            </bmCalDet>
        </bmCalYearDet>
    </performanceVO>
</catalog>

Below is my xsl:

<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="bmCalDet-by-year" match="bmCalDet" use="calYear" />

<xsl:template match="/catalog">
    <xsl:variable name="catalog" select="." />

    <xsl:variable name="years">
        <xsl:for-each select="performanceVO/fAnReVal">
            <xsl:sort select="rtnDate" order="descending"/>
            <xsl:if test="position() le 10">
                <xsl:copy-of select="."/>
            </xsl:if>
        </xsl:for-each> 
    </xsl:variable> 

    <table border="1">
        <!-- header -->
        <tr>
            <th/>
            <xsl:for-each select="$years/fAnReVal">
                <th>
                    <xsl:value-of select="substring-before(rtnDate, '-')" />
                </th>
            </xsl:for-each>
        </tr>
        <!-- 1st row -->
        <tr>
            <th>rtnWOSC</th>
            <xsl:for-each select="$years/fAnReVal">
                <td>
                    <xsl:value-of select="rtnWOSC" />
                </td>
            </xsl:for-each>
        </tr>
        <!-- 2nd row -->
        <tr>
            <th>rtnWSC</th>
            <xsl:for-each select="$years/fAnReVal">
                <td>
                    <xsl:value-of select="rtnWSC" />
                </td>
            </xsl:for-each>
        </tr>
        <!-- 3rd row here is the issue with the code-->
        <tr>
            <th>val</th>
            <xsl:for-each select="$years/fAnReVal">
                <td>
                    <xsl:value-of select="key('bmCalDet-by-year', substring-before(rtnDate, '-'), $catalog)/val" />
                </td>
            </xsl:for-each>
        </tr>
    </table>
</xsl:template>

</xsl:stylesheet>

There are two tree node which differs with node . When I loop and use the code as I'm getting two values in the same row. Tried filtering it with node but couldn't able to filter. Can anyone please provide the pointers? issue is with third row.


Solution

  • It looks like you need an xsl:for-each on bmCalYearDet and then add a condition on the key to filter on the benchMarkOrder

    <!-- 3rd row here is the issue with the code-->
    <xsl:for-each select="performanceVO/bmCalYearDet">
        <xsl:variable name="benchMarkOrder" select="benchMarkOrder" />
        <tr>
            <th>val</th>
            <xsl:for-each select="$years/fAnReVal">
                <td>
                   <xsl:value-of select="key('bmCalDet-by-year', substring-before(rtnDate, '-'), $catalog)[../benchMarkOrder = $benchMarkOrder]/val" />
                </td>
            </xsl:for-each>
        </tr>
    </xsl:for-each>
    

    As you are using XSLT 2.0, you could also write it like so

    <!-- 3rd row here is the issue with the code-->
    <xsl:for-each select="performanceVO/bmCalYearDet">
        <xsl:variable name="benchMarkOrder" select="." />
        <tr>
            <th>val</th>
            <xsl:for-each select="$years/fAnReVal">
                <td>
                    <xsl:value-of select="key('bmCalDet-by-year', substring-before(rtnDate, '-'), $benchMarkOrder)/val" />
                </td>
            </xsl:for-each>
        </tr>
    </xsl:for-each>