Search code examples
xsltxslt-2.0

Need to calculate Median for set of numbers using xslt


Need help with calculating Median for set of numbers using xslt. Ex: I am getting PSQ3_Values for first Empid are 8 6 8 and need Median value from it. Ex: sort:6,8,8 and median is 8. Getting PSQ3_Values for second Empid (456) are 9 10 and need Median value from it. Ex: sort:9,10 Since it is even number and median should be 19/2=9.5. I tried with the below commented one but not able to figure it out fully.

Input xml:

<wd:Report_Data
    xmlns:wd="urn:com.workday/bsvc">
    <wd:Report_Entry>
        <wd:empid>123</wd:empid>
        <wd:tempno>2</wd:tempno>
        <wd:category>Peer/Stakeholder</wd:category>
        <wd:questionno>1</wd:questionno>
        <wd:response>
            <p>Dependable and Honest</p>
        </wd:response>
    </wd:Report_Entry>
    <wd:Report_Entry>
        <wd:empid>123</wd:empid>
        <wd:tempno>2</wd:tempno>
        <wd:category>Peer/Stakeholder</wd:category>
        <wd:questionno>2</wd:questionno>
        <wd:response>
            <p>Results</p>
        </wd:response>
    </wd:Report_Entry>
    <wd:Report_Entry>
        <wd:empid>123</wd:empid>
        <wd:tempno>2</wd:tempno>
        <wd:category>Peer/Stakeholder</wd:category>
        <wd:questionno>3</wd:questionno>
        <wd:response>8</wd:response>
    </wd:Report_Entry>
    <wd:Report_Entry>
        <wd:empid>123</wd:empid>
        <wd:tempno>2</wd:tempno>
        <wd:category>Peer/Stakeholder</wd:category>
        <wd:questionno>4</wd:questionno>
        <wd:response>9</wd:response>
    </wd:Report_Entry>
    <wd:Report_Entry>
        <wd:empid>456</wd:empid>
        <wd:tempno>1</wd:tempno>
        <wd:category>Peer/Stakeholder</wd:category>
        <wd:questionno>1</wd:questionno>
        <wd:response>
            <p>Flexibility and Open-Minded</p>
        </wd:response>
    </wd:Report_Entry>
    <wd:Report_Entry>
        <wd:empid>456</wd:empid>
        <wd:tempno>1</wd:tempno>
        <wd:category>Peer/Stakeholder</wd:category>
        <wd:questionno>2</wd:questionno>
        <wd:response>
            <p>Transparency</p>
        </wd:response>
    </wd:Report_Entry>
    <wd:Report_Entry>
        <wd:empid>456</wd:empid>
        <wd:tempno>1</wd:tempno>
        <wd:category>Peer/Stakeholder</wd:category>
        <wd:questionno>3</wd:questionno>
        <wd:response>9</wd:response>
    </wd:Report_Entry>
    <wd:Report_Entry>
        <wd:empid>456</wd:empid>
        <wd:tempno>1</wd:tempno>
        <wd:category>Peer/Stakeholder</wd:category>
        <wd:questionno>4</wd:questionno>
        <wd:response>10</wd:response>
    </wd:Report_Entry>
    <wd:Report_Entry>
        <wd:empid>123</wd:empid>
        <wd:tempno>2</wd:tempno>
        <wd:category>Peer/Stakeholder</wd:category>
        <wd:questionno>1</wd:questionno>
        <wd:response>
            <p>Results and Experience</p>
        </wd:response>
    </wd:Report_Entry>
    <wd:Report_Entry>
        <wd:empid>123</wd:empid>
        <wd:tempno>2</wd:tempno>
        <wd:category>Peer/Stakeholder</wd:category>
        <wd:questionno>2</wd:questionno>
        <wd:response>
            <p>Efficient</p>
        </wd:response>
    </wd:Report_Entry>
    <wd:Report_Entry>
        <wd:empid>123</wd:empid>
        <wd:tempno>2</wd:tempno>
        <wd:category>Peer/Stakeholder</wd:category>
        <wd:questionno>3</wd:questionno>
        <wd:response>6</wd:response>
    </wd:Report_Entry>
    <wd:Report_Entry>
        <wd:empid>123</wd:empid>
        <wd:tempno>2</wd:tempno>
        <wd:category>Peer/Stakeholder</wd:category>
        <wd:questionno>4</wd:questionno>
        <wd:response>4</wd:response>
    </wd:Report_Entry>
    <wd:Report_Entry>
        <wd:empid>456</wd:empid>
        <wd:tempno>1</wd:tempno>
        <wd:category>Direct Report</wd:category>
        <wd:questionno>1</wd:questionno>
        <wd:response>
            <p>intentional and open</p>
        </wd:response>
    </wd:Report_Entry>
    <wd:Report_Entry>
        <wd:empid>456</wd:empid>
        <wd:tempno>1</wd:tempno>
        <wd:category>Direct Report</wd:category>
        <wd:questionno>2</wd:questionno>
        <wd:response>
            <p>Change</p>
        </wd:response>
    </wd:Report_Entry>
    <wd:Report_Entry>
        <wd:empid>456</wd:empid>
        <wd:tempno>1</wd:tempno>
        <wd:category>Direct Report</wd:category>
        <wd:questionno>3</wd:questionno>
        <wd:response>5</wd:response>
    </wd:Report_Entry>
    <wd:Report_Entry>
        <wd:empid>456</wd:empid>
        <wd:tempno>1</wd:tempno>
        <wd:category>Direct Report</wd:category>
        <wd:questionno>4</wd:questionno>
        <wd:response>6</wd:response>
    </wd:Report_Entry>
    <wd:Report_Entry>
        <wd:empid>456</wd:empid>
        <wd:tempno>1</wd:tempno>
        <wd:category>Peer/Stakeholder</wd:category>
        <wd:questionno>1</wd:questionno>
        <wd:response>
            <p>Team Leader and Flexibility</p>
        </wd:response>
    </wd:Report_Entry>
    <wd:Report_Entry>
        <wd:empid>456</wd:empid>
        <wd:tempno>1</wd:tempno>
        <wd:category>Peer/Stakeholder</wd:category>
        <wd:questionno>2</wd:questionno>
        <wd:response>
            <p>Collaborator</p>
        </wd:response>
    </wd:Report_Entry>
    <wd:Report_Entry>
        <wd:empid>456</wd:empid>
        <wd:tempno>1</wd:tempno>
        <wd:category>Peer/Stakeholder</wd:category>
        <wd:questionno>3</wd:questionno>
        <wd:response>10</wd:response>
    </wd:Report_Entry>
    <wd:Report_Entry>
        <wd:empid>456</wd:empid>
        <wd:tempno>1</wd:tempno>
        <wd:category>Peer/Stakeholder</wd:category>
        <wd:questionno>4</wd:questionno>
        <wd:response>10</wd:response>
    </wd:Report_Entry>
    <wd:Report_Entry>
        <wd:empid>123</wd:empid>
        <wd:tempno>2</wd:tempno>
        <wd:category>Peer/Stakeholder</wd:category>
        <wd:questionno>1</wd:questionno>
        <wd:response>
            <p>knowledge and confident</p>
        </wd:response>
    </wd:Report_Entry>
    <wd:Report_Entry>
        <wd:empid>123</wd:empid>
        <wd:tempno>2</wd:tempno>
        <wd:category>Peer/Stakeholder</wd:category>
        <wd:questionno>2</wd:questionno>
        <wd:response>
            <p>stretch</p>
        </wd:response>
    </wd:Report_Entry>
    <wd:Report_Entry>
        <wd:empid>123</wd:empid>
        <wd:tempno>2</wd:tempno>
        <wd:category>Peer/Stakeholder</wd:category>
        <wd:questionno>3</wd:questionno>
        <wd:response>8</wd:response>
    </wd:Report_Entry>
    <wd:Report_Entry>
        <wd:empid>123</wd:empid>
        <wd:tempno>2</wd:tempno>
        <wd:category>Peer/Stakeholder</wd:category>
        <wd:questionno>4</wd:questionno>
        <wd:response>6</wd:response>
    </wd:Report_Entry>
    <wd:Report_Entry>
        <wd:empid>456</wd:empid>
        <wd:tempno>1</wd:tempno>
        <wd:category>Direct Report</wd:category>
        <wd:questionno>1</wd:questionno>
        <wd:response>
            <p>Agility and Transparency</p>
        </wd:response>
    </wd:Report_Entry>
    <wd:Report_Entry>
        <wd:empid>456</wd:empid>
        <wd:tempno>1</wd:tempno>
        <wd:category>Direct Report</wd:category>
        <wd:questionno>2</wd:questionno>
        <wd:response>
            <p>Change Management and Exposure</p>
        </wd:response>
    </wd:Report_Entry>
    <wd:Report_Entry>
        <wd:empid>456</wd:empid>
        <wd:tempno>1</wd:tempno>
        <wd:category>Direct Report</wd:category>
        <wd:questionno>3</wd:questionno>
        <wd:response>4</wd:response>
    </wd:Report_Entry>
    <wd:Report_Entry>
        <wd:empid>456</wd:empid>
        <wd:tempno>1</wd:tempno>
        <wd:category>Direct Report</wd:category>
        <wd:questionno>4</wd:questionno>
        <wd:response>5</wd:response>
    </wd:Report_Entry>
    <wd:Report_Entry>
        <wd:empid>456</wd:empid>
        <wd:tempno>1</wd:tempno>
        <wd:category>Direct Report</wd:category>
        <wd:questionno>1</wd:questionno>
        <wd:response>
            <p>Fearless and Collaborator</p>
        </wd:response>
    </wd:Report_Entry>
    <wd:Report_Entry>
        <wd:empid>456</wd:empid>
        <wd:tempno>1</wd:tempno>
        <wd:category>Direct Report</wd:category>
        <wd:questionno>2</wd:questionno>
        <wd:response>
            <p>Strategy and Transparency</p>
        </wd:response>
    </wd:Report_Entry>
