Subject: Re: For-each loop or recursion
From: Oleg Konovalov <olegkon@xxxxxxxxx>
Date: Mon, 16 May 2005 19:11:46 -0400
|
Aron,
Thank you very much.
It was very helpful.
My solution to get was similar, but without Count.
Thanks again,
Oleg.
On 5/16/05, Aron Bock <aronbock@xxxxxxxxxxx> wrote:
> Oleg,
>
>
> >Existing code is very complex - big Cocoon project
>
> Which is why I, among other people, have been asking for a "representative"
> example. It doesn't have to be your actual XML. Just make up something
> that's representative. Making up a representative sample is possible, as
> you'll see at the end of this note.
>
> >(and I started using XSLT 2 weeks ago, but have lots of experience in
> >Java/C/C++), so I tried to keep concentrated on what I am doing:
>
> Nobody's questioning your competency with those languages. But since you
> mention it, it seems you're giving into the thinking that if you're
> proficient at something, it's an admission of, uh, who knows what, to start
> from basics in another field. You're saying, "tell me how this is done,
and
> I'm smart enough/nice enough/whatever enough to apply it myself", whereas
> sampes and descriptions you've provided thus far show only that you're
> bringing to bear imperative solutions on declarative problems. Trust me on
> this--provide a sample, and you'll get all the specific help you need.
>
> >At this point I am interested in how to implement algorithms in XSLT:
> >a) find out first non-zero on either rebate1 and rebate2
> >b) find out first occurrence of max number in either rebate1 or rebate2
>
> This was already answered succintly by a prior respondent, who suggested
you
> use a loop and pick out the first/last element.
>
>
> >So back to my questions:
> >1) How do I get a position of last occurrence of min ?
>
> Many ways, 2 of which may be:
> --locate the node and count its preceding siblings
> --count number of min and adjust
>
> >1a) Can I scan using for-each loop from the end of the sequence
> >to the beginning ?
>
> yes, see <xsl:sort> and its attributes
>
> >2) OK, lets try to get a position of the first occurrence when var2 = max
> >node.
> >What would be a correct ?
> >
> ><xsl:for-each select=mystruct/myarray1[1]/myvar>
> > <xsl:if select="rebate1=*[last()]">
> > <xsl:value-of select="position()">
> > </xsl:if>
> ></xsl:for-each>
> >
> >3) Expanding 2 for the rebate2 (var3) for the values from another
> >(parallel) branch,
> >would that work ?
> >
> ><xsl:for-each select=mystruct/myarray1[1]/myvar>
> > <xsl:if select="rebate1=*[last()] and
> > ../../../myarray2[1]/myvar/rebate2=*[last()]">
> > <xsl:value-of select="position()">
> > </xsl:if>
> ></xsl:for-each>
> >
> >I think, that second *[last()] is wrong,
> >I have to get a max of the rebate2 (second sequence)
> >before that for-each loop.
> >
> >3a) Can I calculate max of rebate2 like:
> ><xsl:variable name="max2"
> >select="mystruct/myarray2[1]/myvar/rebate2[position()=last()]">
> >Is that the right way of assigning *[last()] to a variable ?
>
> These need more context to respond to with any value. As a prior
respondent
> said, showing just the XSL is of little use--without the corresponding XML
> it's more often than not futile to comment on its semantics.
>
> Now, using your description below, *I'll* make up XML, and write simple, if
> verbose, XSL to get your results:
>
>
> >column to be displayed [first non-zero on either rebate1 and rebate2]
> >and the last one [first occurrence of max number in either rebate1 or
> >rebate2]
> >
> > 1 2 3 4 5 6 7 8 9 10 11 12
> >13 (sales volume)
> >rebate1(%) 0 0 1 2 3 4 5 6 7 8 8 8 8
> >rebate2(%) 0 1 2 3 4 5 6 7 9 10 11 11 11
> >
> >Need it be dynamically trimmed to display:
> >
> > 2 3 4 5 6 7 8 9 10 "11 or more"
> >rebate1(%) 0 1 2 3 4 5 6 7 8 8
> >rebate2(%) 1 2 3 4 5 6 7 9 10 11
> >
> >So if it makes it any easier, we can call it
> >mystruct/myarray1[1]/myvar/rebate1 and
> >mystruct/myarray2[1]/myvar/rebate2
>
> This XML:
>
> <mystruct>
> <myarray1>
> <myvar><rebate1>0</rebate1></myvar>
> <myvar><rebate1>0</rebate1></myvar>
> <myvar><rebate1>1</rebate1></myvar>
> <myvar><rebate1>2</rebate1></myvar>
> <myvar><rebate1>3</rebate1></myvar>
> <myvar><rebate1>4</rebate1></myvar>
> <myvar><rebate1>5</rebate1></myvar>
> <myvar><rebate1>6</rebate1></myvar>
> <myvar><rebate1>7</rebate1></myvar>
> <myvar><rebate1>8</rebate1></myvar>
> <myvar><rebate1>8</rebate1></myvar>
> <myvar><rebate1>8</rebate1></myvar>
> </myarray1>
> <myarray2>
> <myvar><rebate2>0</rebate2></myvar>
> <myvar><rebate2>1</rebate2></myvar>
> <myvar><rebate2>2</rebate2></myvar>
> <myvar><rebate2>3</rebate2></myvar>
> <myvar><rebate2>4</rebate2></myvar>
> <myvar><rebate2>5</rebate2></myvar>
> <myvar><rebate2>6</rebate2></myvar>
> <myvar><rebate2>7</rebate2></myvar>
> <myvar><rebate2>9</rebate2></myvar>
> <myvar><rebate2>10</rebate2></myvar>
> <myvar><rebate2>11</rebate2></myvar>
> <myvar><rebate2>11</rebate2></myvar>
> <myvar><rebate2>11</rebate2></myvar>
> </myarray2>
> </mystruct>
>
> With this XSL:
>
> (This could be shortened, but I'm unwilling to put in any more time w/
> guessed-at data)
>
> <?xml version="1.0" encoding="iso8859-1"?>
> <xsl:stylesheet version="1.0"
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
> <xsl:output method="text"/>
>
> <xsl:template match="/">
> <xsl:call-template name="raw-data"/>
> <xsl:text>
</xsl:text>
> <xsl:call-template name="trimmed-data"/>
> </xsl:template>
>
> <xsl:template name="raw-data">
> <xsl:text>raw data (sorted)
</xsl:text>
> <xsl:text>rebate1 </xsl:text>
> <xsl:apply-templates select="mystruct/myarray1/myvar/rebate1">
> <xsl:sort data-type="number" select="."/>
> </xsl:apply-templates>
> <xsl:text>
</xsl:text>
>
> <xsl:text>rebate2 </xsl:text>
> <xsl:apply-templates select="mystruct/myarray2/myvar/rebate2">
> <xsl:sort data-type="number" select="."/>
> </xsl:apply-templates>
> <xsl:text>
</xsl:text>
> </xsl:template>
>
> <xsl:template name="trimmed-data">
> <!-- pos of first non-zero rebate1 -->
> <xsl:variable name="pr1"
> select="count(mystruct/myarray1/myvar/rebate1[. <= 0]) + 1"/>
>
> <!-- pos of first non-zero rebate2 -->
> <xsl:variable name="pr2"
> select="count(mystruct/myarray2/myvar/rebate2[. <= 0]) + 1"/>
>
> <!-- pos of first non-zero rebate* -->
> <xsl:variable name="pr">
> <xsl:choose>
> <xsl:when test="$pr1 <= $pr2">
> <xsl:value-of select="$pr1"/>
> </xsl:when>
> <xsl:otherwise>
> <xsl:value-of select="$pr2"/>
> </xsl:otherwise>
> </xsl:choose>
> </xsl:variable>
>
> <!-- max rebate1 -->
> <xsl:variable name="mr1">
> <xsl:for-each select="mystruct/myarray1/myvar/rebate1">
> <xsl:sort data-type="number" select="."/>
> <xsl:if test="position() = last()">
> <xsl:value-of select="."/>
> </xsl:if>
> </xsl:for-each>
> </xsl:variable>
>
> <!-- pos first max rebate1 -->
> <xsl:variable name="pmr1"
> select="count(mystruct/myarray1/myvar/rebate1[. < $mr1]) + 1"/>
>
> <!-- max rebate2 -->
> <xsl:variable name="mr2">
> <xsl:for-each select="mystruct/myarray2/myvar/rebate2">
> <xsl:sort data-type="number" select="."/>
> <xsl:if test="position() = last()">
> <xsl:value-of select="."/>
> </xsl:if>
> </xsl:for-each>
> </xsl:variable>
>
> <!-- pos first max rebate2 -->
> <xsl:variable name="pmr2"
> select="count(mystruct/myarray2/myvar/rebate2[. < $mr2]) + 1"/>
>
> <!-- pos of greater max rebate* -->
> <xsl:variable name="pmr">
> <xsl:choose>
> <xsl:when test="$pmr1 >= $pmr2">
> <xsl:value-of select="$pmr1"/>
> </xsl:when>
> <xsl:otherwise>
> <xsl:value-of select="$pmr2"/>
> </xsl:otherwise>
> </xsl:choose>
> </xsl:variable>
>
> <xsl:text>trimmed data
</xsl:text>
> <xsl:text>rebate1 </xsl:text>
> <xsl:for-each select="mystruct/myarray1/myvar/rebate1">
> <xsl:if test="position() >= $pr and position() <= $pmr">
> <xsl:apply-templates select="."/>
> </xsl:if>
> </xsl:for-each>
> <xsl:text>
</xsl:text>
>
> <xsl:text>rebate2 </xsl:text>
> <xsl:for-each select="mystruct/myarray2/myvar/rebate2">
> <xsl:if test="position() >= $pr and position() <= $pmr">
> <xsl:apply-templates select="."/>
> </xsl:if>
> </xsl:for-each>
> <xsl:text>
</xsl:text>
> </xsl:template>
>
> <xsl:template match="rebate1">
> <xsl:value-of select="."/>
> <xsl:text> </xsl:text>
> </xsl:template>
>
> <xsl:template match="rebate2">
> <xsl:value-of select="."/>
> <xsl:text> </xsl:text>
> </xsl:template>
>
> </xsl:stylesheet>
>
> Produces:
>
> raw data (sorted)
> rebate1 0 0 1 2 3 4 5 6 7 8 8 8
> rebate2 0 1 2 3 4 5 6 7 9 10 11 11 11
>
> trimmed data
> rebate1 0 1 2 3 4 5 6 7 8 8
> rebate2 1 2 3 4 5 6 7 9 10 11
>
> Regards,
>
> --A
>
> _________________________________________________________________
> Express yourself instantly with MSN Messenger! Download today - it's FREE!
> http://messenger.msn.click-url.com/go/onm00200471ave/direct/01/
|