0

Hi I am relatively new to XSLT (used to procedural programming languages) but finding it difficult to understand how I can accomplish that in XSLT and will appreciate any help:

The xml, I want to transform follows - Is nothing more than a listing of employees with their monthly salary changes. The objective is to determine the annual salary for 2015.

    <employees>

        <employee>
            <id>E1</id>
            <hiredt>2000-01-01</hiredt>
            <salaryhistory>
                <change> 
                    <efffrom>2000-01-01</efffrom>
                    <monthlypay>4000</monthlypay>
                </change>
                <change> 
                    <efffrom>2014-01-01</efffrom>
                    <monthlypay>5000</monthlypay>
                </change>
                <change>
                    <efffrom>2015-02-01</efffrom>
                    <monthlypay>6000</monthlypay>
                </change>
                <change>
                    <efffrom>2015-07-01</efffrom>
                    <monthlypay>7000</monthlypay>
                </change>
            </salaryhistory>
        </employee>
        <employee>
            <id>E2</id>
            <hiredt>2015-03-01</hiredt>     
            <salaryhistory>
                <change>
                    <efffrom>2015-03-01</efffrom>
                    <monthlypay>5000</monthlypay>
                </change>
            </salaryhistory>
        </employee>

    </employees>

The objective is to compute the annual salary for all employees for 2015 and transform into the following XML document

        <employees>

        <employee>
            <id>E1</id>
            <annualsal>77000</annualsal>
        </employee>

        <employee>
            <id>E2</id>
            <annualsal>50000</annualsal>
        </employee>     

    </employees>

Explanation on computation.

Computation for E1
5000 * 1 month  =  5000
6000 * 5 months = 30000
7000 * 6 months = 42000
Total                   77000

Computation for E2

5000 * 10 months = 50,000 employee started on March 1,2015.

Any guidance will be much appreciated.

1 Answers1

0

There may be a more elegant way, but this works:

XSLT 2.0

<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>

<xsl:param name="year" select="2015"/>

<xsl:variable name="months" as="xs:date*">
    <xsl:for-each select="1 to 12">
        <xsl:sequence select="xs:date(concat($year, format-number(., '-00'), '-01'))"/>
    </xsl:for-each>
</xsl:variable>

<xsl:template match="/employees">
    <xsl:copy>
        <xsl:apply-templates select="employee"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="employee">
    <xsl:copy>
        <xsl:copy-of select="id"/>
        <xsl:variable name="salary-changes" select="salaryhistory/change" />
        <xsl:variable name="salaries-by-month" as="xs:integer*">
            <xsl:for-each select="$months">
                <xsl:sequence select="$salary-changes[xs:date(efffrom) le current()][last()]/monthlypay" />
            </xsl:for-each>
        </xsl:variable>
        <annualsal>
            <xsl:value-of select="sum($salaries-by-month)" />
        </annualsal>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

Note that salary changes are assumed to be listed in chronological order.

michael.hor257k
  • 113,275
  • 6
  • 33
  • 51
  • Michael,Thank you for your response. I would never have thought of doing something like this - – StillStumbling Apr 17 '15 at 18:56
  • Michael,Thank you for your response. I would never have thought of doing something like this - I was thinking more on the lines of look for the next effective dated row and then computing the amount. Can you explain this statement - – StillStumbling Apr 17 '15 at 19:02
  • "*Can you explain this statement - – michael.hor257k Apr 17 '15 at 19:08
  • Thanks. Cannot vote up the answer as I joined recently. – StillStumbling Apr 17 '15 at 20:08
  • I am getting a error here when I try to run the xfrom - – StillStumbling Apr 17 '15 at 21:08
  • How will this work if the dates of changes are not necessarily at the begining of the month? – StillStumbling Apr 17 '15 at 21:11
  • **1.** I can't help you with the error if you don't provide a way to reproduce the problem. **2.** I don't know: what would be the rules for such calculation? – michael.hor257k Apr 17 '15 at 21:24
  • @StillStumbling - are you sure you are using an XSLT 2.0 processor? – Michael Kay Apr 17 '15 at 21:47
  • @Michael Kay - I am not sure. I am trying to trasform on Net beans IDE. – StillStumbling Apr 17 '15 at 22:22
  • @StillStumbling If you're not sure, find out - see here how: http://stackoverflow.com/questions/25244370/how-can-we-check-that-which-xslt-processor-uses-as-default-in-solr/25245033#25245033 – michael.hor257k Apr 17 '15 at 22:24
  • @Michael Kay - You are right its using XALAN for some reason. I did copy the saxonhe jar in lib/ext folder and created the jaxp.properties file. – StillStumbling Apr 18 '15 at 04:39
  • @michael-hor257k Thank you for the link. Cannot thank you and Michael Kay guys enough! – StillStumbling Apr 18 '15 at 04:42
  • I tried doing the same on a different laptop. And it certainly looks like a config issue. – StillStumbling Apr 18 '15 at 04:56
  • I tried doing the same on a different laptop. And it certainly looks like a config issue. It working wonderfully . As regards, the date, @michael-hor257k, yes you are spot.. Cannot expect you to envisage how the dates will look. I simplified it. employee is paid bi-weekly. If the salary increase falls in a particular bi-week, then the increase will apply to that entire pay period. For example, say the bi weekly period is as follows: period 1 4-Jan 17-Jan Peiod 2 18-Jan 31-Jan Peiod 3 - 1-Feb 14-Feb etc. I will try working on this and post a new question if I find myself getting stuck. – StillStumbling Apr 18 '15 at 05:11
  • @StillStumbling Switching from months to bi-weekly periods shouldn't make too much difference, but two things need to be established: (1) how to adjust a monthly salary to a bi-weekly payout; and (2) what exactly is the meaning of "annual salary", when pay periods can span across year boundaries. – michael.hor257k Apr 18 '15 at 07:55