[xsl] Re: Grouping problem?

Subject: [xsl] Re: Grouping problem?
From: "Dimitre Novatchev" <dnovatchev@xxxxxxxxx>
Date: Tue, 22 Apr 2003 23:18:47 +0200
Unfortunately, this does not produce the right result in the general case.

Consider:

<root>
  <ele sum="3"/>
  <ele sum="4"/>
  <ele sum="2"/>
  <ele sum="10"/>
  <ele sum="1"/>
  <ele sum="5"/>
  <ele sum="1"/>
  <ele sum="2"/>
</root>


The result produced by your transformation is:

<root>
  <ele sum="3"></ele>
  <ele sum="4"></ele>
  <ele sum="2"></ele>
  <br />
  <ele sum="10"></ele>
  <ele sum="1"></ele>
  <br />
  <ele sum="5"></ele>
  <ele sum="1"></ele>
  <ele sum="2"></ele>
</root>

The second group above has a sum of 11.


There is a recursive solution. It can be obtained by translating in XSLT the
following brief Haskell solution:


> cutBy :: (Num a, Ord a) => a -> [[a]] -> [a] -> [[a]]

> cutBy z yss [] = yss

> cutBy z (yss) (x:xs)

> | sum (last yss) + x < z + 1 = cutBy z ( init yss ++ [last yss ++ [x]]) xs

> | otherwise = cutBy z ( yss ++ [[x]]) xs

This works as follows:

MYExamples> cutBy 10 [ [] ]   [3, 4, 2, 10, 7, 5, 1, 2]

[[3,4,2], [10], [7], [5,1,2]]

MYExamples> cutBy 10 [ [] ]  [3, 4, 2, 10, 1, 7, 5, 1, 2]

[[3,4,2], [10], [1,7], [5,1,2]]

MYExamples>


The beauty of Haskell is that because of lazy evaluation we could have
infinite lists and the above function is a transformation of one stream into
another -- e.g. we could model operations on a conveyor line.


Of course the above will not work, because we are using last().

But this will work with streams:

> cutBy :: (Num a, Ord a) => a -> [[a]] -> [a] -> [[a]]

> cutBy z yss [] = yss

> cutBy z (ys:yss) (x:xs)

> | sum ys + x < z + 1 = cutBy z ((x : ys) : yss ) xs

> | otherwise = cutBy z ([x] : ys : yss ) xs


MYExamples> cutBy 10 [ [] ] [3, 4, 2, 10, 7, 5, 1, 2]

[[2,1,5], [7], [10], [2,4,3]]

MYExamples> cutBy 10 [ [] ] [3, 4, 2, 10, 1, 7, 5, 1, 2]

[[2,1,5], [7,1], [10], [2,4,3]]

MYExamples>


=====
Cheers,

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

"Benjamin Farrow" <lovinjess@xxxxxxxxxxx> wrote in message
news:Law15-F58cDioalzvzy0000e86f@xxxxxxxxxxxxxx
> Well perhaps I've found a solution...it appears to be working anyhow.  Any
> comments would be welcome.
>
> <xsl:stylesheet version="1.0"
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
>
>   <xsl:key name="groupByTen"
>            match="ele"
>            use="ceiling(sum(preceding-sibling::ele/@sum|@sum) div 10)"/>
>
>   <xsl:template match="/">
>     <xsl:apply-templates select="node()|@*"/>
>   </xsl:template>
>
>   <xsl:template match="ele">
>     <xsl:variable name="sum"
> select="sum(preceding-sibling::ele/@sum|@sum)"/>
>     <xsl:if test="generate-id(key('groupByTen',ceiling($sum div 10))[1]) =
> generate-id(.) and
>                   position() != 1">
>       <br/>
>     </xsl:if>
>     <xsl:copy>
>       <xsl:apply-templates select="node()|@*"/>
>     </xsl:copy>
>   </xsl:template>
>
>   <xsl:template match="node()|@*">
>     <xsl:copy>
>       <xsl:apply-templates select="node()|@*"/>
>     </xsl:copy>
>   </xsl:template>
>
> </xsl:stylesheet>
>
>
>
>
>
> >From: "Benjamin Farrow" <lovinjess@xxxxxxxxxxx>
> >Reply-To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> >To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> >Subject: [xsl] Grouping problem?
> >Date: Tue, 22 Apr 2003 12:06:02 -0700
> >
> >All,
> >  I don't know how to explain my problem in words very concisely, so I'll
> >try with a simplified example.
> >
> >SourceXML:
> ><root>
> >  <ele sum="3"/>
> >  <ele sum="4"/>
> >  <ele sum="2"/>
> >  <ele sum="10"/>
> >  <ele sum="7"/>
> >  <ele sum="5"/>
> >  <ele sum="1"/>
> >  <ele sum="2"/>
> ></root>
> >
> >Desired Output:
> ><root>
> >  <ele sum="3"/>
> >  <ele sum="4"/>
> >  <ele sum="2"/>
> >  <br/>          <!-- next element makes total greater than 10 -->
> >  <ele sum="10"/>
> >  <br/>          <!-- next element makes total greater than 20 -->
> >  <ele sum="7"/>
> >  <br/>          <!-- next element makes total greater than 30 -->
> >  <ele sum="5"/>
> >  <ele sum="1"/>
> >  <ele sum="2"/>
> ></root>
> >
> >I'm trying to break apart the ele element when the sum total of preceding
> >siblings and self is greater than the increment of 10 by putting an
element
> >to denote the break.
> >
> >I've tried some crazy tests with mod and div and I've looked over the
> >Muenchian grouping, but I still can't come up with a way to arbitrarily
set
> >the break points.  I know there is a solution and I get close, but I just
> >can't get around it.
> >
> >Here is my template (also have the standard identity template) with which
> >I'm trying to get this working.  I just can't figure out the if test for
> >this though.
> >
> >XSL:
> >  <xsl:template match="ele">
> >    <xsl:variable name="sum"
> >select="sum(preceding-sibling::ele/@sum|@sum)"/>
> >    <xsl:if test="$sum &gt; (floor($sum div 10) * 10)">
> >      <br/>
> >    </xsl:if>
> >    <xsl:copy>
> >      <xsl:apply-templates select="node()|@*"/>
> >    </xsl:copy>
> >  </xsl:template>
> >
> >Thanks in advance,
> >  Benjamin
> >
> >
> >_________________________________________________________________
> >MSN 8 with e-mail virus protection service: 2 months FREE*
> >http://join.msn.com/?page=features/virus
> >
> >
> >XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
> >
>
>
> _________________________________________________________________
> Tired of spam? Get advanced junk mail protection with MSN 8.
> http://join.msn.com/?page=features/junkmail
>
>
>  XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
>
>







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


Current Thread