Subject: 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: 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 > (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
|