RE: [xsl] Recursive grouping won't recurse...

Subject: RE: [xsl] Recursive grouping won't recurse...
From: "Hunsberger, Peter" <Peter.Hunsberger@xxxxxxxxxx>
Date: Fri, 5 Jul 2002 10:42:10 -0500
Hi Robert, 

got a version of your implementation to work.  One gotcha, the code won't
separate two groups of the same type at the same level that are separated by
an intervening group.  Luckily, this condition will not occur in the data
I'm dealing with.  I can see that Dimitre's code would handle that, but I
can skip the complexity of that code (for now).  Final solution resembled:

<xsl:template match="list">
   <xsl:apply-templates select="." mode="menu"/>
</xsl:template>

<xsl:template match="*" mode="menu">
   <xsl:copy select=".">
      <xsl:apply-templates select="@* | text()"/>
      <xsl:for-each select="*">
         <xsl:variable name="type"><xsl:value-of
select="@type"/></xsl:variable>
         <xsl:variable name="flag"><xsl:value-of
select="@flag"/></xsl:variable>
         <xsl:variable name="prev_type"><xsl:value-of
select="preceding-sibling::*[1]/@type"/></xsl:variable>
         <xsl:choose>
            <xsl:when test="$flag='true'">
               <xsl:if test="$prev_type != $type">
                  <group>
                     <xsl:apply-templates select="../*[@type = $type]"
mode="menu"/>
                  </group>
               </xsl:if>
            </xsl:when>
            <xsl:otherwise>
               <xsl:apply-templates select="." mode="menu"/>
            </xsl:otherwise>
         </xsl:choose>
      </xsl:for-each>
   </xsl:copy>
</xsl:template>

One very strange thing:  I had to code the detection of the type and the
flag using the form given above (as in your code).  The form:

      <xsl:variable name="type" select="@type"/>
      <xsl:variable name="flag" select="@flag"/>

or any other direct references to these attributes would not work (IE, with
either ./@type or current()/@type). Anyone know why that is?

-----Original Message-----
From: Robert S. Koberg [mailto:rob@xxxxxxxxxx]
Sent: Thursday, July 04, 2002 1:11 PM
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: Re: [xsl] Recursive grouping won't recurse...


Sorry, to quick to respond. I can see that my first one does not address 
your need. This is a tuff one. How about:

<xsl:template match="list">
 >  <xsl:apply-templates/>
 > </xsl:template>
 >
 > <xsl:template match="a | b | c | d | e | f">
 >   <xsl:element name="name()">
 >     <xsl:attribute  name="type">
 >       <xsl:value-of select="@type"/>
 >     </xsl:attribute>
 >     <xsl:attribute  name="flag">
 >       <xsl:value-of select="@flag"/>
 >     </xsl:attribute>
 >     <xsl:if test="boolean(./*)">
         <xsl:for-each select="./*">
           <xsl:sort select="@type"/>
           <xsl:variable name="prev_sib" select="previous-sibling::*"/>
           <xsl:variable name="type" select="@type"/>
           <xsl:choose>
             <xsl:when test="$type=$prev_sib">
               <xsl:apply-templates select="current()"/>
             </xsl:when>
             <xsl:otherise>
               <xsl:call-template name="grouper">
                 <xsl:with-param name="_type" select="type"/>
               </xsl:template>
             </xsl:otherwise>
           </xsl:choose>
         </xsl:for-each>
	<xsl:apply-templates/>

 >     </xsl:if>
 >   </xsl:element>
 > </xsl:template>

<xsl:template name="grouper">
   <xsl:param name="_type"/>
   <group>
     <xsl:apply-temples select="../*[@type=$_type]"/>
   </group>
</xsl:template>

> Hi Peter,
> 
> Hunsberger, Peter wrote:
> 
>> I'm still shaky on grouping with keys so I've probably missed something
>> obvious, but I can't get a grouping to work when it has to group on a
>> recursive structure.  The input looks essentially like the following:
>>
>>     <list>
>>        <a type="1" flag="false"/>
>>        <b type="2" flag="false"/>
>>        <c type="3" flag="false">
>>           <d type="4" flag="true"/>
>>           <e type="4" flag="true"/>
>>           <f type="5" flag="true"/>
>>          <g type="5" flag="true"/>
>>        </c>
>>     </list>
>>     <list>
>>        <a type="1" flag="false"/>
>>        <b type="2" flag="false"/>
>>        <c type="3" flag="false">
>>           <d type="7" flag="false">
>>              <e type="4" flag="true"/>
>>              <e type="4" flag="true"/>
>>           </d>
>>        </c>
>>     </list>
>>
>> Where, if there are adjacent nodes with the same type than the flag 
>> will be
>> true, otherwise the flag will always be false.  It could be possible for
>> adjacent nodes to have the same type with the flag set to false. The same
>> structure could go many more levels deep than shown here. The desired 
>> output
>> is
> 
>>     <list>
>>        <a type="1" flag="false"/>
>>        <b type="2" flag="false"/>
>>        <c type="3" flag="false">
>>           <group>
>>              <d type="4" flag="true"/>
>>              <e type="4" flag="true"/>
>>                     </group>
>>           <group>
>>              <f type="5" flag="true"/>
>>             <g type="5" flag="true"/>
>>           </group>
>>        </c>
>>     </list>
>>     <list>
>>        <a type="1" flag="false"/>
>>        <b type="2" flag="false"/>
>>        <c type="3" flag="false">
>>           <d type="7" flag="false">
>>              <group>
>>                 <e type="4" flag="true"/>
>>                 <e type="4" flag="true"/>
>>              </group>
>>           </d>
>>        </c>
>>     </list>
>>

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


Current Thread