</wd:Report_Data>

This is the one I am trying it using xslt:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:is="java:com.workday.esb.intsys.xpath.ParsedIntegrationSystemFunctions"
    xmlns:xdiff="urn:com.workday/esb/xdiff"
    xmlns:wd="urn:com.workday/bsvc">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="no"/>
    <xsl:template match="/">
        <Report_Data>
            <xsl:apply-templates select="wd:Report_Data"/>
        </Report_Data>
    </xsl:template>
    <xsl:template match="wd:Report_Data">
        <xsl:for-each-group select="wd:Report_Entry" group-by="wd:empid">
            <Report_Entry>
                <empid>
                    <xsl:value-of select="wd:empid"/>
                </empid>
                <tempno>
                    <xsl:value-of select="wd:tempno"/>
                </tempno>
                <PSQ3_Values>
                    <xsl:for-each
                        select="current-group()[wd:category = 'Peer/Stakeholder' and wd:questionno = '3']">
                        <xsl:value-of select="wd:response"/>
                    </xsl:for-each>
                </PSQ3_Values>
                
              <!-- 
                  <PSQ3_Median>
                    
                    <xsl:variable name="nodes" select="current-group()[wd:category = 'Peer/Stakeholder' and wd:questionno='3']/wd:response"/>                    
                    <xsl:variable name="count" select="count(current-group()[wd:category = 'Peer/Stakeholder' and wd:questionno='3']/wd:response)"/>
                    <xsl:variable name="middle" select="ceiling($count div 2)"/>
                    <xsl:variable name="even" select="not($count mod 2)"/>                           
                    
                    <xsl:for-each select="$nodes">
                        <xsl:sort select="wd:response" data-type="number" order="ascending"/>
                        <xsl:if test="position() = $middle">
                            <xsl:value-of select="wd:response,(position() = $middle())"/>                                 
                            
                        </xsl:if>
                    </xsl:for-each>   
                </PSQ3_Median>
 -->
            </Report_Entry>
        </xsl:for-each-group>
    </xsl:template>
