newbie using group by in XSL on XLM


S

shall

I want to have a grouping by action on this XLM.
=======================
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?xml-stylesheet type="text/xsl" href="Demo_xslt_Help.xsl"?>
<XML>
<Title>
<Planning_Unit>testA</Planning_Unit>
<ProgramName>it test</ProgramName>
<Time_Frame>May</Time_Frame>
</Title>
<Header>
<GOALNAME>Goal# 1 </GOALNAME>
</Header>
<Header_2>
<OBJNAME>Obj# 1 </OBJNAME>
</Header_2>
<Header_3 Total="Total" Female="Female" Male="Male"></Header_3>
<adetail>
<ATOTAL>76</ATOTAL>
<AFEM>17</AFEM>
<AMALE>59</AMALE>
<goalgroup>2011.1012.1.1</goalgroup>
</adetail>
<adetail>
<ATOTAL>599</ATOTAL>
<AFEM>229</AFEM>
<AMALE>370</AMALE>
<goalgroup>2011.1012.1.1</goalgroup>
</adetail>
<Header>
<GOALNAME>Goal# 4 </GOALNAME>
</Header>
<Header_2>
<OBJNAME>Obj# 3 </OBJNAME>
</Header_2>
<Header_3 Total="Total" Female="Female" Male="Male"></Header_3>
<adetail>
<ATOTAL>0</ATOTAL>
<AFEM>0</AFEM>
<AMALE>0</AMALE>
<goalgroup>2011.1012.4.3</goalgroup>
</adetail>
<adetail>
<ATOTAL>3</ATOTAL>
<AFEM>1</AFEM>
<AMALE>2</AMALE>
<goalgroup>2011.1012.4.3</goalgroup>
</adetail>
</XML>
===================================
<?xml version="1.0"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/
Transform">

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

<xsl:template match="child::Header">
<table>
<tr style="background-color:#ccff00">
<td><xsl:value-of select="GOALNAME"/></td>
</tr>
</table>
</xsl:template>
<xsl:template match="child::Header_2">
<table>
<tr style="background-color:#ccff00">
<td><xsl:value-of select="OBJNAME"/></td>
</tr>
</table>
</xsl:template>

<xsl:template match="child::Header_3">
<table>
<tr style="background-color:#ccff00">
<th>ATOTAL</th>
<th>DFEM</th>
<th>DMALE</th>
</tr>
<xsl:call-template name="ShowEmployeesInTeam">
</xsl:call-template>
</table>
</xsl:template>

<xsl:template name="ShowEmployeesInTeam">

<xsl:for-each-group select="XML/adetail" group-by="/../../
goalgroup">
<xsl:comment>
<xsl:value-of select="current-grouping-key()"/>
</xsl:comment>
<xsl:for-each select="current-group()">
<tr style="background-color:#cccccc">
<td><xsl:value-of select="ATOTAL"/></td>
<td><xsl:value-of select="AFEM"/></td>
<td><xsl:value-of select="AMALE"/></td>
</tr>
</xsl:for-each>
</xsl:for-each-group>

</xsl:template>
</xsl:stylesheet>
==============================
I have tried several options, but no success.
Below is what I would like for my output to look like:
===================================
<table>
<tr><td>Goal# 1</td></tr></table>
<table>
<tr><td>Obj# 1</td></tr></table>
<table>
<tr><th>Total</th><th>Female</th><th>Male</th></tr>
<tr><td>76</td><td>17</td><td>59</td></tr>
<tr><td>599</td><td>229</td><td>370</td></tr>
</table>
<table>
<tr><td>Goal# 4</td></tr></table>
<table>
<tr><td>Obj# 3</td></tr></table>
<table>
<tr><th>Total</th><th>Female</th><th>Male</th></tr>
<tr><td>0</td><td>0</td><td>0</td></tr>
<tr><td>3</td><td>1</td><td>2</td></tr>
</table>

=============================
Is this possible with XSL?

TIA
Steve
 
Ad

Advertisements

M

Martin Honnen

I want to have a grouping by action on this XLM.
=======================
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?xml-stylesheet type="text/xsl" href="Demo_xslt_Help.xsl"?>

Such an xml-stylesheet processing instruction is usally applied by a
browser when you load the XML document so that begs the question
<xsl:for-each-group select="XML/adetail" group-by="/../../
goalgroup">

