Re: [xsl] Xalan bug?

Subject: Re: [xsl] Xalan bug?
From: Mukul Gandhi <mukul_gandhi@xxxxxxxxx>
Date: Thu, 2 Dec 2004 20:35:57 -0800 (PST)
Regarding this point..
----------------------------
I wanted to generate , (commas) - to seperate group
members, actually with this code
<xsl:if test="position() != last()">
  <xsl:text>,</xsl:text>
</xsl:if>
But this is not working.. 

So I wrote, 
<xsl:if test="(position() mod $group-size) != 0">
-----------------------------

This code -
<xsl:if test="(position() mod $group-size) = 0">
  group <xsl:value-of select="floor(position() div
$group-size)" /><xsl:text> - </xsl:text>
  <xsl:for-each select=". |
preceding-sibling::node[position() &lt;= ($group-size
- 1)]">         
    <xsl:value-of select="." />
    <!-- PLEASE NOTE THIS -->
    <xsl:if test="position() != last()">
       <xsl:text>,</xsl:text>
    </xsl:if>       
  </xsl:for-each>
  <xsl:text>&#xa;</xsl:text>
</xsl:if> 
is working fine with Saxon 8 and MSXSL 4, but not with
Xalan-J 2.6.0..

I am getting the following outputs(with group-size=3)
:
1) With Xalan 2.6
-----------------
java org.apache.xalan.xslt.Process -in group.xml -xsl
group.xsl

group 1 - a,
group 2 - f,
group 3 - j,

2) With MSXSL 4
---------------
msxsl group.xml group.xsl
g r o u p   1   -   a , s , d
g r o u p   2   -   f , g , h
g r o u p   3   -   j , k , l

3) With Saxon 8
---------------
java net.sf.saxon.Transform group.xml group.xsl
group 1 - a,s,d
group 2 - f,g,h
group 3 - j,k,l

Regards,
Mukul

--- Mukul Gandhi <mukul_gandhi@xxxxxxxxx> wrote:

