xsl-list
[Top] [All Lists]

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

2008-06-06 09:15:38
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(_at_)lists(_dot_)mulberrytech(_dot_)com
From: Martin Honnen <Martin(_dot_)Honnen(_at_)gmx(_dot_)de>
Subject: Re: [xsl] two at a time, using a sequence expression
Message-ID: <48481556(_dot_)9080209(_at_)gmx(_dot_)de>

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(_at_)lists(_dot_)mulberrytech(_dot_)com>
From: "Michael Kay" <mike(_at_)saxonica(_dot_)com>
Subject: RE: [xsl] two at a time, using a sequence expression
Message-ID: <62425D6AAB9D46168585B9F310563558(_at_)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(_dot_)cavalieri(_at_)gmail(_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>