Do you use an XSLT 2.0 processor (like Saxon 9 or AltovaXML Tools or
XQSharp) to run your XSLT stylesheet? Or do you use client-side XSLT in
the browser? That way you couldn't use for-each-group as browsers so far
support only XSLT 1.0 which does not have a for-each-group instruction.
 
M

Martin Honnen

Below is what I would like for my output to look like:
===================================
<table>
<tr><td>Goal# 1</td></tr></table>
<table>
<tr><td>Obj# 1</td></tr></table>
<table>
<tr><th>Total</th><th>Female</th><th>Male</th></tr>
<tr><td>76</td><td>17</td><td>59</td></tr>
<tr><td>599</td><td>229</td><td>370</td></tr>
</table>
<table>
<tr><td>Goal# 4</td></tr></table>
<table>
<tr><td>Obj# 3</td></tr></table>
<table>
<tr><th>Total</th><th>Female</th><th>Male</th></tr>
<tr><td>0</td><td>0</td><td>0</td></tr>
<tr><td>3</td><td>1</td><td>2</td></tr>
</table>

=============================
Is this possible with XSL?

Here is a sample XSLT 2.0 stylesheet (you could run with Saxon 9
(http://saxon.sourceforge.net/) or AltovaXML Tools
(http://www.altova.com/altovaxml.html) or XQSharp
(http://www.xqsharp.com/)):

<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">

<xsl:eek:utput method="html" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="XML">
<xsl:for-each-group select="* except Title"
group-starting-with="Header">
<xsl:apply-templates select="., current-group()[self::Header_2]"/>
<xsl:for-each-group select="current-group()[self::adetail]"
group-by="goalgroup">
<table>
<thead>
<tr>
<th>ATOTAL</th>
<th>DFEM</th>
<th>DEMALE</th>
</tr>
</thead>
<tbody>
<xsl:apply-templates select="current-group()"/>
</tbody>
</table>
</xsl:for-each-group>
</xsl:for-each-group>
</xsl:template>

<xsl:template match="Header">
<table>
<tbody>
<tr>
<td>
<xsl:value-of select="GOALNAME"/>
</td>
</tr>
</tbody>
</table>
</xsl:template>

<xsl:template match="Header_2">
<table>
<tbody>
<tr>
<td>
<xsl:value-of select="OBJNAME"/>
</td>
</tr>
</tbody>
</table>
</xsl:template>

<xsl:template match="adetail">
<tr>
<xsl:apply-templates/>
</tr>
</xsl:template>

<xsl:template match="adetail/ATOTAL | adetail/AFEM | adetail/AMALE">
<td>
<xsl:value-of select="."/>
</td>
</xsl:template>

<xsl:template match="adetail/goalgroup"/>

</xsl:stylesheet>

I am not sure the group-by="goalgroup" is needed for your sample input,
it seemed already grouped.
 
S

shall

No I do NOT use XSLT 2.0
I was just trying to use something after becoming frustrated with XSLT
1.0.




Below is what I would like for my output to look like:
===================================
<table>
<tr><td>Goal# 1</td></tr></table>
<table>
<tr><td>Obj# 1</td></tr></table>
<table>
<tr><th>Total</th><th>Female</th><th>Male</th></tr>
<tr><td>76</td><td>17</td><td>59</td></tr>
<tr><td>599</td><td>229</td><td>370</td></tr>
</table>
<table>
<tr><td>Goal# 4</td></tr></table>
<table>
<tr><td>Obj# 3</td></tr></table>
<table>
<tr><th>Total</th><th>Female</th><th>Male</th></tr>
<tr><td>0</td><td>0</td><td>0</td></tr>
<tr><td>3</td><td>1</td><td>2</td></tr>
</table>
=============================
Is this possible with XSL?

Here is a sample XSLT 2.0 stylesheet (you could run with Saxon 9
(http://saxon.sourceforge.net/) or AltovaXML Tools
(http://www.altova.com/altovaxml.html) or XQSharp
(http://www.xqsharp.com/)):

<xsl:stylesheet
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   xmlns:xs="http://www.w3.org/2001/XMLSchema"
   exclude-result-prefixes="xs"
   version="2.0">

   <xsl:eek:utput method="html" indent="yes"/>
   <xsl:strip-space elements="*"/>

   <xsl:template match="XML">
     <xsl:for-each-group select="* except Title"
group-starting-with="Header">
       <xsl:apply-templates select="., current-group()[self::Header_2]"/>
       <xsl:for-each-group select="current-group()[self::adetail]"
group-by="goalgroup">
         <table>
           <thead>
             <tr>
               <th>ATOTAL</th>
               <th>DFEM</th>
               <th>DEMALE</th>
             </tr>
           </thead>
           <tbody>
             <xsl:apply-templates select="current-group()"/>
           </tbody>
         </table>
       </xsl:for-each-group>
     </xsl:for-each-group>
   </xsl:template>

   <xsl:template match="Header">
     <table>
       <tbody>
         <tr>
           <td>
             <xsl:value-of select="GOALNAME"/>
           </td>
         </tr>
       </tbody>
     </table>
   </xsl:template>

   <xsl:template match="Header_2">
     <table>
       <tbody>
         <tr>
           <td>
             <xsl:value-of select="OBJNAME"/>
           </td>
         </tr>
       </tbody>
     </table>
   </xsl:template>

   <xsl:template match="adetail">
     <tr>
       <xsl:apply-templates/>
     </tr>
   </xsl:template>

   <xsl:template match="adetail/ATOTAL | adetail/AFEM | adetail/AMALE">
     <td>
       <xsl:value-of select="."/>
     </td>
   </xsl:template>

   <xsl:template match="adetail/goalgroup"/>

</xsl:stylesheet>

I am not sure the group-by="goalgroup" is needed for your sample input,
it seemed already grouped.

--

        Martin Honnen
       http://msmvps.com/blogs/martin_honnen/- Hide quoted text -

- Show quoted text -
 
S

shall

I must have copied the wrong version on the first post.
below is one with XSLT1.0
================================
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/
Transform">
<xsl:key name="goalkey" match="adetail" use="goalgroup" />

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

<xsl:template match="child::Header">
<table>
<tr style="background-color:#ccff00">
<td><xsl:value-of select="GOALNAME"/></td>
</tr>
</table>
</xsl:template>
<xsl:template match="child::Header_2">
<table>
<tr style="background-color:#cccc00">
<td><xsl:value-of select="OBJNAME"/></td>
</tr>
</table>
</xsl:template>


<xsl:template match="XML">


<xsl:text>Inside adetail</xsl:text>


<xsl:text>Before 2nd table =</xsl:text>
<xsl:for-each select="adetail[count(. | key('goalkey',goalgroup)[1]) =
1]">
<table>
<tr style="background-color:#ccff00">
<td><xsl:value-of select="GOALNAME"/></td>
</tr>
</table>

<table border="1">

<tr style="background-color:#ccff00">
<th>ATOTAL</th>
<th>DFEM</th>
<th>DMALE</th>
</tr>



<xsl:for-each select="key('goalkey', goalgroup)">
<xsl:variable name="lngGroupID">
<xsl:value-of select="goalgroup"/></xsl:variable>

<xsl:variable name="strGroupID" select="//adetail[groupgoal=
$lngGroupID]" />

<xsl:text>The groupID is =</xsl:text>
<xsl:value-of select="$strGroupID" />
<xsl:text>|</xsl:text>


<xsl:text>Before ROW 1</xsl:text>
<tr style="background-color:#cccccc">
<td><xsl:value-of select="ATOTAL" /></td>
<td><xsl:value-of select="AFEM" /></td>
<td><xsl:value-of select="AMALE" /></td>
</tr>

</xsl:for-each>
</table>

</xsl:for-each>
</xsl:template>


</xsl:stylesheet>



================================




No I do NOT use XSLT 2.0
I was just trying to use something after becoming frustrated with XSLT
1.0.

Here is a sample XSLT 2.0 stylesheet (you could run with Saxon 9
(http://saxon.sourceforge.net/) or AltovaXML Tools
(http://www.altova.com/altovaxml.html) or XQSharp
(http://www.xqsharp.com/)):
<xsl:stylesheet
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   xmlns:xs="http://www.w3.org/2001/XMLSchema"
   exclude-result-prefixes="xs"
   version="2.0">
   <xsl:eek:utput method="html" indent="yes"/>
   <xsl:strip-space elements="*"/>
   <xsl:template match="XML">
     <xsl:for-each-group select="* except Title"
group-starting-with="Header">
       <xsl:apply-templates select="., current-group()[self::Header_2]"/>
       <xsl:for-each-group select="current-group()[self::adetail]"
group-by="goalgroup">
         <table>
           <thead>
             <tr>
               <th>ATOTAL</th>
               <th>DFEM</th>
               <th>DEMALE</th>
             </tr>
           </thead>
           <tbody>
             <xsl:apply-templates select="current-group()"/>
           </tbody>
         </table>
       </xsl:for-each-group>
     </xsl:for-each-group>
   </xsl:template>
   <xsl:template match="Header">
     <table>
       <tbody>
         <tr>
           <td>
             <xsl:value-of select="GOALNAME"/>
           </td>
         </tr>
       </tbody>
     </table>
   </xsl:template>
   <xsl:template match="Header_2">
     <table>
       <tbody>
         <tr>
           <td>
             <xsl:value-of select="OBJNAME"/>
           </td>
         </tr>
       </tbody>
     </table>
   </xsl:template>
   <xsl:template match="adetail">
     <tr>
       <xsl:apply-templates/>
     </tr>
   </xsl:template>
   <xsl:template match="adetail/ATOTAL | adetail/AFEM | adetail/AMALE">
     <td>
       <xsl:value-of select="."/>
     </td>
   </xsl:template>
   <xsl:template match="adetail/goalgroup"/>

I am not sure the group-by="goalgroup" is needed for your sample input,
it seemed already grouped.

        Martin Honnen
       http://msmvps.com/blogs/martin_honnen/-Hide quoted text -
- Show quoted text -- Hide quoted text -

- Show quoted text -
 
M

Martin Honnen

No I do NOT use XSLT 2.0
I was just trying to use something after becoming frustrated with XSLT
1.0.

Well XSLT 2.0 processors do exist thus if XSLT 1.0 and Muenchian
grouping with keys frustrates you you could consider to try XSLT 2.0
with one of Saxon 9 (http://saxon.sourceforge.net/) or AltovaXML Tools
(http://www.altova.com/altovaxml.html) or XQSharp (http://www.xqsharp.com/).

Or have a look at this XSLT 1.0 stylesheet:

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

<xsl:eek:utput method="html" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="detail-by-group" match="adetail" use="goalgroup"/>

<xsl:template match="adetail[not(generate-id() =
generate-id(key('detail-by-group', goalgroup)[1]))]"/>

<xsl:template match="adetail[generate-id() =
generate-id(key('detail-by-group', goalgroup)[1])]">
<table>
<thead>
<tr>
<th>ATOTAL</th>
<th>DFEM</th>
<th>DEMALE</th>
</tr>
</thead>
<tbody>
<xsl:apply-templates select="key('detail-by-group', goalgroup)"
mode="row"/>
</tbody>
</table>
</xsl:template>

<xsl:template match="XML/Title"/>

<xsl:template match="Header">
<table>
<tbody>
<tr>
<td>
<xsl:value-of select="GOALNAME"/>
</td>
</tr>
</tbody>
</table>
</xsl:template>

<xsl:template match="Header_2">
<table>
<tbody>
<tr>
<td>
<xsl:value-of select="OBJNAME"/>
</td>
</tr>
</tbody>
</table>
</xsl:template>

<xsl:template match="adetail" mode="row">
<tr>
<xsl:apply-templates/>
</tr>
</xsl:template>

<xsl:template match="adetail/ATOTAL | adetail/AFEM | adetail/AMALE">
<td>
<xsl:value-of select="."/>
</td>
</xsl:template>

<xsl:template match="adetail/goalgroup"/>

</xsl:stylesheet>

When applied to your input sample in your initial post, Saxon 6.5.5
outputs the following HTML fragment:

<table>
<tbody>
<tr>
<td>Goal# 1 </td>
</tr>
</tbody>
</table>
<table>
<tbody>
<tr>
<td>Obj# 1 </td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr>
<th>ATOTAL</th>
<th>DFEM</th>
<th>DEMALE</th>
</tr>
</thead>
<tbody>
<tr>
<td>76</td>
<td>17</td>
<td>59</td>
</tr>
<tr>
<td>599</td>
<td>229</td>
<td>370</td>
</tr>
</tbody>
</table>
<table>
<tbody>
<tr>
<td>Goal# 4 </td>
</tr>
</tbody>
</table>
<table>
<tbody>
<tr>
<td>Obj# 3 </td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr>
<th>ATOTAL</th>
<th>DFEM</th>
<th>DEMALE</th>
</tr>
</thead>
<tbody>
<tr>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>3</td>
<td>1</td>
<td>2</td>
</tr>
</tbody>
</table>
 
Ad

Advertisements

S

shall

BRILLIANT!!!
Thanks a lot.

No I do NOT use XSLT 2.0
I was just trying to use something after becoming frustrated with XSLT
1.0.

Well XSLT 2.0 processors do exist thus if XSLT 1.0 and Muenchian
grouping with keys frustrates you you could consider to try XSLT 2.0
with one of Saxon 9 (http://saxon.sourceforge.net/) or AltovaXML Tools
(http://www.altova.com/altovaxml.html) or XQSharp (http://www.xqsharp.com/).

Or have a look at this XSLT 1.0 stylesheet:

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

   <xsl:eek:utput method="html" indent="yes"/>
   <xsl:strip-space elements="*"/>

   <xsl:key name="detail-by-group" match="adetail" use="goalgroup"/>

   <xsl:template match="adetail[not(generate-id() =
generate-id(key('detail-by-group', goalgroup)[1]))]"/>

   <xsl:template match="adetail[generate-id() =
generate-id(key('detail-by-group', goalgroup)[1])]">
     <table>
       <thead>
         <tr>
           <th>ATOTAL</th>
           <th>DFEM</th>
           <th>DEMALE</th>
         </tr>
       </thead>
       <tbody>
         <xsl:apply-templates select="key('detail-by-group', goalgroup)"
mode="row"/>
       </tbody>
     </table>
   </xsl:template>

   <xsl:template match="XML/Title"/>

   <xsl:template match="Header">
     <table>
       <tbody>
         <tr>
           <td>
             <xsl:value-of select="GOALNAME"/>
           </td>
         </tr>
       </tbody>
     </table>
   </xsl:template>

   <xsl:template match="Header_2">
     <table>
       <tbody>
         <tr>
           <td>
             <xsl:value-of select="OBJNAME"/>
           </td>
         </tr>
       </tbody>
     </table>
   </xsl:template>

   <xsl:template match="adetail" mode="row">
     <tr>
       <xsl:apply-templates/>
     </tr>
   </xsl:template>

   <xsl:template match="adetail/ATOTAL | adetail/AFEM | adetail/AMALE">
     <td>
       <xsl:value-of select="."/>
     </td>
   </xsl:template>

   <xsl:template match="adetail/goalgroup"/>

</xsl:stylesheet>

When applied to your input sample in your initial post, Saxon 6.5.5
outputs the following HTML fragment:

<table>
    <tbody>
       <tr>
          <td>Goal# 1  </td>
       </tr>
    </tbody>
</table>
<table>
    <tbody>
       <tr>
          <td>Obj# 1  </td>
       </tr>
    </tbody>
</table>
<table>
    <thead>
       <tr>
          <th>ATOTAL</th>
          <th>DFEM</th>
          <th>DEMALE</th>
       </tr>
    </thead>
    <tbody>
       <tr>
          <td>76</td>
          <td>17</td>
          <td>59</td>
       </tr>
       <tr>
          <td>599</td>
          <td>229</td>
          <td>370</td>
       </tr>
    </tbody>
</table>
<table>
    <tbody>
       <tr>
          <td>Goal# 4 </td>
       </tr>
    </tbody>
</table>
<table>
    <tbody>
       <tr>
          <td>Obj# 3 </td>
       </tr>
    </tbody>
</table>
<table>
    <thead>
       <tr>
          <th>ATOTAL</th>
          <th>DFEM</th>
          <th>DEMALE</th>
       </tr>
    </thead>
    <tbody>
       <tr>
          <td>0</td>
          <td>0</td>
          <td>0</td>
       </tr>
       <tr>
          <td>3</td>
          <td>1</td>
          <td>2</td>
       </tr>
    </tbody>
</table>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top