XSLT key not available inside template (using note-set array) - xslt

I created an XLT document with an array of values for each of the hour of the day. I loop through this array by creating a variable using node-set.
I have a key created that holds the total counts for each hour called key-hours. However, when I pass it a value from the $hour-array variable, it does not display the corresponding total count.
XML data
<Records reportTime24h="18:14" reportTime="06:14:55PM" reportDate="2020-11-12" reportTitle="Samples per time of day v2">
<vars>
<date>2020-11-12</date>
</vars>
<Record>
<TubeName>Wholeblood Haematology</TubeName>
<RegisterHour>07 AM</RegisterHour>
<Total>2</Total>
</Record>
<Record>
<TubeName>Wholeblood Haematology</TubeName>
<RegisterHour>08 AM</RegisterHour>
<Total>15</Total>
</Record>
<Record>
<TubeName>Chemistry Serum</TubeName>
<RegisterHour>08 AM</RegisterHour>
<Total>4</Total>
</Record>
<Record>
<TubeName>Chemistry Wholeblood</TubeName>
<RegisterHour>08 AM</RegisterHour>
<Total>1</Total>
</Record>
<Record>
<TubeName>Chemistry Plasma</TubeName>
<RegisterHour>08 AM</RegisterHour>
<Total>1</Total>
</Record>
<Record>
<TubeName>Wholeblood Haematology</TubeName>
<RegisterHour>09 AM</RegisterHour>
<Total>23</Total>
</Record>
<Record>
<TubeName>Chemistry Serum</TubeName>
<RegisterHour>09 AM</RegisterHour>
<Total>15</Total>
</Record>
<Record>
<TubeName>Chemistry Wholeblood</TubeName>
<RegisterHour>09 AM</RegisterHour>
<Total>4</Total>
</Record>
<Record>
<TubeName>FAST_PLA</TubeName>
<RegisterHour>09 AM</RegisterHour>
<Total>2</Total>
</Record>
<Record>
<TubeName>1HR_PLASMA</TubeName>
<RegisterHour>09 AM</RegisterHour>
<Total>2</Total>
</Record>
<Record>
<TubeName>2HR_PLASMA</TubeName>
<RegisterHour>09 AM</RegisterHour>
<Total>2</Total>
</Record>
<Record>
<TubeName>Wholeblood Haematology</TubeName>
<RegisterHour>10 AM</RegisterHour>
<Total>25</Total>
</Record>
<Record>
<TubeName>Chemistry Serum</TubeName>
<RegisterHour>10 AM</RegisterHour>
<Total>8</Total>
</Record>
<Record>
<TubeName>Chemistry Wholeblood</TubeName>
<RegisterHour>10 AM</RegisterHour>
<Total>1</Total>
</Record>
<Record>
<TubeName>Chemistry Serum</TubeName>
<RegisterHour>11 AM</RegisterHour>
<Total>30</Total>
</Record>
<Record>
<TubeName>FAST_PLA</TubeName>
<RegisterHour>11 AM</RegisterHour>
<Total>4</Total>
</Record>
<Record>
<TubeName>Wholeblood Haematology</TubeName>
<RegisterHour>11 AM</RegisterHour>
<Total>18</Total>
</Record>
<Record>
<TubeName>Chemistry Wholeblood</TubeName>
<RegisterHour>11 AM</RegisterHour>
<Total>2</Total>
</Record>
<Record>
<TubeName>1HR_PLASMA</TubeName>
<RegisterHour>11 AM</RegisterHour>
<Total>1</Total>
</Record>
<Record>
<TubeName>2HR_PLASMA</TubeName>
<RegisterHour>11 AM</RegisterHour>
<Total>2</Total>
</Record>
<Record>
<TubeName>FAST_PLA</TubeName>
<RegisterHour>12 PM</RegisterHour>
<Total>3</Total>
</Record>
<Record>
<TubeName>Chemistry Serum</TubeName>
<RegisterHour>12 PM</RegisterHour>
<Total>29</Total>
</Record>
<Record>
<TubeName>Wholeblood Haematology</TubeName>
<RegisterHour>12 PM</RegisterHour>
<Total>24</Total>
</Record>
<Record>
<TubeName>2HR_PLASMA</TubeName>
<RegisterHour>12 PM</RegisterHour>
<Total>1</Total>
</Record>
<Record>
<TubeName>1HR_PLASMA</TubeName>
<RegisterHour>12 PM</RegisterHour>
<Total>1</Total>
</Record>
<Record>
<TubeName>Chemistry Wholeblood</TubeName>
<RegisterHour>12 PM</RegisterHour>
<Total>3</Total>
</Record>
<Record>
<TubeName>Chemistry Plasma</TubeName>
<RegisterHour>12 PM</RegisterHour>
<Total>1</Total>
</Record>
<Record>
<TubeName>Chemistry Serum</TubeName>
<RegisterHour>01 PM</RegisterHour>
<Total>32</Total>
</Record>
<Record>
<TubeName>Wholeblood Haematology</TubeName>
<RegisterHour>01 PM</RegisterHour>
<Total>33</Total>
</Record>
<Record>
<TubeName>2HR_PLASMA</TubeName>
<RegisterHour>01 PM</RegisterHour>
<Total>1</Total>
</Record>
<Record>
<TubeName>1HR_PLASMA</TubeName>
<RegisterHour>01 PM</RegisterHour>
<Total>1</Total>
</Record>
<Record>
<TubeName>FAST_PLA</TubeName>
<RegisterHour>01 PM</RegisterHour>
<Total>5</Total>
</Record>
<Record>
<TubeName>Chemistry Wholeblood</TubeName>
<RegisterHour>01 PM</RegisterHour>
<Total>3</Total>
</Record>
<Record>
<TubeName>Chemistry Serum</TubeName>
<RegisterHour>02 PM</RegisterHour>
<Total>36</Total>
</Record>
<Record>
<TubeName>FAST_PLA</TubeName>
<RegisterHour>02 PM</RegisterHour>
<Total>13</Total>
</Record>
<Record>
<TubeName>Wholeblood Haematology</TubeName>
<RegisterHour>02 PM</RegisterHour>
<Total>38</Total>
</Record>
<Record>
<TubeName>Chemistry Wholeblood</TubeName>
<RegisterHour>02 PM</RegisterHour>
<Total>8</Total>
</Record>
<Record>
<TubeName>2HR_PLASMA</TubeName>
<RegisterHour>02 PM</RegisterHour>
<Total>4</Total>
</Record>
<Record>
<TubeName>1HR_PLASMA</TubeName>
<RegisterHour>02 PM</RegisterHour>
<Total>4</Total>
</Record>
<Record>
<TubeName>Chemistry Plasma</TubeName>
<RegisterHour>02 PM</RegisterHour>
<Total>1</Total>
</Record>
<Record>
<TubeName>Chemistry Serum</TubeName>
<RegisterHour>03 PM</RegisterHour>
<Total>23</Total>
</Record>
<Record>
<TubeName>Wholeblood Haematology</TubeName>
<RegisterHour>03 PM</RegisterHour>
<Total>29</Total>
</Record>
<Record>
<TubeName>Chemistry Wholeblood</TubeName>
<RegisterHour>03 PM</RegisterHour>
<Total>1</Total>
</Record>
<Record>
<TubeName>FAST_PLA</TubeName>
<RegisterHour>03 PM</RegisterHour>
<Total>12</Total>
</Record>
<Record>
<TubeName>2HR_PLASMA</TubeName>
<RegisterHour>03 PM</RegisterHour>
<Total>5</Total>
</Record>
<Record>
<TubeName>1HR_PLASMA</TubeName>
<RegisterHour>03 PM</RegisterHour>
<Total>5</Total>
</Record>
<Record>
<TubeName>Chemistry Plasma</TubeName>
<RegisterHour>03 PM</RegisterHour>
<Total>3</Total>
</Record>
<Record>
<TubeName>Chemistry Urine</TubeName>
<RegisterHour>03 PM</RegisterHour>
<Total>1</Total>
</Record>
<Record>
<TubeName>FAST_PLA</TubeName>
<RegisterHour>04 PM</RegisterHour>
<Total>6</Total>
</Record>
<Record>
<TubeName>Chemistry Serum</TubeName>
<RegisterHour>04 PM</RegisterHour>
<Total>16</Total>
</Record>
<Record>
<TubeName>Wholeblood Haematology</TubeName>
<RegisterHour>04 PM</RegisterHour>
<Total>17</Total>
</Record>
<Record>
<TubeName>Chemistry Wholeblood</TubeName>
<RegisterHour>04 PM</RegisterHour>
<Total>2</Total>
</Record>
<Record>
<TubeName>Chemistry Plasma</TubeName>
<RegisterHour>04 PM</RegisterHour>
<Total>2</Total>
</Record>
<Record>
<TubeName>2HR_PLASMA</TubeName>
<RegisterHour>04 PM</RegisterHour>
<Total>2</Total>
</Record>
<Record>
<TubeName>1HR_PLASMA</TubeName>
<RegisterHour>04 PM</RegisterHour>
<Total>2</Total>
</Record>
<Record>
<TubeName>Chemistry Urine</TubeName>
<RegisterHour>04 PM</RegisterHour>
<Total>2</Total>
</Record>
<Record>
<TubeName>Chemistry Plasma</TubeName>
<RegisterHour>05 PM</RegisterHour>
<Total>1</Total>
</Record>
<Record>
<TubeName>Chemistry Serum</TubeName>
<RegisterHour>05 PM</RegisterHour>
<Total>3</Total>
</Record>
<Record>
<TubeName>Wholeblood Haematology</TubeName>
<RegisterHour>05 PM</RegisterHour>
<Total>4</Total>
</Record>
<Record>
<TubeName>Chemistry Serum</TubeName>
<RegisterHour>06 PM</RegisterHour>
<Total>2</Total>
</Record>
<Record>
<TubeName>Wholeblood Haematology</TubeName>
<RegisterHour>06 PM</RegisterHour>
<Total>2</Total>
</Record>
<Record>
<TubeName>Chemistry Serum</TubeName>
<RegisterHour>09 PM</RegisterHour>
<Total>5</Total>
</Record>
<Record>
<TubeName>Wholeblood Haematology</TubeName>
<RegisterHour>09 PM</RegisterHour>
<Total>4</Total>
</Record>
<Record>
<TubeName>Chemistry Serum</TubeName>
<RegisterHour>10 PM</RegisterHour>
<Total>11</Total>
</Record>
<Record>
<TubeName>Wholeblood Haematology</TubeName>
<RegisterHour>10 PM</RegisterHour>
<Total>11</Total>
</Record>
<Record>
<TubeName>Chemistry Wholeblood</TubeName>
<RegisterHour>10 PM</RegisterHour>
<Total>1</Total>
</Record>
<Record>
<TubeName>Wholeblood Haematology</TubeName>
<RegisterHour>11 PM</RegisterHour>
<Total>2</Total>
</Record>
<Record>
<TubeName>Chemistry Serum</TubeName>
<RegisterHour>11 PM</RegisterHour>
<Total>3</Total>
</Record>
<Record>
<TubeName>Chemistry Wholeblood</TubeName>
<RegisterHour>11 PM</RegisterHour>
<Total>1</Total>
</Record>
</Records>
XSLT
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="key-tube" match="Record" use="TubeName"/>
<xsl:key name="key-hour" match="Record" use="RegisterHour"/>
<xsl:key name="key-tube-hour" match="Record" use="concat(TubeName,'::',RegisterHour)"/>
<xsl:key name="key-hour-list" match="RegisterHour" use="."/>
<xsl:key name="key-tube-list" match="TubeName" use="."/>
<!--<xsl:variable name="unique-hour-list" select="//RegisterHour[generate-id() = generate-id(key('key-hour-list', .)[1])]"/>-->
<xsl:variable name="unique-tube-list" select="//TubeName[generate-id() = generate-id(key('key-tube-list', .)[1])]"/>
<!--Hour Array -->
<xsl:variable name="hours">
<hour>01 AM</hour>
<hour>02 AM</hour>
<hour>03 AM</hour>
<hour>04 AM</hour>
<hour>05 AM</hour>
<hour>06 AM</hour>
<hour>07 AM</hour>
<hour>08 AM</hour>
<hour>09 AM</hour>
<hour>10 AM</hour>
<hour>11 AM</hour>
<hour>12 AM</hour>
<hour>01 PM</hour>
<hour>02 PM</hour>
<hour>03 PM</hour>
<hour>04 PM</hour>
<hour>05 PM</hour>
<hour>06 PM</hour>
<hour>07 PM</hour>
<hour>08 PM</hour>
<hour>09 PM</hour>
<hour>10 PM</hour>
<hour>11 PM</hour>
<hour>12 PM</hour>
</xsl:variable>
<xsl:variable name="hour-array" select="exsl:node-set($hours)" xmlns:exsl="http://exslt.org/common"/>
<xsl:template match="/Records">
<html>
<head>
<title>
<xsl:value-of select="/Records/#reportTitle"/>_<xsl:value-of select="/Records/vars/date"/>
</title>
<style>
body { font-family: monospace; }
table { border-collapse: collapse; font-size: 8pt; width: 100%; }
td,th { padding: 3px; border: 1px solid gainsboro;}
th.day { width: 25px; }
h1,h2,h3,h4,h5 { margin: 0 0 5px 0; }
h3 { color: gray; }
thead,tfoot { background-color: whitesmoke; }
tbody th,
tbody td { text-align: right; }
tbody td.test { text-align: left; }
tbody td.area { text-align: left; font-weight: bold; text-decoration: underline; }
img.logo { float: right; width: 70px; }
header { clear:both; margin-bottom: 10px; border-bottom: 1px solid gray; padding-bottom: 10px;}
tfoot th { text-align:right;}
.red-10 {background-color: #F3DFDB}
.red-30 {background-color: #F1C8BF}
.red-50 {background-color: #EE8873}
.red-70 {background-color: #EF6E53}
.red-90 {background-color: #EB411E}
</style>
</head>
<body>
<h1><xsl:value-of select="/Records/#reportTitle"/></h1>
<h3><xsl:value-of select="/Records/vars/date"/> </h3>
<table>
<thead>
<tr>
<th style="text-align:left">Time of Day</th>
<xsl:apply-templates select="$unique-tube-list" mode="day-list"/>
<th>Total</th>
</tr>
</thead>
<tbody>
<xsl:apply-templates select="$hour-array" mode="test-list"/>
</tbody>
<tfoot>
<tr>
<th>Totals</th>
<xsl:apply-templates select="$unique-tube-list" mode="day-totals"/>
<th>
<xsl:value-of select="format-number(sum(Record/Total),'###,###')" />
</th>
</tr>
</tfoot>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="TubeName" mode="day-list">
<th class="day"><xsl:value-of select="."/></th>
</xsl:template>
<xsl:template match="TubeName" mode="day-totals">
<th><xsl:value-of select="format-number(sum(key('key-tube',.)/Total),'###,###')"/></th>
</xsl:template>
<xsl:template match="hour" mode="test-list">
<xsl:variable name="h" select="."/>
<xsl:variable name="grand-total" select="sum(/Records/Record/Total)" />
<xsl:variable name="row-total" select="sum(key('key-hour',.)/Total)" />
<xsl:variable name="pct" select="($row-total div $grand-total)*100" />
<tr>
<xsl:choose>
<xsl:when test="$pct > 50">
<xsl:attribute name="class">red-90</xsl:attribute>
</xsl:when>
<xsl:when test="$pct > 40">
<xsl:attribute name="class">red-70</xsl:attribute>
</xsl:when>
<xsl:when test="$pct > 30">
<xsl:attribute name="class">red-50</xsl:attribute>
</xsl:when>
<xsl:when test="$pct > 20">
<xsl:attribute name="class">red-30</xsl:attribute>
</xsl:when>
<xsl:when test="$pct > 10">
<xsl:attribute name="class">red-10</xsl:attribute>
</xsl:when>
</xsl:choose>
<td class="test">
<xsl:value-of select="$h"/> (<xsl:value-of select="key('key-hour',$h)"/>)
</td>
<xsl:for-each select="$unique-tube-list">
<xsl:variable name="total" select="key('key-tube-hour',concat(current(),'::',$h))/Total"/>
<xsl:choose>
<xsl:when test="$total">
<td><xsl:value-of select="format-number($total,'###,###')" /></td>
</xsl:when>
<xsl:otherwise>
<td>0</td>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<td>
<xsl:value-of select="format-number(sum(key('key-hour',$h)/Total),'###,###')" />
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
This results in the total column not been populated with the actual sum of totals. Here is what that looks like.
Here is a fiddle of the result for you to play with.
https://xsltfiddle.liberty-development.net/pNvtBGk

I would suggest to change the context by doing
<xsl:template match="hour" mode="test-list">
<xsl:apply-templates select="$main-doc" mode="test-list">
<xsl:with-param name="h" select="."/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="/" mode="test-list">
<xsl:param name="h"/>
<xsl:variable name="grand-total" select="sum(/Records/Record/Total)" />
<xsl:variable name="row-total" select="sum(key('key-hour', $h)/Total)" />
<xsl:variable name="pct" select="($row-total div $grand-total)*100" />
<tr>
<xsl:choose>
<xsl:when test="$pct > 50">
<xsl:attribute name="class">red-90</xsl:attribute>
</xsl:when>
<xsl:when test="$pct > 40">
<xsl:attribute name="class">red-70</xsl:attribute>
</xsl:when>
<xsl:when test="$pct > 30">
<xsl:attribute name="class">red-50</xsl:attribute>
</xsl:when>
<xsl:when test="$pct > 20">
<xsl:attribute name="class">red-30</xsl:attribute>
</xsl:when>
<xsl:when test="$pct > 10">
<xsl:attribute name="class">red-10</xsl:attribute>
</xsl:when>
</xsl:choose>
<td class="test">
<xsl:value-of select="$h"/> (<xsl:value-of select="key('key-hour',$h)"/>)
</td>
<xsl:for-each select="$unique-tube-list">
<xsl:variable name="total" select="key('key-tube-hour',concat(current(),'::',$h))/Total"/>
<xsl:choose>
<xsl:when test="$total">
<td><xsl:value-of select="format-number($total,'###,###')" /></td>
</xsl:when>
<xsl:otherwise>
<td>0</td>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<td>
<xsl:value-of select="format-number(sum(key('key-hour',$h)/Total),'###,###')" />
</td>
</tr>
</xsl:template>
Needs <xsl:variable name="main-doc" select="/"/> and where you process the hours change the apply-templates to <xsl:apply-templates select="$hour-array/hour" mode="test-list"/>
https://xsltfiddle.liberty-development.net/pNvtBGk/2

Related

How to get duplicate record as single record in xslt

I am struggling to get desired output result in xslt:
I want something Like I have 2 records in each records i have multiple child node I have to check if the child element values are duplicated in one record or not if yes i should only create 1 record with respect to duplicate record and remaining records for unique ones,
My input file looks like:
<Records count="2">
<Record id="parentRecord">
<Record id="childRecord1">
<Record id="childRecord2">
<Field id="childRecord2Field">Technology Asset Management</Field>
</Record>
</Record>
<Record id="childRecord1">
<Record id="childRecord2">
<Field id="childRecord2Field1">Inadequate Information Security Practices</Field>
</Record>
</Record>
<Record id="childRecord1">
<Record id="childRecord2">
<Field id="childRecord2Field1">Inadequate Information Security Practices</Field>
</Record>
</Record>
</Record>
<Record id="parentRecord">
<Record id="childRecord1">
<Record id="childRecord2">
<Field id="childRecord2Field">Technology Asset Management</Field>
</Record>
</Record>
<Record id="childRecord1">
<Record id="childRecord2">
<Field id="childRecord2Field1">Inadequate Information Security Practices</Field>
</Record>
</Record>
<Record id="childRecord1">
<Record id="childRecord2">
<Field id="childRecord2Field">Technology Asset Management</Field>
</Record>
</Record>
</Record>
</Records>
I am Expecting :
<Records>
<Record id="parentRecord">
<Record id="childRecord1">
<Record id="childRecord2">
<Field id="childRecord2Field">Technology Asset Management</Field>
</Record>
</Record>
<Record id="childRecord1">
<Record id="childRecord2">
<Field id="childRecord2Field1">Inadequate Information Security Practices</Field>
</Record>
</Record>
</Record>
<Record id="parentRecord">
<Record id="childRecord1">
<Record id="childRecord2">
<Field id="childRecord2Field">Technology Asset Management</Field>
</Record>
</Record>
<Record id="childRecord1">
<Record id="childRecord2">
<Field id="childRecord2Field1">Inadequate Information Security Practices</Field>
</Record>
</Record>
</Records>
Here is my xslt:
<xsl:template match="Records">
<Records>
<xsl:for-each select="Record[id='parentRecord']">
<xsl:variable name="MatchedChildRecord2Value" select="Record/Record/Field[id='childRecord2Field']"> //I am trying to store all the field values in paraent node
<xsl:for-each select="Record/Record/Field[id=childRecord2']/">
<xsl:choose>
<xsl:when test=".=$MatchedChildRecord2Value">
//Nothing I am doing
</xsl:when>
<xsl:otherwise>
<Record>
<Record id="childRecord1">
<Record id="childRecord2">
<Field>FieldRecordvalue</Field>
</Record>
</Record>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:for-each>
</Records>
</xsl:template>
Could you please help me out
I've tried it this way with XSLT3. I don't get the same result as what you indicated that you wanted, but I don't understand your result as there are duplicates within your result.
I've added an additional attribute count in order to show how many duplicates were folded into the result.
I get this result:
<Records>
<Record id="parentRecord" count="2">
<Record id="childRecord1" count="6">
<Record id="childRecord2" count="6">
<Field id="childRecord2Field" count="3">Technology Asset Management</Field>
<Field id="childRecord2Field1" count="3">Inadequate Information Security Practices</Field>
</Record>
</Record>
</Record>
</Records>
using this xslt3 stylesheet:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
expand-text="yes">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:output indent="yes" />
<xsl:template match="/Records">
<xsl:copy >
<xsl:call-template name="groupRecords" >
<xsl:with-param name="currentGroup" select="Record" />
</xsl:call-template >
</xsl:copy>
</xsl:template>
<xsl:template name="groupRecords" >
<xsl:param name="currentGroup" as="element()*" />
<xsl:for-each-group select="$currentGroup/self::Record" group-by="#id" >
<Record id="{current-grouping-key()}" count="{count(current-group())}" >
<xsl:call-template name="groupRecords" >
<xsl:with-param name="currentGroup" select="current-group()/*" />
</xsl:call-template>
</Record>
</xsl:for-each-group>
<xsl:for-each-group select="$currentGroup/self::Field" group-by="concat(#id, '##', text())" >
<Field id="{current-group()[1]/#id}" count="{count(current-group())}">{(current-group()/text())[1]}</Field>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>

How to resolve Group and Sort withing XSLT

I have the following input message where the data needs to be grouped based on 'EmpNo' and 'Date' first. But the result should be taken from the latest date time from field 'lastDateTime'
Input XML:
<Record>
<Record>
<Date>2019-04-01T00:00:00.000</Date>
<Hours>3</Hours>
<EmpNo>825</EmpNo>
<lastDateTime>2019-04-12T08:35:38.000</lastDateTime>
<Rate>1139</Rate>
<Code>102486</Code>
</Record>
<Record>
<Date>2019-04-01T00:00:00.000</Date>
<Hours>4</Hours>
<EmpNo>826</EmpNo>
<lastDateTime>2019-04-12T08:35:38.000</lastDateTime>
<Rate>1139</Rate>
<Code>102486</Code>
</Record>
<Record>
<Date>2019-04-01T00:00:00.000</Date>
<Hours>5</Hours>
<EmpNo>827</EmpNo>
<lastDateTime>2019-04-12T08:35:38.000</lastDateTime>
<Rate>1139</Rate>
<Code>102486</Code>
</Record>
<Record>
<Date>2019-04-01T00:00:00.000</Date>
<Hours>3</Hours>
<EmpNo>825</EmpNo>
<lastDateTime>2019-04-14T08:35:38.000</lastDateTime>
<Rate>1139</Rate>
<Code>102486</Code>
</Record>
<Record>
<Date>2019-04-01T00:00:00.000</Date>
<Hours>4</Hours>
<EmpNo>826</EmpNo>
<lastDateTime>2019-04-10T08:35:38.000</lastDateTime>
<Rate>1139</Rate>
<Code>102486</Code>
</Record>
<Record>
<Date>2019-04-01T00:00:00.000</Date>
<Hours>5</Hours>
<EmpNo>827</EmpNo>
<lastDateTime>2019-04-12T08:35:38.000</lastDateTime>
<Rate>1139</Rate>
<Code>102486</Code>
</Record>
<Record>
<Date>2019-04-01T00:00:00.000</Date>
<Hours>3</Hours>
<EmpNo>825</EmpNo>
<lastDateTime>2019-04-10T08:35:38.000</lastDateTime>
<Rate>1139</Rate>
<Code>102486</Code>
</Record>
<Record>
<Date>2019-04-01T00:00:00.000</Date>
<Hours>4</Hours>
<EmpNo>826</EmpNo>
<lastDateTime>2019-04-11T08:35:38.000</lastDateTime>
<Rate>1139</Rate>
<Code>102486</Code>
</Record>
<Record>
<Date>2019-04-01T00:00:00.000</Date>
<Hours>5</Hours>
<EmpNo>827</EmpNo>
<lastDateTime>2019-04-16T08:35:38.000</lastDateTime>
<Rate>1139</Rate>
<Code>102486</Code>
</Record>
</Record>
There could be many EmpNo with different Dates as well in the Input XML file. This needs to be grouped but it requires to extract only that particular node where lastDateTime is the latest.
Expected Result:
<Record>
<Record>
<Date>2019-04-01T00:00:00.000</Date>
<Hours>6</Hours>
<EmpNo>825</EmpNo>
<lastDateTime>2019-04-14T08:35:38.000</lastDateTime>
<Rate>1142</Rate>
<Code>13</Code>
</Record>
<Record>
<Date>2019-04-01T00:00:00.000</Date>
<Hours>4</Hours>
<EmpNo>826</EmpNo>
<lastDateTime>2019-04-12T08:35:38.000</lastDateTime>
<Rate>1140</Rate>
<Code>11</Code>
</Record>
<Record>
<Date>2019-04-01T00:00:00.000</Date>
<Hours>11</Hours>
<EmpNo>827</EmpNo>
<lastDateTime>2019-04-16T08:35:38.000</lastDateTime>
<Rate>1147</Rate>
<Code>18</Code>
</Record>
</Record>
I tried to write the following code but no luck.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:mf="http://example.com/mf" exclude-result-prefixes="#all" version="2.0">
<xsl:output method="xml" encoding="utf-8" indent="no"/>
<xsl:template match="Record">
<xsl:copy>
<xsl:for-each-group select="Record" group-by="EmpNo">
<xsl:for-each-group select="current-group()" group-by="Date">
<xsl:copy>
<EmpNo>
<xsl:value-of select="EmpNo"/>
</EmpNo>
<Date>
<xsl:value-of select="Date"/>
</Date>
<lastDateTime>
<xsl:value-of select="max(current-group()/lastDateTime/xs:dateTime(.))"/>
</lastDateTime>
<Hours>
<xsl:value-of select="Hours[Date=max(current-group()/lastDateTime/xs:dateTime(.))]"/>
</Hours>
</xsl:copy>
</xsl:for-each-group>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:transform>
Based on your description I think you want
<xsl:template match="Record">
<xsl:copy>
<xsl:for-each-group select="Record" group-by="EmpNo">
<xsl:for-each-group select="current-group()" group-by="Date">
<xsl:for-each select="current-group()">
<xsl:sort select="xs:dateTime(lastDateTime)"/>
<xsl:if test="position() = last()">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:for-each>
</xsl:for-each-group>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
However, result at https://xsltfiddle.liberty-development.net/ncdD7mB is
<Record>
<Record>
<Date>2019-04-01T00:00:00.000</Date>
<Hours>3</Hours>
<EmpNo>825</EmpNo>
<lastDateTime>2019-04-14T08:35:38.000</lastDateTime>
<Rate>1139</Rate>
<Code>102486</Code>
</Record>
<Record>
<Date>2019-04-01T00:00:00.000</Date>
<Hours>4</Hours>
<EmpNo>826</EmpNo>
<lastDateTime>2019-04-12T08:35:38.000</lastDateTime>
<Rate>1139</Rate>
<Code>102486</Code>
</Record>
<Record>
<Date>2019-04-01T00:00:00.000</Date>
<Hours>5</Hours>
<EmpNo>827</EmpNo>
<lastDateTime>2019-04-16T08:35:38.000</lastDateTime>
<Rate>1139</Rate>
<Code>102486</Code>
</Record>
</Record>
I am not sure from which item in a group you want to take the not grouped child elements.

More XSL Grouping - how to remove parent nodes with duplicate child attributes?

Yes, this is another XSLT grouping/duplicates questions, but I was unable to find any answers that I could successfully apply to my situation.
This is the original XML:
<data jsxid="jsxroot">
<record jsxid="10" groupNum="1319" item="q123" total="1"/>
<record jsxid="20" groupNum="1319" item="w123" total="1"/>
<record jsxid="30" groupNum="1319" item="" total="0"/>
<record jsxid="40" groupNum="1322" item="z123" total="1"/>
<record jsxid="50" groupNum="1322" item="x123" total="1"/>
<record jsxid="60" groupNum="1322" item="c123" total="1"/>
<record jsxid="70" groupNum="1322" item="" total="0"/>
<record jsxid="80" groupNum="1323" item="x123" total="1"/>
<record jsxid="90" groupNum="1323" item="c123" total="1"/>
<record jsxid="100" groupNum="1323" item="z123" total="1"/>
<record jsxid="110" groupNum="1323" item="" total="0"/>
</data>
First, I need it grouped by attribute "groupNum" and wrapped in a parent element jsxid that increments with each group, so that the output looks like this:
<data jsxid="jsxroot">
<record jsxid="1">
<record jsxid="10" groupNum="1319" item="q123" total="1"/>
<record jsxid="20" groupNum="1319" item="w123" total="1"/>
<record jsxid="30" groupNum="1319" item="" total="0"/>
</record>
<record jsxid="2">
<record jsxid="40" groupNum="1322" item="z123" total="1"/>
<record jsxid="50" groupNum="1322" item="x123" total="1"/>
<record jsxid="60" groupNum="1322" item="c123" total="1"/>
<record jsxid="70" groupNum="1322" item="" total="0"/>
</record>
<record jsxid="3">
<record jsxid="80" groupNum="1323" item="x123" total="1"/>
<record jsxid="90" groupNum="1323" item="c123" total="1"/>
<record jsxid="100" groupNum="1323" item="z123" total="1"/>
<record jsxid="110" groupNum="1323" item="" total="0"/>
</record>
</data>
I was able to accomplish that with this stylesheet:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:key name="groupNum" match="data/*" use="#groupNum" />
<xsl:template match="data">
<data>
<xsl:apply-templates select="*[generate-id(.)=generate-id(key('groupNum',#groupNum)[1])]"/>
</data>
</xsl:template>
<xsl:template match="*">
<record jsxid="{position()}" >
<xsl:copy-of select="key('groupNum', #groupNum)" />
</record>
</xsl:template>
</xsl:stylesheet>
Now I need to remove any grouping that contains the exact same items as another grouping for records where total = "1". If you look at the groupings of jsxid = 2 and jsxid = 3 above, you'll see that they both contain the following item attributes, though not in the same order:
item="x123"
item="c123"
item="z123"
So I want to remove the entire jsxid = 3 grouping and have the final output look like this:
<data jsxid="jsxroot">
<record jsxid="1">
<record jsxid="1" groupNum="1319" item="q123" total="1"/>
<record jsxid="2" groupNum="1319" item="w123" total="1"/>
<record jsxid="3" groupNum="1319" item="" total="0"/>
</record>
<record jsxid="2">
<record jsxid="4" groupNum="1322" item="z123" total="1"/>
<record jsxid="5" groupNum="1322" item="x123" total="1"/>
<record jsxid="6" groupNum="1322" item="c123" total="1"/>
<record jsxid="7" groupNum="1322" item="" total="0"/>
</record>
</data>
EDIT: Instead of removing the duplicate grouping, what if I wanted to add in a new attribute as a "grouping identifier." I'd call it something like "groupType" so the output for the above situation where the last two groupings are the same, they would have the same grouptype:
<data jsxid="jsxroot">
<record jsxid="1">
<record jsxid="10" groupNum="1319" item="q123" groupType = "type1" total="1"/>
<record jsxid="20" groupNum="1319" item="w123" groupType = "type1" total="1"/>
<record jsxid="30" groupNum="1319" item="" groupType = "type1" total="0"/>
</record>
<record jsxid="2">
<record jsxid="40" groupNum="1322" item="z123" groupType = "type2" total="1"/>
<record jsxid="50" groupNum="1322" item="x123" groupType = "type2" total="1"/>
<record jsxid="60" groupNum="1322" item="c123" groupType = "type2" total="1"/>
<record jsxid="70" groupNum="1322" item="" groupType = "type2" total="0"/>
</record>
<record jsxid="3">
<record jsxid="80" groupNum="1323" item="x123" groupType = "type2" total="1"/>
<record jsxid="90" groupNum="1323" item="c123" groupType = "type2" total="1"/>
<record jsxid="100" groupNum="1323" item="z123" groupType = "type2" total="1"/>
<record jsxid="110" groupNum="1323" item="" groupType = "type2" total="0"/>
</record>
</data>
Any help is greatly appreciated.
This is not going to be simple, so hang onto your seat:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:variable name="root" select="/" />
<xsl:key name="rec-by-group" match="record" use="#groupNum" />
<xsl:key name="group-by-items" match="group" use="#items" />
<xsl:template match="/">
<!-- first pass -->
<xsl:variable name="groups">
<!-- for each unique groupNum ... -->
<xsl:for-each select="data/record[count(. | key('rec-by-group', #groupNum)[1]) = 1]">
<xsl:variable name="groupNum" select="#groupNum" />
<!-- ... create a group ... -->
<group groupNum="{$groupNum}">
<!-- ... and concatenate all its items - in known order(!) - into a single attribute. -->
<xsl:attribute name="items">
<!-- switch context back to document in order to use key -->
<xsl:for-each select="$root">
<xsl:for-each select="key('rec-by-group', $groupNum)[#total=1]">
<xsl:sort select="#item" data-type="text" order="ascending"/>
<xsl:value-of select="#item"/>
<xsl:text>|</xsl:text>
</xsl:for-each>
</xsl:for-each>
</xsl:attribute>
</group>
</xsl:for-each>
</xsl:variable>
<!-- final pass -->
<data jsxid="jsxroot">
<!-- for each unique group (unique by its #items attribute) ... -->
<xsl:for-each select="exsl:node-set($groups)/group[count(. | key('group-by-items', #items)[1]) = 1]">
<!-- ... create a wrapper record ... -->
<record jsxid="{position()}">
<xsl:variable name="groupNum" select="#groupNum" />
<!-- switch context back to document in order to use key -->
<xsl:for-each select="$root">
<!-- ... and list the records in this group. -->
<xsl:for-each select="key('rec-by-group', $groupNum)">
<record>
<xsl:attribute name="jsxid">
<xsl:number/>
</xsl:attribute>
<xsl:copy-of select="#groupNum | #item | #total"/>
</record>
</xsl:for-each>
</xsl:for-each>
</record>
</xsl:for-each>
</data>
</xsl:template>
</xsl:stylesheet>
Edit:
in response to your edit:
If you can live with groupType being an arbitrary (though unique) number, you can change the "final pass" part to something like:
<!-- final pass -->
<data jsxid="jsxroot">
<!-- for each group ... -->
<xsl:for-each select="exsl:node-set($groups)/group">
<!-- ... create a wrapper record ... -->
<record jsxid="{position()}">
<xsl:variable name="groupNum" select="#groupNum" />
<xsl:variable name="groupType" select="key('group-by-items', #items)[1]/#groupNum" />
<!-- switch context back to document in order to use key -->
<xsl:for-each select="$root">
<!-- ... and list the records in this group. -->
<xsl:for-each select="key('rec-by-group', $groupNum)">
<record groupType="{$groupType}">
<xsl:attribute name="jsxid">
<xsl:number/>
</xsl:attribute>
<xsl:copy-of select="#groupNum | #item | #total"/>
</record>
</xsl:for-each>
</xsl:for-each>
</record>
</xsl:for-each>
</data>
Using your input example, this would return:
<?xml version="1.0" encoding="UTF-8"?>
<data jsxid="jsxroot">
<record jsxid="1">
<record groupType="1319" jsxid="1" groupNum="1319" item="q123" total="1"/>
<record groupType="1319" jsxid="2" groupNum="1319" item="w123" total="1"/>
<record groupType="1319" jsxid="3" groupNum="1319" item="" total="0"/>
</record>
<record jsxid="2">
<record groupType="1322" jsxid="4" groupNum="1322" item="z123" total="1"/>
<record groupType="1322" jsxid="5" groupNum="1322" item="x123" total="1"/>
<record groupType="1322" jsxid="6" groupNum="1322" item="c123" total="1"/>
<record groupType="1322" jsxid="7" groupNum="1322" item="" total="0"/>
</record>
<record jsxid="3">
<record groupType="1322" jsxid="8" groupNum="1323" item="x123" total="1"/>
<record groupType="1322" jsxid="9" groupNum="1323" item="c123" total="1"/>
<record groupType="1322" jsxid="10" groupNum="1323" item="z123" total="1"/>
<record groupType="1322" jsxid="11" groupNum="1323" item="" total="0"/>
</record>
</data>
As you can see, it uses the groupNum of the first group of the current type as the groupType value. Alternatively, you could also use the auto-generated id of that group:
<xsl:variable name="groupType" select="generate-id(key('group-by-items', #items)[1])" />.
To only copy the first instance, When generating each item, enclose it in a condition using count(preceding-sibling::*[]) = 0.
<xsl:template match="record">
<xsl:variable name="item" select="item"/>
<record jsxid="{position()}" >
<xsl:if test="count (preceding-sibling::*[item=$item])=0">
<xsl:copy-of select="key('groupNum', #groupNum)" />
</xsl:if>
</record>
</xsl:template>

Need some help converting an XML with XSLT 1.0

Need some help regarding the XSLT transformation of a flat file schema. Is it possible to combine the direct children of the Record node into one containing Record node? Child 512 is required and has min and max occurrence of 1 and marks the beginning of a new Record node.
Input:
<ns0:Root xmlns="">
<Header>
<node01>AA</node01>
<node02>123</node02>
</Header>
<Record>
<512>
<node01>BB</node01>
<node02>123</node02>
</512>
</Record>
<Record>
<513>
<node01>CC</node01>
<node02>123</node02>
</513>
</Record>
<Record>
<512>
<node01>DD</node01>
<node02>123</node02>
</512>
</Record>
<Record>
<515>
<node01>JJ</node01>
<node02>123</node02>
</515>
</Record>
<Record>
<512>
<node01>EE</node01>
<node02>123</node02>
</512>
</Record>
<Record>
<513>
<node01>FF</node01>
<node02>123</node02>
</513>
</Record>
<Record>
<514>
<node01>GG</node01>
<node02>123</node02>
</514>
<514>
<node01>HH</node01>
<node02>123</node02>
</514>
</Record>
<Footer>
<node01>II</node01>
<node02>123</node02>
</Footer>
</ns0:Root>
Desired Output:
<ns0:Root xmlns="">
<Header>
<item01>AA</item01>
<item02>123</item02>
</Header>
<Record>
<512>
<item01>BB</item01>
<item02>123</item02>
</512>
<513>
<item01>CC</item01>
<item02>123</item02>
</513>
</Record>
<Record>
<512>
<item01>DD</item01>
<item02>123</item02>
</512>
<515>
<item01>JJ</item01>
<item02>123</item02>
</515>
</Record>
<Record>
<512>
<item01>EE</item01>
<item02>123</item02>
</512>
<513>
<item01>FF</item01>
<item02>123</item02>
</513>
<514>
<item01>GG</item01>
<item02>123</item02>
</514>
<514>
<item01>HH</item01>
<item02>123</item02>
</514>
</Record>
<Footer>
<item01>II</item01>
<item02>123</item02>
</Footer>
</ns0:Root>
Thank you and kind regards
Philipp
P.S.: XSLT 2.0 is not available.
That's not legal XML (element names can't start with numbers), but supposing you renamed all the invalid elements to start with "r", you can do the following:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*" />
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Record[r512]">
<xsl:copy>
<xsl:apply-templates select="." mode="iterate" />
</xsl:copy>
</xsl:template>
<xsl:template match="Record" />
<xsl:template match="Record" mode="iterate">
<xsl:apply-templates />
<xsl:apply-templates select="following-sibling::Record[1][not(r512)]"
mode="iterate"/>
</xsl:template>
</xsl:stylesheet>
When run on this input:
<ns0:Root xmlns="" xmlns:ns0="nsss">
<Header>
<node01>AA</node01>
<node02>123</node02>
</Header>
<Record>
<r512>
<node01>BB</node01>
<node02>123</node02>
</r512>
</Record>
<Record>
<r513>
<node01>CC</node01>
<node02>123</node02>
</r513>
</Record>
<Record>
<r512>
<node01>DD</node01>
<node02>123</node02>
</r512>
</Record>
<Record>
<r515>
<node01>JJ</node01>
<node02>123</node02>
</r515>
</Record>
<Record>
<r512>
<node01>EE</node01>
<node02>123</node02>
</r512>
</Record>
<Record>
<r513>
<node01>FF</node01>
<node02>123</node02>
</r513>
</Record>
<Record>
<r514>
<node01>GG</node01>
<node02>123</node02>
</r514>
<r514>
<node01>HH</node01>
<node02>123</node02>
</r514>
</Record>
<Footer>
<node01>II</node01>
<node02>123</node02>
</Footer>
</ns0:Root>
Produces:
<ns0:Root xmlns:ns0="nsss">
<Header>
<node01>AA</node01>
<node02>123</node02>
</Header>
<Record>
<r512>
<node01>BB</node01>
<node02>123</node02>
</r512>
<r513>
<node01>CC</node01>
<node02>123</node02>
</r513>
</Record>
<Record>
<r512>
<node01>DD</node01>
<node02>123</node02>
</r512>
<r515>
<node01>JJ</node01>
<node02>123</node02>
</r515>
</Record>
<Record>
<r512>
<node01>EE</node01>
<node02>123</node02>
</r512>
<r513>
<node01>FF</node01>
<node02>123</node02>
</r513>
<r514>
<node01>GG</node01>
<node02>123</node02>
</r514>
<r514>
<node01>HH</node01>
<node02>123</node02>
</r514>
</Record>
<Footer>
<node01>II</node01>
<node02>123</node02>
</Footer>
</ns0:Root>

Implementing bit tricky logic in xslt 1.0 transformation

I am finding bit difficulty to implement following logic while doing transformation using xslt 1.0.
Here is my requirement:
I need to define following logic on hours worked by an employee.
1. anything over 8 will be OT else Regular in a day.
2. if worked continuously for 3 days then 3rd day hours would be double time.
Here is an example:
Input:
<Input>
<Record>
<EmpId>1</EmpId>
<Date></Date>
<Hours></Hours>
</Record>
<Record>
<EmpId>1</EmpId>
<Date>12/1/2012</Date>
<Hours>6</Hours>
</Record>
<Record>
<EmpId>1</EmpId>
<Date>12/1/2012</Date>
<Hours>4</Hours>
</Record>
<Record>
<EmpId>1</EmpId>
<Date>12/2/2012</Date>
<Hours>4</Hours>
</Record>
<Record>
<EmpId>1</EmpId>
<Date>12/2/2012</Date>
<Hours></Hours>
</Record>
<Record>
<EmpId>1</EmpId>
<Date>12/3/2012</Date>
<Hours>3</Hours>
</Record>
<Record>
<EmpId>2</EmpId>
<Date>12/1/2012</Date>
<Hours>4</Hours>
</Record>
<Record>
<EmpId>2</EmpId>
<Date>12/1/2012</Date>
<Hours></Hours>
</Record>
</Input>
Output:
<Output>
<Record>
<EmployeeId>1</EmployeeId>
<Detail>
<Date>12/1/2012</Date>
<RegHours>8</Reghours>
<OTHours>2</OTHours>
</Detail>
<Detail>
<Date>12/2/2012</Date>
<RegHours>4</Reghours>
</Detail>
<Detail>
<Date>12/3/2012</Date>
<DTHours>3</DThours>
</Detail>
</Record>
<Record>
<EmployeeId>2</EmployeeId>
<Detail>
<Date>12/1/2012</Date>
<RegHours>4</Reghours>
</Detail>
<Detail>
</Record>
</Output>
Would appreciate for any help.
Thanks..
Abhi
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:strip-space elements="*"/>
<xsl:key name="kRecByEmpId" match="Record[Date/node() and Hours/node()]"
use="EmpId"/>
<xsl:key name="kRecByEmpIdDate" match="Record[Date/node() and Hours/node()]"
use="concat(EmpId,'+',Date)"/>
<xsl:template match=
"Record[generate-id()=generate-id(key('kRecByEmpId',EmpId)[1])]">
<Record>
<EmployeeId>
<xsl:value-of select="EmpId"/>
</EmployeeId>
<xsl:apply-templates mode="datetime" select=
"key('kRecByEmpId', EmpId)
[generate-id()
=
generate-id(key('kRecByEmpIdDate',
concat(EmpId,'+',Date)
)[1]
)
]
"/>
</Record>
</xsl:template>
<xsl:template match="Record" mode="datetime">
<Detail>
<xsl:copy-of select="Date"/>
<xsl:variable name="vTotal" select=
"sum(key('kRecByEmpIdDate', concat(EmpId,'+',Date))/Hours)"/>
<RegHours>
<xsl:value-of select="8*($vTotal >= 8) + $vTotal*(not($vTotal >= 8))"/>
</RegHours>
<xsl:if test="$vTotal > 8">
<OTHours>
<xsl:value-of select="$vTotal -8"/>
</OTHours>
</xsl:if>
</Detail>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
when applied on the provided XML document:
<Input>
<Record>
<EmpId>1</EmpId>
<Date></Date>
<Hours></Hours>
</Record>
<Record>
<EmpId>1</EmpId>
<Date>12/1/2012</Date>
<Hours>6</Hours>
</Record>
<Record>
<EmpId>1</EmpId>
<Date>12/1/2012</Date>
<Hours>4</Hours>
</Record>
<Record>
<EmpId>1</EmpId>
<Date>12/2/2012</Date>
<Hours>4</Hours>
</Record>
<Record>
<EmpId>1</EmpId>
<Date>12/2/2012</Date>
<Hours></Hours>
</Record>
<Record>
<EmpId>1</EmpId>
<Date>12/3/2012</Date>
<Hours>3</Hours>
</Record>
<Record>
<EmpId>2</EmpId>
<Date>12/1/2012</Date>
<Hours>4</Hours>
</Record>
<Record>
<EmpId>2</EmpId>
<Date>12/1/2012</Date>
<Hours></Hours>
</Record>
</Input>
produces the wanted, correct result:
<Record>
<EmployeeId>1</EmployeeId>
<Detail>
<Date>12/1/2012</Date>
<RegHours>8</RegHours>
<OTHours>2</OTHours>
</Detail>
<Detail>
<Date>12/2/2012</Date>
<RegHours>4</RegHours>
</Detail>
<Detail>
<Date>12/3/2012</Date>
<RegHours>3</RegHours>
</Detail>
</Record>
<Record>
<EmployeeId>2</EmployeeId>
<Detail>
<Date>12/1/2012</Date>
<RegHours>4</RegHours>
</Detail>
</Record>