This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Table styling


Hi Arup,

> As I am rendering table of three colomns,my problem is when I am
> looping for services to create new row It creates first row
> correctly but for second row instead of going to position 4 of
> services it goes to second position and so on . Can any one suggest
> where I am making mistake or correction in Xsl or in code.

The problem is at the point where you select the
'current_row_services'. Currently, the code for creating the content
of the table is as follows:

  <xsl:for-each select="$all_services[position() mod $cols = 1]">
    <xsl:variable name="this_services_pos" select="position()"/>
    <xsl:variable name="current_row_services"
      select="$all_services[position() &gt;= $this_services_pos and
                            position() &lt; $this_services_pos + $cols]" />
    <!-- go generate the 2 table rows for this one data row -->
    <xsl:call-template name="make_table_rows">
      <xsl:with-param name="cols" select="$cols"/>
      <xsl:with-param name="current_row_services"
                      select="$current_row_services"/>
    </xsl:call-template>
  </xsl:for-each>

The xsl:for-each here selects the services numbered 1, 4, 7 and so on
in the whole list of services.

This filtered list of services becomes the current node list within
the xsl:for-each. The first node processed (whose position is 1 in the
xsl:for-each) is the first of all the services; the second node
processed (whose position is 2 in the xsl:for-each) is the fourth of
all the services; the third node processed (whose position is 3 in the
xsl:for-each) is the seventh of all the services and so on.

In other words, the $this_services_pos variable takes the values 1, 2,
3 and so on and *not* 1, 4, 7 etc. Which is why the code that you have
isn't working.

But rather than show you how to get what you have working, I'll show
you a different, and more efficient method, to work out which services
elements should be passed to the make_table_rows template.

As we've seen, with your xsl:for-each as it stands, you're getting the
first, fourth, seventh and so on services element within the document.
You know that these services elements are the first services element
to be shown within the row. The other services elements are siblings
of these. In fact, the other services elements that you want to
display within the row are the two following siblings of the services
element that you're on.

So rather than accessing the other services elements by index, you can
step from these selected services elements to their following siblings
through the following-siblings axis, as follows:

  <xsl:for-each select="$all_services[position() mod $cols = 1]">
  
    <xsl:variable name="current_row_services"
      select=". | following-sibling::services[position() &lt; $cols]" />
      
    <!-- go generate the 2 table rows for this one data row -->
    <xsl:call-template name="make_table_rows">
      <xsl:with-param name="cols" select="$cols"/>
      <xsl:with-param name="current_row_services"
                      select="$current_row_services"/>
    </xsl:call-template>
  </xsl:for-each>

This is more efficient because the processor will only have to visit
three nodes to create the list of nodes that you're after, rather than
trawling through the entire list of services to find those with the
correct position.

---

These grouping by position problems are slightly assisted with the
xsl:for-each-group element proposed for XSLT 2.0. An equivalent to
the above code, in XSLT 2.0, would be:

  <xsl:for-each-group select="$all_services"
                      group-starting-with="position() mod $cols = 1">
  
    <xsl:variable name="current_row_services"
                  select="current-group()" />
      
    <!-- go generate the 2 table rows for this one data row -->
    <xsl:call-template name="make_table_rows">
      <xsl:with-param name="cols" select="$cols"/>
      <xsl:with-param name="current_row_services"
                      select="$current_row_services"/>
    </xsl:call-template>
  </xsl:for-each>

It's not *extremely* user-friendly, given the number of times people
want to group by position. I wonder whether a group-number would be
more helpful - an attribute value template perhaps:

  <xsl:for-each-group select="$all_services"
                      group-number="{$cols}">
  
    <xsl:variable name="current_row_services"
                  select="current-group()" />
      
    <!-- go generate the 2 table rows for this one data row -->
    <xsl:call-template name="make_table_rows">
      <xsl:with-param name="cols" select="$cols"/>
      <xsl:with-param name="current_row_services"
                      select="$current_row_services"/>
    </xsl:call-template>
  </xsl:for-each>
  
Cheers,

Jeni

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


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]