[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: alternate row color in a table

Subject: Re: alternate row color in a table
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Mon, 18 Feb 2002 12:14:56 +0000
alternative row color
Hi Sébastien,

> I have different xml like this one and sometimes element <info1> or
> <info2> or <info3> or <info4> may be not present.
>
> In this case it seems to be impossible to use a test with position()
> mod 2.

As it stands, you're outputting a row for each of the relevant nodes
whether or not they exist; I guess that you are talking about what to
do if the rows themselves are optional.

You can use position() mod 2 as long as you can create a node set that
holds the nodes that you want to use to create the rows, and can sort
them in the order in which you want them to appear.

In your case, the node set that holds the nodes you want to appear in
the table can be created with the path:

  info3 | info2/@type | info4/subinfo

To sort them, in order to get the ordering that you want, you need to
create a series of xsl:sorts that sort first by whether the node is an
info3 element, then by whether it's a type attribute on an info2
element, then by whether it's a subinfo element on a info4 element,
which you can do with:

  <xsl:for-each select="info3 | info2/@type | info4/subinfo">
    <xsl:sort select="self::info3" order="descending" />
    <xsl:sort select="parent::info2 and not(self::node()) and
                      name() = 'type'" order="descending" />
    <xsl:sort select="parent::info4 and self::subinfo"
              order="descending" />
    <tr class="color{position() mod 2}">
      <td><xsl:value-of select="." /></td>
    </tr>
  </xsl:for-each>

An alternative is to create the rows first, and then add the required
colour afterwards. For that, you need a node-set() extension function,
but they're not hard to find...

  <xsl:variable name="rows">
    <xsl:if test="info3">
      <tr><td><xsl:value-of select="info3"/></td></tr>
    </xsl:if>
    <xsl:if test="info2/@type">
      <tr><td><xsl:value-of select="info2/@type"/></td></tr>
    </xsl:if>
    <xsl:if test="info4/subinfo">
      <tr><td><xsl:value-of select="info4/subinfo"/></td></tr>
    </xsl:if>
  </xsl:variable>
  <xsl:for-each select="exsl:node-set($rows)/tr">
    <tr class="color{position() mod 2}">
      <xsl:copy-of select="node()" />
    </tr>
  </xsl:for-each>

---

This gets a lot easier in XSLT 2.0, since you can construct a sequence
that holds the nodes in the order you want them in the first place, as
follows:

  <xsl:for-each select="(info3, info2/@type, info4/subinfo)">
    <tr class="color{position() mod 2}">
      <td><xsl:value-of select="." /></td>
    </tr>
  </xsl:for-each>

Cheers,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.