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

M

Michael Ahlers

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?
 
R

Robin Johnson

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>
 
M

Michael Ahlers

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.
 
D

David Carlisle

<!-- ... -->
<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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,997
Messages
2,570,239
Members
46,827
Latest member
DMUK_Beginner

Latest Threads

Top