XSL max value from a group of sample values not working

Go To StackoverFlow.com

0

I was trying to get an MAX charge from the group of values where my ddi matches the refddiNmr and name does not contain "Active"

I have multiple ddi objects and ddi name can be "PH", "FX" and such; Now for each "PH" ddi i want to get the max charge and Name from the "newP" object where Name does not contain "Active"

I tried to write multiple xsl code with for loops and other options, in the end i eneded up removing my for loops cause they were not giving me any result.

Currently i have the following code which is returning me the Max from all newP object rather then returning the max for that ddi. I'm not sure how to accomplish this, would request experts for your suggestions on this, is there is way of doing this.

My expected output should be

Number- 90004    
Name        =   SM 10 P  
MaxChre     =   39.99 < ! -- Max value within 90004 group-->

Number- 30010 < !-- this should not come because its not of name "PH"-->

Number- 30011   
Name        =   SBB 15 FX     
MaxChre     =   40.0  < ! -- Max value within 30011 group-->

Number- 30012    
Name        =   VEI    
MaxChre     =   41.0  < ! -- Max value within 30012 group-->

Apologies for the indentation in the question. here are the additional details for the code and data:

My Buggy CODE:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  xmlns:date="http://exslt.org/dates-and-times"  extension-element-prefixes="date" xmlns:math="http://exslt.org/math"  version="1.0">
<xsl:output method="xml" encoding="utf-8" indent="no"/>
    <xsl:template match="/">
            <xsl:variable name="New" select="/SM/xml_data/emData" />
            <xsl:for-each select="/SM/xml_data/emData/ddi">
        Number- <xsl:value-of select="Nmr"/>
                 <xsl:if test="name='PH'">
        Amount- <xsl:value-of select="math:max(/SM/xml_data/emData/newP[contains(refddiNmr,Nmr)]/chre)"/>
        Name- <xsl:value-of select="/SM/xml_data/emData/newP/name"/>
                </xsl:if> 
            </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

Sample Data:

    <SM>
    <xml_data>
    <emData>
        <ddi>
            <Nmr>90004</Nmr>
            <name>PH</name>
        </ddi>
        <ddi>
            <Nmr>30010</Nmr>
            <name>FA</name>
        </ddi>
        <ddi>
            <Nmr>30011</Nmr>
            <name>PH</name>
        </ddi>
        <ddi>
            <Nmr>30012</Nmr>
            <name>PH</name>
        </ddi>
        <newP>
            <start>2012-03-30</start>
            <name>VAF - Active</name>
            <chre>29.99</chre>
            <refddiNmr>90004</refddiNmr>
        </newP>
        <newP>
            <start>2012-03-30</start>
            <name>VAFD - Active</name>
            <chre>-29.99</chre>
            <refddiNmr>90004</refddiNmr>
        </newP>
        <newP>
            <start>2012-03-30</start>
            <name>SM 10 P</name>
            <chre>39.99</chre>
            <refddiNmr>90004</refddiNmr>
        </newP>
        <newP>
            <start>2012-03-30</start>
            <name>VE-I</name>
            <chre>10.0</chre>
            <refddiNmr>90004</refddiNmr>
        </newP>
        <newP>
            <start>2012-03-30</start>
            <name>SBB 15 FX</name>
            <chre>40.0</chre>
            <refddiNmr>30011</refddiNmr>
        </newP>
        <newP>
            <start>2012-03-30</start>
            <name>FXA - Active</name>
            <chre>9.99</chre>
            <refddiNmr>30011</refddiNmr>
        </newP>
        <newP>
            <start>2012-03-30</start>
            <name>FAD - Active</name>
            <chre>-9.99</chre>
            <refddiNmr>30011</refddiNmr>
        </newP>
        <newP>
            <start>2012-03-30</start>
            <name>VEI</name>
            <chre>40.0</chre>
            <refddiNmr>30011</refddiNmr>
        </newP>
        <newP>
            <start>2012-03-30</start>
            <name>SBB 15 FXA</name>
            <chre>90.0</chre>
            <refddiNmr>30010</refddiNmr>
        </newP>
        <newP>
            <start>2012-03-30</start>
            <name>FXA - Active</name>
            <chre>9.99</chre>
            <refddiNmr>30010</refddiNmr>
        </newP>
        <newP>
            <start>2012-03-30</start>
            <name>FAD - Active</name>
            <chre>-9.99</chre>
            <refddiNmr>30010</refddiNmr>
        </newP>
        <newP>
            <start>2012-03-30</start>
            <name>VEI</name>
            <chre>45.0</chre>
            <refddiNmr>30010</refddiNmr>
        </newP>
        <newP>
            <start>2012-03-30</start>
            <name>SBB 15 FXB</name>
            <chre>40.0</chre>
            <refddiNmr>30012</refddiNmr>
        </newP>
        <newP>
            <start>2012-03-30</start>
            <name>FXB - Active</name>
            <chre>9.99</chre>
            <refddiNmr>30012</refddiNmr>
        </newP>
        <newP>
            <start>2012-03-30</start>
            <name>FAD - Active</name>
            <chre>-9.99</chre>
            <refddiNmr>30012</refddiNmr>
        </newP>
        <newP>
            <start>2012-03-30</start>
            <name>VEI</name>
            <chre>41.0</chre>
            <refddiNmr>30012</refddiNmr>
        </newP>
    </emData>
    </xml_data>
    </SM>
2012-04-03 21:07
by K I M I -


0

One way to achieve this (in XSLT 1.0), is by means of a key to look up the newP elements

<xsl:key name="ref" match="newP[not(contains(name, 'active'))]" use="refddiNmr"/>

Then, for each ddi element you match, you can find the first element in the key, ordered by the chre value...

<xsl:for-each select="key('ref', Nmr)">
   <xsl:sort select="chre" order="descending" data-type="number"/>
   <xsl:if test="position() = 1">
      ... Maximum value...

Here is the full XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
   <xsl:output method="text" />

   <xsl:key name="ref" match="newP[not(contains(name, 'active'))]" use="refddiNmr"/>

   <xsl:template match="/">
      <xsl:apply-templates select="//ddi"/>
   </xsl:template>

   <xsl:template match="ddi[name='PH']">
      <xsl:value-of select="concat('Number - ', Nmr, '&#13;')"/>
      <xsl:for-each select="key('ref', Nmr)">
         <xsl:sort select="chre" order="descending" data-type="number"/>
         <xsl:if test="position() = 1">
            <xsl:value-of select="concat('Name - ', name, '&#13;MaxChre = ', chre, '&#13;')"/>
         </xsl:if>
      </xsl:for-each>
      <xsl:value-of select="'&#13;'"/>
   </xsl:template>

   <xsl:template match="ddi">
      <xsl:value-of select="concat('Number - ', Nmr, '&#13;&#13;')"/>
   </xsl:template>
</xsl:stylesheet>

When applied to your sample XML, the following is output:

Number - 90004
Name - SM 10 P
MaxChre = 39.99

Number - 30010

Number - 30011
Name - SBB 15 FX
MaxChre = 40.0

Number - 30012
Name - VEI
MaxChre = 41.0
2012-04-03 22:10
by Tim C
Is there a way of displaying Name OR chre based on which one of the 2 is required.

Like below code will always display name and chre

But I'd want to display name OR chre which ever is required in a particular location in my frontend by calling the same template - K I M I - 2012-04-04 15:08

I am not sure I get what you mean by "particular location". I think it may be better if you edit your original question to explain the extra requirment, or ask a new question. Thanks - Tim C 2012-04-05 07:40
Ads