xsl-list
[Top] [All Lists]

RE: xslt node-set variable transversal

2004-03-31 12:43:04
-----Original Message-----
From: Kyle Partridge [mailto:kpartridge(_at_)mathsoft(_dot_)com]

<snip />
I know that all the preceding and following siblings of "region" will be
available from inside the template I'm calling.  But the problem is, I
ONLY want to process "region" nodes that belong within the column I'm
processing.


Hi,

So, if I get correctly, you probably want to go for some form of grouping,
making groups of regions that reflect the columns grouped over the
pages --ultimately determined by the left attribute and the
usable-page-width...

If you have this (made numbers of the attributes for convenience; you'll
have to play a little with substring-before() if you want to work around the
units)

As a further convenience, assumed nothing WRT rows / top as yet

<root>
<page usable-width="493" />
<regions>
      <region left="36" .../>
      <region left="120" .../>
      <region left="630" .../>
      <region left="230" .../>
     ...
</regions>
</root>

What 'division' do you want to see happening? Is it something like:

regions 1, 2 and 4 on page 1
region 3 on page 2

Maybe you could use keys to be able to select the regions by starting- or
ending-page:

<xsl:key name="region-by-start-page" match="region"
         use="floor( 1 +
           (@left div /root/page/@usable-width ) )" />

<xsl:key name="region-by-end-page" match="region"
         use="floor( 1 +
           ( (@left+(_at_)width) div /root/page/@usable-width ) )" />

This bit would give you the region that ends the last page (using an
extension function):

<xsl:variable name="sorted-regions">
  <xsl:for-each select="/root/regions/region">
    <xsl:sort select="@left+(_at_)width" data-type="number"
              order="descending" />
    <xsl:copy-of select="." />
  </xsl:for-each>
</xsl:variable>

<xsl:variable name="end-region"
              select="ext:node-set($sorted-regions)[1]" />

Then this will get you its page-number:

<xsl:variable name="last-page"
              select="floor( 1 +
                (($end-region/@left + $end-region/@width)
                  div /root/page/@usable-width))" />

Since you know beforehand that there's always going to be more regions than
pages, use the last-page variable in  code like:

<xsl:template match="root">
  <xsl:for-each select="regions/region[position() &lt;= $last-page]">
    <xsl:variable name="page-count" select="position()" />
    <xsl:apply-templates select="page">
      <xsl:with-param name="current-page" select="$page-count" />
    </xsl:apply-templates>
  </xsl:for-each>
</xsl:template>

<xsl:template match="page">
  <xsl:param name="current-page" select="0" />
  <xsl:apply-templates select="key('region-by-start-page',$current-page)">
    <xsl:with-param name="current-page" select="$current-page" />
  </xsl:apply-templates>
</xsl:template>

Now, in the region-matching template, you will only have to deal with
preceding- and following-siblings that are already on the same page... so
when you 'reach' the second region, the immediately following-sibling from
there is the fourth in the original source tree. If you need to query
regions that end on the previous page, you can do so by using the key inside
the matching template, and supplying it the value of the previous page,
like:

<xsl:template match="region">
  <xsl:param name="current-page" select="0" />
  ...
  <xsl:variable name="prev-page-regions"
                select="key('region-by-end-page',$current-page - 1)" />

</xsl:template>


IIC all the above should break the regions down into manageable chunks.
Using the keys you can easily get to regions that haven't been included in
the context node, so...

Hope this helps!

Cheers,

Andreas



<Prev in Thread] Current Thread [Next in Thread>