Re: Re: [xsl] Re: Problem with Muenchian grouping

Subject: Re: Re: [xsl] Re: Problem with Muenchian grouping
From: Dimitre Novatchev <dnovatchev@xxxxxxxxx>
Date: Wed, 12 Nov 2003 01:53:11 -0800 (PST)
> Usually my input XML files are much bigger but this one is a good 
> example.
> The <action>  elements all have the value "delete" but this is not a 
> problem.
> There are two groups (I'm only interested in the children of <data>  
> that have <action>  elements): breakdown and breakdownlanguage.
> I repeat that I need, for each of both groups, to build an HTML table. 
> To set the headers of those tables, I must get all possible children of 
> a category (the children differ from one member of a group to another, 
> but a member has only one child of a certain kind). Then the tables are 
> filled with the textnode values of those children (a field can be blank 
> if there is no child of a certain category).
> (But then, in a way, I must pay attention to the order of the headers).
> If someone could show me how nested grouping works, using the Muenchian
> method...

The solution is straightforward:

This transformation:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
  
  <xsl:output omit-xml-declaration="yes"/>
  
  <xsl:key name="kGrps" match="data/*[action]"
   use="name()"/>
   
   <xsl:key name="ktabRows" match="data/*[action]/*"
    use="concat(name(..), '|', name())"/>
  
  <xsl:template match="/">
    <xsl:for-each 
      select="*/data/*[generate-id()
                      =
                       generate-id(key('kGrps', name())[1])
                      ]">
      <xsl:value-of select="name()"/>
      <br />
      <table border="1">
        <tr>
          <xsl:for-each 
           select="/*/data/*[action]/*
                              [generate-id()
                              =
                               generate-id(key('ktabRows',
                                               concat(name(current()),
                                                     '|', 
                                                      name()
                                                     )
                                               )[1]
                                           )
                              ]">
            <td>
              <xsl:value-of select="name()"/>
            </td>
          </xsl:for-each>
        </tr>
          
        <xsl:for-each select="key('kGrps', name())">
          <xsl:variable name="vRow" select="."/>
         <tr>
          <xsl:for-each 
           select="/*/data/*[action]/*
                              [generate-id()
                              =
                               generate-id(key('ktabRows',
                                               concat(name(current()),
                                                     '|', 
                                                      name()
                                                     )
                                               )[1]
                                           )
                              ]">
            <td>
              <xsl:choose>
                <xsl:when test="$vRow/*[name() = name(current())]">
                  <xsl:value-of 
                       select="$vRow/*[name() = name(current())]"/>
                </xsl:when>
                <xsl:otherwise>
                  <xsl:value-of select="' '"/>
                </xsl:otherwise>
              </xsl:choose>
            </td>
          </xsl:for-each>
         
         </tr>
        </xsl:for-each>
      </table>
      <br />
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

when applied on your xml source:

<dump>
  <identification>
    <version> 1.0</version>
    <date> 17/04/2003</date>
  </identification>
  <data>
    <project eiac="PISCINE">
      <eiac> PISCINE</eiac>
      <lotnum> Lot 1</lotnum>
      <contractnum> 0011</contractnum>
      <lcnstructure> 11222333</lcnstructure>
      <projectpricecoef> 0.000</projectpricecoef>
      <projectpricecur> EUR</projectpricecur>
      <totalsystems> 1</totalsystems>
      <xafree1> REF LSA</xafree1>
      <xafree2> Rev</xafree2>
      <xafree10> ED1</xafree10>
    </project>
    <breakdown eiac="PISCINE" lcn="P1AA00XX" alc="00">
      <action> delete</action>
      <eiac> PISCINE</eiac>
      <lcn> P1AA00XX</lcn>
      <alc> 00</alc>
      <lcntype> P</lcntype>
      <uoc1> PS1</uoc1>
      <xbfree1> ED1</xbfree1>
      <xbfree2> E</xbfree2>
    </breakdown>
    <breakdown eiac="PISCINE" lcn="P1AA00XX001" alc="00">
      <action> delete</action>
      <eiac> PISCINE</eiac>
      <lcn> P1AA00XX001</lcn>
      <alc> 00</alc>
      <lcntype> P</lcntype>
      <breakramind> Y</breakramind>
      <uoc1> PS1</uoc1>
      <uoc2> PS2</uoc2>
      <xbfree1> ED1</xbfree1>
      <xbfree2> F</xbfree2>
    </breakdown>
    <breakdown eiac="PISCINE" lcn="P1AA01AB" alc="01">
      <action> delete</action>
      <eiac> PISCINE</eiac>
      <lcn> P1AA01AB</lcn>
      <alc> 01</alc>
      <lcntype> P</lcntype>
      <breakramind> Y</breakramind>
      <uoc1> PS2</uoc1>
      <xbfree1> ED1</xbfree1>
      <xbfree2> E</xbfree2>
    </breakdown>
    <breakdownlanguage eiac="PISCINE" lcn="P1AA00" alc="01" language="FR">
      <eiac> PISCINE</eiac>
      <lcn> P1AA00</lcn>
      <alc> 01</alc>
      <lcntypexb1> P</lcntypexb1>
      <language> FR</language>
      <lcnnom> S_SYST FILTRATION</lcnnom>
      <lcnnomfull> S_SYST FILTRATION</lcnnomfull>
    </breakdownlanguage>
    <breakdownlanguage eiac="PISCINE" lcn="P1AA00XX003" alc="01"
