for-each and incrementing by the count() function

Discussion in 'XML' started by Ken, Jul 15, 2003.

  1. Ken

    Ken Guest

    The fact that you can not reassign a variable in XSL is an endless
    source of frustration, causing you to jump through all sorts of
    non-intuitive hoops.

    In this case, however, the lack of reassignment has me totally
    perplexed on how to achieve a solution to the following problem:

    (These are illustrative fragments)

    XML:

    <item id="0" name="item0">
    <event description="item0_event0"/>
    <event description="item0_event1"/>
    </item>
    <item id="1" name="item1">
    <event description="item1_event0"/>
    <event description="item1_event1"/>
    </item>

    XSL: (Incorrect, this is what I'm trying to figure out)

    <xsl:for-each select="item">
    <xsl:variable name="baseRow" select="position()"/>
    <row>
    <xsl:attribute name="index"><xsl:value-of
    select="$baseRow"/></xsl:attribute>
    <cell index="0">
    <xsl:value-of select="@id"/>
    </cell>
    <cell index="1">
    <xsl:value-of select="@name"/>
    </cell>
    </row>
    <xsl:for-each select="event">
    <row>
    <xsl:attribute name="index"><xsl:value-of select="$baseRow
    + position()"/></xsl:attribute>
    <cell index="0">
    <xsl:value-of select="@description"/>
    </cell>
    </row>
    </xsl:for-each>
    <!-- <xsl:variable name="baseRow" select="$baseRow +
    count(event)"/> --> <!-- Pseudocode -->
    </xsl:for-each>

    DESIRED OUTPUT AFTER XFORM:

    <row index="0">
    <cell index="0">0</cell>
    <cell index="1">item0</cell>
    </row>
    <row index="1">
    <cell index="0">item0_event0"</cell>
    </row>
    <row index="2">
    <cell index="0">item0_event1"</cell>
    </row>
    <row index="3">
    <cell index="0">1</cell>
    <cell index="1">item1</cell>
    </row>
    <row index="4">
    <cell index="0">item1_event0"</cell>
    </row>
    <row index="5">
    <cell index="0">item1_event1"</cell>
    </row>

    Notice how the row index is continuously incremented. This is my
    desired output, however I cannot figure out how to accomplish it.
    Essentially I like to increment the base position() of the first
    for-each by the count() of the second for-each at the end of the first
    loop.

    Thanks for any insight you can provide.
    Ken, Jul 15, 2003
    #1
    1. Advertising

  2. This is easy and straightforward.

    This transformation:

    <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:eek:utput omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="item | event">
    <xsl:variable name="vRowInd">
    <xsl:number count="item | event" level="any"/>
    </xsl:variable>
    <row index="{$vRowInd - 1}">
    <xsl:for-each select="@*">
    <cell index="{position() - 1}">
    <xsl:value-of select="."/>
    </cell>
    </xsl:for-each>
    </row>
    <xsl:apply-templates/>
    </xsl:template>
    </xsl:stylesheet>


    when applied on your source.xml:

    <items>
    <item id="0" name="item0">
    <event description="item0_event0"/>
    <event description="item0_event1"/>
    </item>
    <item id="1" name="item1">
    <event description="item1_event0"/>
    <event description="item1_event1"/>
    </item>
    </items>

    produces the wanted result:

    <row index="0">
    <cell index="0">0</cell>
    <cell index="1">item0</cell>
    </row>
    <row index="1">
    <cell index="0">item0_event0</cell>
    </row>
    <row index="2">
    <cell index="0">item0_event1</cell>
    </row>
    <row index="3">
    <cell index="0">1</cell>
    <cell index="1">item1</cell>
    </row>
    <row index="4">
    <cell index="0">item1_event0</cell>
    </row>
    <row index="5">
    <cell index="0">item1_event1</cell>
    </row>


    Hope this helped.


    =====
    Cheers,

    Dimitre Novatchev.
    http://fxsl.sourceforge.net/ -- the home of FXSL

    "Ken" <> wrote in message
    news:...
    > The fact that you can not reassign a variable in XSL is an endless
    > source of frustration, causing you to jump through all sorts of
    > non-intuitive hoops.
    >
    > In this case, however, the lack of reassignment has me totally
    > perplexed on how to achieve a solution to the following problem:
    >
    > (These are illustrative fragments)
    >
    > XML:
    >
    > <item id="0" name="item0">
    > <event description="item0_event0"/>
    > <event description="item0_event1"/>
    > </item>
    > <item id="1" name="item1">
    > <event description="item1_event0"/>
    > <event description="item1_event1"/>
    > </item>
    >
    > XSL: (Incorrect, this is what I'm trying to figure out)
    >
    > <xsl:for-each select="item">
    > <xsl:variable name="baseRow" select="position()"/>
    > <row>
    > <xsl:attribute name="index"><xsl:value-of
    > select="$baseRow"/></xsl:attribute>
    > <cell index="0">
    > <xsl:value-of select="@id"/>
    > </cell>
    > <cell index="1">
    > <xsl:value-of select="@name"/>
    > </cell>
    > </row>
    > <xsl:for-each select="event">
    > <row>
    > <xsl:attribute name="index"><xsl:value-of select="$baseRow
    > + position()"/></xsl:attribute>
    > <cell index="0">
    > <xsl:value-of select="@description"/>
    > </cell>
    > </row>
    > </xsl:for-each>
    > <!-- <xsl:variable name="baseRow" select="$baseRow +
    > count(event)"/> --> <!-- Pseudocode -->
    > </xsl:for-each>
    >
    > DESIRED OUTPUT AFTER XFORM:
    >
    > <row index="0">
    > <cell index="0">0</cell>
    > <cell index="1">item0</cell>
    > </row>
    > <row index="1">
    > <cell index="0">item0_event0"</cell>
    > </row>
    > <row index="2">
    > <cell index="0">item0_event1"</cell>
    > </row>
    > <row index="3">
    > <cell index="0">1</cell>
    > <cell index="1">item1</cell>
    > </row>
    > <row index="4">
    > <cell index="0">item1_event0"</cell>
    > </row>
    > <row index="5">
    > <cell index="0">item1_event1"</cell>
    > </row>
    >
    > Notice how the row index is continuously incremented. This is my
    > desired output, however I cannot figure out how to accomplish it.
    > Essentially I like to increment the base position() of the first
    > for-each by the count() of the second for-each at the end of the first
    > loop.
    >
    > Thanks for any insight you can provide.
    Dimitre Novatchev, Jul 16, 2003
    #2
    1. Advertising

  3. Ken

    Ken Guest

    Dimitre,

    Thanks for taking the time to help. The union operator is something
    that I'd seen before, but I wasn't able to piece that together with
    xsl:number to solve my problem.

    XSL (and other functional languages) are a different species of
    language than Java/C++, and as I learn XSL, I have to remember to set
    aside my previous ways of thinking about solving problems.
    Ken, Jul 16, 2003
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. John Wilkinson

    XSLT incrementing count

    John Wilkinson, Sep 5, 2005, in forum: XML
    Replies:
    2
    Views:
    1,506
    toudidel
    Sep 6, 2005
  2. pozz
    Replies:
    10
    Views:
    495
  3. bthumber

    Incrementing a count

    bthumber, May 29, 2009, in forum: ASP .Net
    Replies:
    1
    Views:
    372
    Alexey Smirnov
    May 29, 2009
  4. Pat Maddox
    Replies:
    6
    Views:
    141
    Marcin Mielżyński
    Jan 20, 2006
  5. Igor Nn
    Replies:
    7
    Views:
    426
    Johnny Morrice
    May 28, 2011
Loading...

Share This Page