user1905354
user1905354

Reputation: 39

Tricky grouping using xslt 1.0

I need to do a bit tricky mapping using xslt 1.0. need to do grouping only on the date part of the datetime element. However the element contains the both date and time.Also after grouping need to add the hours.

Here is the input:

<Records>
   <Record>
      <empid>1</empid>
      <datetime>10/10/2010 11:11:00 AM</datetime>
      <hours>5</hours>
    </Record>
    <Record>            
      <empid>1</empid>
      <datetime>10/10/2010 10:11:00 AM</datetime>
      <hours>5</hours>
    </Record>
    <Record>   
      <empid>1</empid>           
      <datetime>10/11/2010 11:11:00 AM</datetime>
      <hours>5</hours>
    </Record>
    <Record>   
       <empid>2</empid>
       <datetime>10/10/2010 10:11:00 AM</datetime>
       <hours>2</hours>
    </Record>
    <Record> 
      <empid>2</empid>
      <datetime>10/10/2010 9:11:00 AM</datetime>
      <hours>5</hours>  
     </Record>    
  </Records>   

Expected output is:

  <Records>
      <Record>
       <empid>1</empid>
      <detail>     
         <date>10/10/2010</date>
         <hours>10</hours>
      </detail> 
     <detail>
        <date>10/11/2010</date>
        <hours>5</hours>
     </detail>
    </Record>
    <Record>
       <empid>2</empid>
       <detail>
          <date>10/10/2010</date>
          <hours>7</hours>
       </detail>
    </Record>
 </Records>

Appreciate for any help.

Upvotes: 1

Views: 117

Answers (1)

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243449

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="kRecById" match="Record" use="empid"/>
 <xsl:key name="kRecByDateId" match="Record"
          use="concat(empid,'+',substring-before(datetime, ' '))"/>

 <xsl:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match=
  "Record[generate-id()=generate-id(key('kRecById', empid)[1])]">
  <Record>
   <xsl:apply-templates select="empid"/>
   <xsl:apply-templates mode="inGroup" select=
    "key('kRecById', empid)
                [generate-id()
                =
                 generate-id(key('kRecByDateId',
                             concat(empid,'+',substring-before(datetime, ' ')))[1])]"/>
  </Record>
 </xsl:template>

 <xsl:template match="Record" mode="inGroup">
   <detail>
     <date><xsl:value-of select="substring-before(datetime, ' ')"/></date>
     <hours><xsl:value-of select=
     "sum(key('kRecByDateId',
              concat(empid,'+',substring-before(datetime, ' '))
              )/hours)"/>
     </hours>
   </detail>
 </xsl:template>
 <xsl:template match="Record"/>
</xsl:stylesheet>

when applied on the provided XML document:

<Records>
    <Record>
        <empid>1</empid>
        <datetime>10/10/2010 11:11:00 AM</datetime>
        <hours>5</hours>
    </Record>
    <Record>
        <empid>1</empid>
        <datetime>10/10/2010 10:11:00 AM</datetime>
        <hours>5</hours>
    </Record>
    <Record>
        <empid>1</empid>
        <datetime>10/11/2010 11:11:00 AM</datetime>
        <hours>5</hours>
    </Record>
    <Record>
        <empid>2</empid>
        <datetime>10/10/2010 10:11:00 AM</datetime>
        <hours>2</hours>
    </Record>
    <Record>
        <empid>2</empid>
        <datetime>10/10/2010 9:11:00 AM</datetime>
        <hours>5</hours>
    </Record>
</Records>

produces the wanted, correct result:

<Records>
   <Record>
      <empid>1</empid>
      <detail>
         <date>10/10/2010</date>
         <hours>10</hours>
      </detail>
      <detail>
         <date>10/11/2010</date>
         <hours>5</hours>
      </detail>
   </Record>
   <Record>
      <empid>2</empid>
      <detail>
         <date>10/10/2010</date>
         <hours>7</hours>
      </detail>
   </Record>
</Records>

Explanation:

Two nested Muenchian grouping s, the inner using a composite key.

Upvotes: 1

Related Questions