RE: [xsl] two at a time, using a sequence expression

Subject: RE: [xsl] two at a time, using a sequence expression
From: "John Cavalieri" <john.cavalieri@xxxxxxxxx>
Date: Fri, 6 Jun 2008 11:15:09 -0500
Hi Martin, Michael,

Thanks for the suggestions.  I knew my attempt looked clunky.

Michael, you are right, there is no divide by zero in my example.  I
was mixed up with a zero count divided by 2 (flip flopped in my head),
which of course isn't an issue.

-John

> Date: Thu, 05 Jun 2008 18:33:26 +0200
> To:  xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> From: Martin Honnen <Martin.Honnen@xxxxxx>
> Subject: Re: [xsl] two at a time, using a sequence expression
> Message-ID: <48481556.9080209@xxxxxx>
>
> John Cavalieri wrote:
>
> >   <xsl:template match="/pairs">
> >     <xsl:copy>
> >       <xsl:for-each select="for $i in 1 to (count(*) idiv 2 +
> > (count(*) mod 2)) return *[($i*2)-1]">
> >         <pair>
> >           <xsl:copy-of select="." />
> >           <xsl:copy-of select="./following-sibling::*[1]" />
> >         </pair>
> >       </xsl:for-each>
> >     </xsl:copy>
> >   </xsl:template>
>
> Doesn't the following suffice to achieve the same result?
>
>   <xsl:template match="/pairs">
>     <xsl:copy>
>       <xsl:for-each select="*[position() mod 2 = 1]">
>         <pair>
>           <xsl:copy-of select="."/>
>           <xsl:copy-of select="following-sibling::*[1]"/>
>         </pair>
>       </xsl:for-each>
>     </xsl:copy>
>   </xsl:template>
>
> --
>
>        Martin Honnen
>        http://JavaScript.FAQTs.com/
>
> ------------------------------
>
> Date: Thu, 5 Jun 2008 22:58:18 +0100
> To: <xsl-list@xxxxxxxxxxxxxxxxxxxxxx>
> From: "Michael Kay" <mike@xxxxxxxxxxxx>
> Subject: RE: [xsl] two at a time, using a sequence expression
> Message-ID: <62425D6AAB9D46168585B9F310563558@Sealion>
>
> > I'm curious if there is a more elegant way to use a sequence
> > expression to process two adjacent elements at a time.  With
> > XSLT 1.0 I would have used recursion, but with XSLT/XPath 2.0
> > I'm wondering if I can exploit sequences.  Below is something
> > I've come up with so far.
>
> >       <xsl:for-each select="for $i in 1 to (count(*) idiv 2 +
> > (count(*) mod 2)) return *[($i*2)-1]">
> >         <pair>
> >           <xsl:copy-of select="." />
> >           <xsl:copy-of select="./following-sibling::*[1]" />
> >         </pair>
> >       </xsl:for-each>
>
> It seems to me that you can either write code that assumes you're working
> with a sequence of siblings, or you can write code that works with an
> arbitrary sequence. For sibling elements, the following works just fine:
>
> <xsl:for-each select="*[position() mod 2 = 1]">
>  <pair>
>    <xsl:copy-of select="., following-sibling::*[1]" />
>  </pair>
> </xsl:for-each>
>
> If you want to work with an arbitrary sequence $SEQ (not necessarily
> siblings), try
>
> <xsl:for-each select="1 to count($SEQ)[. mod 2 = 1]">
>  <xsl:variable name="p" select="."/>
>  <pair>
>    <xsl:copy-of select="$SEQ[$p], $SEQ[$p+1]" />
>  </pair>
> </xsl:for-each>
>
> Alternatively of course there is
>
> <xsl:for-each-group select="$SEQ" group-adjacent="(position()-1) idiv 2">
>  <pair>
>    <xsl:copy-of select="current-group()"/>
>  </pair>
> </xsl:for-each-group>
>
> >
> > An interesting side note, I thought the sequence expression
> > would error because of divide by zero, but it appears to be
> > side effect free, at least with Saxon.
>
> I can't see where you think you might be dividing by zero.
>
> Michael Kay
> http://www.saxonica.com/
>
> ------------------------------


--
John Cavalieri
john.cavalieri@xxxxxxxxx

Current Thread