> Hi Geert,
>   Thanks for your observations..
> 
> Please note: I am getting correct result for
> group-size of 1,2,3 & 4. But with 5 and above,
> result
> is wrong(Only with Xalan; among Xalan-J2.6.0, Saxon
> 8,
> and MSXSL 4 with whom I tested).
> 
> One another interesting observation is that, in this
> part of the code
> 
> <!-- display group members -->
> <xsl:for-each select=". |
> preceding-sibling::node[position() &lt;=
> ($group-size
> - 1)]">         
>    <xsl:value-of select="." />
>    <xsl:if test="(position() mod $group-size) !=
> 0">
>      <xsl:text>,</xsl:text>
>    </xsl:if>       
> </xsl:for-each>
> 
> I wanted to generate , (commas) - to seperate group
> members, actually with this code
> <xsl:if test="position() != last()">
>   <xsl:text>,</xsl:text>
> </xsl:if>
> But this is not working.. 
> 
> So I wrote, 
> <xsl:if test="(position() mod $group-size) != 0">
> 
> Is'nt this surprising?
> 
> Regards,
> Mukul
> 
> --- Geert Josten <Geert.Josten@xxxxxxxxxxx> wrote:
> 
> > Hi Mukul,
> > 
> > The trouble rests in the expression that takes the
> > preceding nodes that sound belong in the last 
> > group together with the last node:
> > 
> >         <xsl:for-each select=". |
> > preceding-sibling::node[position() &lt; $n]">
> > 
> > I'm very uncertain on what the XPath rec sais on
> how
> > position() should be interpreted. I tried to 
> > wrap preceding-sibling::node in braces, but that
> > results in them being put back into doc order (as 
> > it should!), so you get a in the last group
> instead
> > of one of the last... :-P
> > 
> > Considering that preceding-sibling::node is
> failing,
> > one should expect that only the left part of 
> > the union (.) returns a value. But, the result is
> > _not_ showing the last node, but the first of that
> 
> > last group (which is correct). Moreover, a ',' is
> > shown, so the context list is filled with more 
> > than one node! The for-each is definitely
> failing!!!
> > 
> > A less mind boggling expression, that works with
> all
> > parsers as well (I guess) is:
> > 
> >         <xsl:for-each select="../node[position() >
> > $m]">
> > 
> > with m defined as:
> > 
> >     <xsl:variable name="m"
> select="floor(count(node)
> > div $group-size) * $group-size" />
> > 
> > 
> > Though I really think, you have conceived a
> complex
> > solution for a not necessarily that complex a 
> > problem...
> > 
> > 
> > Cheers,
> > Geert
> > 
> > 
> > Mukul Gandhi wrote:
> > 
> > > I have added some comments in my logic(shown
> > below) to
> > > help in understanding..
> > > 
> > > <?xml version="1.0"?> 
> > > <xsl:stylesheet
> > > xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
> > > version="1.0">
> > >  
> > > <xsl:output method="text" /> 
> > > 
> > > <xsl:param name="group-size" select="3" />
> > >  
> > > <xsl:template match="/Parent">
> > >    <!-- calculate the no of "node" elements,
> which
> > are
> > > left as a fraction; which are to be displayed in
> > the
> > > last group -->
> > >    <xsl:variable name="n" select="count(node) -
> > > (floor((count(node) div $group-size)) *
> > $group-size)"
> > > />
> > >    
> > >    <xsl:for-each select="node">
> > >      <!-- determine group boundary; this if test
> > stops
> > > at the last "node" element of the group -->
> > >      <xsl:if test="(position() mod $group-size)
> =
> > 0">
> > >        group <xsl:value-of
> > select="floor(position()
> > > div $group-size)" /><xsl:text> - </xsl:text>
> > >        <!-- display group members -->
> > >        <xsl:for-each select=". |
> > > preceding-sibling::node[position() &lt;=
> > ($group-size
> > > - 1)]">         
> > >          <xsl:value-of select="." /><xsl:if
> > > test="(position() mod $group-size) !=
> > > 0"><xsl:text>,</xsl:text></xsl:if>       
> > >        </xsl:for-each>
> > >        <xsl:text>
> </xsl:text>
> > >      </xsl:if> 
> > >      <!-- this if test processes the last group;
> > whose
> > > number of group members will be less than the
> > > group-size -->
> > >      <xsl:if test="((position() = last()) and
> > > ((position() mod $group-size) != 0))">
> > >        group <xsl:value-of
> > select="floor(position()
> > > div $group-size) + 1" /><xsl:text> - </xsl:text>
> > >        <xsl:for-each select=". |
> > > preceding-sibling::node[position() &lt; $n]">
> > >          <xsl:value-of select="." /><xsl:if
> > > test="position() !=
> > > last()"><xsl:text>,</xsl:text></xsl:if> 
> > >        </xsl:for-each>
> > >        <xsl:text>
> </xsl:text>
> > >      </xsl:if>
> > >    </xsl:for-each>
> > > </xsl:template>
> > >    
> > > </xsl:stylesheet>
> > > 
> > > I would be happy to see any discussion on this
> > post..
> > > 
> > > Regards,
> > > Mukul
> > > 
> > > PS: I have posted it as a bug on Xalan site. 
> > > 
> > > --- Mukul Gandhi <mukul_gandhi@xxxxxxxxx> wrote:
> > > 
> > > 
> > >>Hello,
> > >>I was solving a problem posted by a user at
> > >>microsoft.public.xsl newsgroup. I seem to have
> > been
> > >>hit by a Xalan bug(Xalan-J 2.6.0), which I wish
> to
> > >>confirm with members here.. 
> > >>
> > >>The problem posted was -
> > >>Subject: Grouping by two or any number
> > >>--------------------------------------
> > >>i have the following xml
> > >>
> > >><Parent>
> > >>  <node>a</node>
> > >>  <node>s</node>
> > >>  <node>d</node>
> > >>  <node>f</node>
> > >>  <node>g</node>
> > >>  <node>h</node>
> > >>  <node>j</node>
> > >>  <node>k</node>
> > >>  <node>l</node>
> > >></Parent>
> > >>
> > >>
> > >>Need to print in following format (into groups
> of
> > >>two)
> > >>
> > >>group 1 - a,s
> > >>group 2 - d,f
> > >>group 3 - g,h
> > >>group 4 - j,k
> > >>group 5 - l
> > >>
> > >>I wrote the following stylesheet -
> > >>
> > >><?xml version="1.0"?> 
> > >><xsl:stylesheet
> > >>xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
> > >>version="1.0">
> > >> 
> > >><xsl:output method="text" /> 
> > >>
> > >><xsl:param name="group-size" select="3" />
> > >> 
> > >><xsl:template match="/Parent">
> > >>   <xsl:variable name="n" select="count(node) -
> > >>(floor((count(node) div $group-size)) *
> > >>$group-size)"
> > >>/>
> > >>   
> > >>   <xsl:for-each select="node">
> > >>     <xsl:if test="(position() mod $group-size)
> =
> > >>0">
> > >>       group <xsl:value-of
> > select="floor(position()
> > >>div $group-size)" /><xsl:text> - </xsl:text>
> > >>       <xsl:for-each select=". |
> > >>preceding-sibling::node[position() &lt;=
> > >>($group-size
> > >>- 1)]">         
> > >>         <xsl:value-of select="." /><xsl:if
> > >>test="(position() mod $group-size) !=
> > >>0"><xsl:text>,</xsl:text></xsl:if>       
> > >>       </xsl:for-each>
> > >>       <xsl:text>
> > > 
> > > </xsl:text>
> > > 
> > >>     </xsl:if> 
> > >>     <xsl:if test="((position() = last()) and
> > >>((position() mod $group-size) != 0))">
> > >>       group <xsl:value-of
> > select="floor(position()
> > >>div $group-size) + 1" /><xsl:text> - </xsl:text>
> > >>       <xsl:for-each select=". |
> > >>preceding-sibling::node[position() &lt; $n]">
> > >>         <xsl:value-of select="." /><xsl:if
> > >>test="position() !=
> > >>last()"><xsl:text>,</xsl:text></xsl:if> 
> > >>       </xsl:for-each>
> > >>       <xsl:text>
> > > 
> > > </xsl:text>
> > > 
> > >>     </xsl:if>
> > >>   </xsl:for-each>
> > >></xsl:template>
> > >>   
> > >></xsl:stylesheet>
> > >>
> > >>I invoke Xalan like this:
> > >>java org.apache.xalan.xslt.Process -in file.xml
> > -xsl
> > >>file.xsl -PARAM group-size 2
> > >>
> > >>The output is fine for -PARAM group-size values
> of
> > >>1,2,3 & 4. But for -PARAM group-size values of 5
> > and
> > >>above, the ouput is not coming as expected. For
> > >>e.g.,
> > >>for -PARAM group-size 5, the output received is
> -
> > >>
> > >>group 1 - a,s,d,f,g
> > >>group 2 - h,
> > >>
> > >>I tested the same XSL with Saxon-SA 8.1.1 and
> > MSXSL
> > >>4,
> > >>and both produce correct result for all the
> cases.
> > >>Both Saxon and MSXSL produce the following
> output
> > >>for
> > >>group-size=5 -
> > >>
> > >>group 1 - a,s,d,f,g
> > >>group 2 - h,j,k,l
> > >>
> > >>Does this look like a Xalan bug?
> > >>
> > >>Regards,
> > >>Mukul
> > > 
> > > 
> > > 
> > > 
> > > 	
> > > 		
> > > __________________________________ 
> > > Do you Yahoo!? 
> > > Yahoo! Mail - You care about security. So do we.
> 
> > > http://promotions.yahoo.com/new_mail
> > > 
> > > 
> > > 
> > 
> > -- 
> > Geert.Josten@xxxxxxxxxxx
> > IT-consultant at Daidalos BV, Zoetermeer (NL)
> > 
> > http://www.daidalos.nl/
> > tel:+31-(0)79-3316961
> > fax:+31-(0)79-3316464
> > 
> > GPG: 1024D/12DEBB50
> 
> 
> 
> 		
> __________________________________ 
> Do you Yahoo!? 
> Yahoo! Mail - 250MB free storage. Do more. Manage
> less. 
> http://info.mail.yahoo.com/mail_250
> 
> 


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 

Current Thread