Easy way to alternate output with XSLT when not using templates or loops?

Discussion in 'XML' started by Michael Ahlers, Jul 12, 2004.

  1. Obviously if you're looping or using a template, choosing output based
    on the current iteration is easy. For example, if you're walking a
    set of elements and you want index % 2 == 0 produce one thing and
    another when that is not true. My question is, what if you are not
    looping through tags but want to achieve a similar effect without
    having to be excessively verbose? Is there any way that I can
    simplify the following block?

    <!-- ... -->
    <dt>
    <xsl:attribute name="class"><xsl:text>Even</xsl:text></xsl:attribute>
    <xsl:text>Sex</xsl:text>
    </dt>
    <dd>
    <xsl:attribute name="class"><xsl:text>Even</xsl:text></xsl:attribute>
    <xsl:value-of select="Sex"/>
    </dd>
    <dt>
    <xsl:attribute name="class"><xsl:text>Odd</xsl:text></xsl:attribute>
    <xsl:text>Height</xsl:text>
    </dt>
    <dd>
    <xsl:attribute name="class"><xsl:text>Odd</xsl:text></xsl:attribute>
    <xsl:value-of select="Height"/>
    </dd>
    <!-- ... -->

    That's particularly annoying if you want to insert an element anywhere
    other than the end of the list. You cannot modify variables, so
    incrementing as you walk along is not possible. I can't exactly loop
    because the name of the element is not necessarily human-friendly.
    Any ideas?
     
    Michael Ahlers, Jul 12, 2004
    #1
    1. Advertising

  2. (Michael Ahlers) wrote in message news:<>...
    > Is there any way that I can
    > simplify the following block?
    >
    > <!-- ... -->
    > <dt>
    > <xsl:attribute name="class"><xsl:text>Even</xsl:text></xsl:attribute>
    > <xsl:text>Sex</xsl:text>
    > </dt>
    > <dd>
    > <xsl:attribute name="class"><xsl:text>Even</xsl:text></xsl:attribute>
    > <xsl:value-of select="Sex"/>
    > </dd>
    > <dt>
    > <xsl:attribute name="class"><xsl:text>Odd</xsl:text></xsl:attribute>
    > <xsl:text>Height</xsl:text>
    > </dt>
    > <dd>
    > <xsl:attribute name="class"><xsl:text>Odd</xsl:text></xsl:attribute>
    > <xsl:value-of select="Height"/>
    > </dd>


    If Sex and Height (or whatever data) are the only child elements of the context:

    <xsl:for-each select="*"><!-- or maybe select="Sex|Height|whatever..." -->
    <xsl:variable name="even-or-odd">
    <xsl:choose>
    <xsl:when test="position() mod 2 = 0">
    <xsl:text>Even</xsl:text>
    </xsl:when>
    <xsl:eek:therwise>
    <xsl:text>Odd</xsl:text>
    </xsl:eek:therwise>
    </xsl:choose>
    </xsl:variable>
    <dt class="{$even-or-odd}">
    <xsl:value-of select="name()"/>
    </dt>
    <dd class="{$even-or-odd}">
    <xsl:value-of select="."/>
    </dd>
    </xsl:for-each>

    --
    Robin Johnson
    http://www.robinjohnson.f9.co.uk - rj at robinjohnson dot f9 dot co dot uk
    "The labours of men of genius, however erroneously directed, scarcely ever fail
    in contributing ultimately to the solid advantage of mankind." - Mary Shelley
     
    Robin Johnson, Jul 15, 2004
    #2
    1. Advertising

  3. > If Sex and Height (or whatever data) are the only child
    > elements of the context:


    It would be extremely convenient I only had those two tags since this
    whole thing would be effortless. The problem is, I only took a snippet
    of my code to demonstrate what I am shooting for. Also, I have no
    guarantee that the element names are suitable for user output, so I have
    to supply them myself in the XSLT. Thanks for your response though.

    *** Sent via Developersdex http://www.developersdex.com ***
    Don't just participate in USENET...get rewarded for it!
     
    Michael Ahlers, Jul 15, 2004
    #3
  4. (Michael Ahlers) writes:

    >
    > <!-- ... -->
    > <dt>
    > <xsl:attribute name="class"><xsl:text>Even</xsl:text></xsl:attribute>
    > <xsl:text>Sex</xsl:text>
    > </dt>
    > <dd>
    > <xsl:attribute name="class"><xsl:text>Even</xsl:text></xsl:attribute>
    > <xsl:value-of select="Sex"/>
    > </dd>
    > <dt>
    > <xsl:attribute name="class"><xsl:text>Odd</xsl:text></xsl:attribute>
    > <xsl:text>Height</xsl:text>
    > </dt>
    > <dd>
    > <xsl:attribute name="class"><xsl:text>Odd</xsl:text></xsl:attribute>
    > <xsl:value-of select="Height"/>
    > </dd>
    > <!-- ... -->
    >


    The above is written in a very verbose style, you could write it
    equivalently as



    <!-- ... -->
    <dt class="even">Sex</dt>
    <dd class="even">
    <xsl:value-of select="Sex"/>
    </dd>
    <dt class="odd">Height</dt>
    <dd class="odd">
    <xsl:value-of select="Height"/>
    </dd>
    <!-- ... -->

    or if you want to loop over arbitrary child elements

    <xsl:for-each select="*">
    <dt class="even">
    <xsl:if test="position() mod 2 = 1">
    <xsl:attribute name="class">odd</xsl:attribute>
    </xsl:if>
    <xsl:apply-templates mode="name" select="."/>
    </dt>
    <dd class="even">
    <xsl:if test="position() mod 2 = 1">
    <xsl:attribute name="class">odd</xsl:attribute>
    </xsl:if>
    <xsl:apply-templates select="."/>
    </dd>
    </xsl:for-each>


    for names you can have a default of

    <xsl:template mode="name" match="*">
    <xsl:value-of select="name()"/>
    </xsl:template>

    together with overrides where needed:

    <xsl:template mode="name" match="Sex">
    <xsl:text>seX</xsl:text>
    </xsl:template>


    David
     
    David Carlisle, Jul 15, 2004
    #4
    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. JKop
    Replies:
    3
    Views:
    479
  2. Chris
    Replies:
    2
    Views:
    702
    Chris
    Mar 4, 2007
  3. recover
    Replies:
    2
    Views:
    813
    recover
    Jul 25, 2006
  4. Replies:
    10
    Views:
    342
    Sean O'Halpin
    Jul 17, 2006
  5. Me
    Replies:
    2
    Views:
    247
Loading...

Share This Page