language="FR">
      <action> delete</action>
      <eiac> PISCINE</eiac>
      <lcn> P1AA00XX003</lcn>
      <alc> 01</alc>
      <lcntypexb1> P</lcntypexb1>
      <language> FR</language>
    </breakdownlanguage>
    <breakdownlanguage eiac="PISCINE" lcn="P1AA00XX" alc="00"
language="EN">
      <action> delete</action>
      <eiac> PISCINE</eiac>
      <lcn> P1AA00XX</lcn>
      <alc> 00</alc>
      <lcntypexb1> P</lcntypexb1>
      <language> EN</language>
      <lcnnom> ALIMENTATION EAUX</lcnnom>
      <lcnnomfull> ALIMENTATION EAUX</lcnnomfull>
    </breakdownlanguage>
  </data>
</dump>

produces the wanted result:

breakdown<br/>
<table border="1">
   <tr>
      <td>action</td>
      <td>eiac</td>
      <td>lcn</td>
      <td>alc</td>
      <td>lcntype</td>
      <td>uoc1</td>
      <td>xbfree1</td>
      <td>xbfree2</td>
      <td>breakramind</td>
      <td>uoc2</td>
   </tr>
   <tr>
      <td> delete</td>
      <td> PISCINE</td>
      <td> P1AA00XX</td>
      <td> 00</td>
      <td> P</td>
      <td> PS1</td>
      <td> ED1</td>
      <td> E</td>
      <td> </td>
      <td> </td>
   </tr>
   <tr>
      <td> delete</td>
      <td> PISCINE</td>
      <td> P1AA00XX001</td>
      <td> 00</td>
      <td> P</td>
      <td> PS1</td>
      <td> ED1</td>
      <td> F</td>
      <td> Y</td>
      <td> PS2</td>
   </tr>
   <tr>
      <td> delete</td>
      <td> PISCINE</td>
      <td> P1AA01AB</td>
      <td> 01</td>
      <td> P</td>
      <td> PS2</td>
      <td> ED1</td>
      <td> E</td>
      <td> Y</td>
      <td> </td>
   </tr>
</table>
<br/>breakdownlanguage<br/>
<table border="1">
   <tr>
      <td>action</td>
      <td>eiac</td>
      <td>lcn</td>
      <td>alc</td>
      <td>lcntypexb1</td>
      <td>language</td>
      <td>lcnnom</td>
      <td>lcnnomfull</td>
   </tr>
   <tr>
      <td> delete</td>
      <td> PISCINE</td>
      <td> P1AA00XX003</td>
      <td> 01</td>
      <td> P</td>
      <td> FR</td>
      <td> </td>
      <td> </td>
   </tr>
   <tr>
      <td> delete</td>
      <td> PISCINE</td>
      <td> P1AA00XX</td>
      <td> 00</td>
      <td> P</td>
      <td> EN</td>
      <td> ALIMENTATION EAUX</td>
      <td> ALIMENTATION EAUX</td>
   </tr>
</table>
<br/>


Hope this helped.


=====
Cheers,

Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL



__________________________________
Do you Yahoo!?
Protect your identity with Yahoo! Mail AddressGuard
http://antispam.yahoo.com/whatsnewfree

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread