xsl-list
[Top] [All Lists]

Re: For-each loop or recursion

2005-05-16 16:11:46
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(_at_)hotmail(_dot_)com> 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>&#xa;</xsl:text>
       <xsl:call-template name="trimmed-data"/>
   </xsl:template>

   <xsl:template name="raw-data">
       <xsl:text>raw data (sorted)&#xa;</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>&#xa;</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>&#xa;</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[. &lt;= 0]) + 1"/>

       <!-- pos of first non-zero rebate2 -->
       <xsl:variable name="pr2"
select="count(mystruct/myarray2/myvar/rebate2[. &lt;= 0]) + 1"/>

       <!-- pos of first non-zero rebate* -->
       <xsl:variable name="pr">
           <xsl:choose>
               <xsl:when test="$pr1 &lt;= $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[. &lt; $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[. &lt; $mr2]) + 1"/>

       <!-- pos of greater max rebate* -->
       <xsl:variable name="pmr">
           <xsl:choose>
               <xsl:when test="$pmr1 &gt;= $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&#xa;</xsl:text>
       <xsl:text>rebate1 </xsl:text>
       <xsl:for-each select="mystruct/myarray1/myvar/rebate1">
           <xsl:if test="position() &gt;= $pr and position() &lt;= $pmr">
               <xsl:apply-templates select="."/>
           </xsl:if>
       </xsl:for-each>
       <xsl:text>&#xa;</xsl:text>

       <xsl:text>rebate2 </xsl:text>
       <xsl:for-each select="mystruct/myarray2/myvar/rebate2">
           <xsl:if test="position() &gt;= $pr and position() &lt;= $pmr">
               <xsl:apply-templates select="."/>
           </xsl:if>
       </xsl:for-each>
       <xsl:text>&#xa;</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/

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: 
<mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--



--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--



<Prev in Thread] Current Thread [Next in Thread>