</xsl:stylesheet>

Solution

  • Consider the following simplified example:

    XML

    <Report_Data>
       <Report_Entry>
          <empid>123</empid>
          <value>9</value>
       </Report_Entry>
       <Report_Entry>
          <empid>456</empid>
          <value>9</value>
       </Report_Entry>
       <Report_Entry>
          <empid>456</empid>
          <value>10</value>
       </Report_Entry>
       <Report_Entry>
          <empid>123</empid>
          <value>6</value>
       </Report_Entry>
       <Report_Entry>
          <empid>123</empid>
          <value>4</value>
       </Report_Entry>
       <Report_Entry>
          <empid>456</empid>
          <value>5</value>
       </Report_Entry>
       <Report_Entry>
          <empid>456</empid>
          <value>6</value>
       </Report_Entry>
       <Report_Entry>
          <empid>456</empid>
          <value>10</value>
       </Report_Entry>
       <Report_Entry>
          <empid>456</empid>
          <value>10</value>
       </Report_Entry>
       <Report_Entry>
          <empid>123</empid>
          <value>8</value>
       </Report_Entry>
       <Report_Entry>
          <empid>123</empid>
          <value>6</value>
       </Report_Entry>
       <Report_Entry>
          <empid>456</empid>
          <value>4</value>
       </Report_Entry>
       <Report_Entry>
          <empid>456</empid>
          <value>5</value>
       </Report_Entry>
    </Report_Data>
    

    XSLT 2.0

    <xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>
    
    <xsl:template match="/Report_Data">
        <Report_Data>
            <xsl:for-each-group select="Report_Entry" group-by="empid">
                <Report_Entry>
                    <empid>
                        <xsl:value-of select="empid"/>
                    </empid>
                    <xsl:variable name="sorted-values" as="element()*">
                        <xsl:perform-sort select="current-group()/value">
                            <xsl:sort select="." data-type="number"/>
                        </xsl:perform-sort> 
                    </xsl:variable> 
                    <values>
                        <xsl:value-of select="$sorted-values"/>
                    </values>
                    <median>
                        <xsl:variable name="n" select="count($sorted-values)" />
                        <xsl:variable name="mid" select="$n idiv 2" />
                        <xsl:choose>
                            <xsl:when test="$n mod 2">
                                <xsl:value-of select="$sorted-values[$mid + 1]"/>
                            </xsl:when>
                            <xsl:otherwise>
                                <xsl:value-of select="avg($sorted-values[position()=($mid, $mid + 1)])"/>
                            </xsl:otherwise>
                        </xsl:choose>
                   </median>
                </Report_Entry>
            </xsl:for-each-group>
        </Report_Data>
    </xsl:template>
    
    </xsl:stylesheet>
    

    Result

    <?xml version="1.0" encoding="UTF-8"?>
    <Report_Data>
       <Report_Entry>
          <empid>123</empid>
          <values>4 6 6 8 9</values>
          <median>6</median>
       </Report_Entry>
       <Report_Entry>
          <empid>456</empid>
          <values>4 5 5 6 9 10 10 10</values>
          <median>7.5</median>
       </Report_Entry>
    </Report_Data>