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

Re: ordering and iteration problem

Subject: Re: ordering and iteration problem
From: "Hector Echegoyen" <hechegoyen@xxxxxxxxxxx>
Date: Thu, 15 Nov 2001 16:24:44 -0500
hector echegoyen

Hi Jeni,


How would you modify your solution to accomodate Mark's XML file modified as follows:

<circuit-breaker-panel var="888">
	<circuit-breaker column="1" row="1" height="2">
		<amps>60</amps>
		<special>doubled</special>
		<description>heat pump</description>
		<circuit-breaker-panel>
			<circuit-breaker column="1" row="1" height="1">
				<amps>99</amps>
				<description>the upper stairs</description>
			</circuit-breaker>
		</circuit-breaker-panel>
	</circuit-breaker>
	<circuit-breaker column="1" row="3" height="1">
		<amps>15</amps>
		<description>upper stairs</description>
	</circuit-breaker>
	<circuit-breaker column="2" row="7" height="1">
		<amps>15</amps>
		<description/>
	</circuit-breaker>
	<circuit-breaker column="2" row="8" height="2">
		<amps>20</amps>
		<special>doubled</special>
		<description/>
	</circuit-breaker>
</circuit-breaker-panel>


..the difference is that now there could be a nested table of Circuit Breakers. Using the "key" function in your stylesheet does not provide that kind of output. I'm looking to still do recursion within a cell to look for a nested table there (N levels down)


Thanks,

Hector.


Jeni Tennison Wrote: ------------------------

Hi Mark,

My thinking is that I need to do something like

   for each row
       for each column
           ooutput the <circuit-breaker> with that row and column

I'd probably do this using the Piez Method/Hack of having an xsl:for-each iterate over the correct number of random nodes and using the position of the node to give the row/column number.

You need to define some random nodes - I usually use nodes from the
stylesheet:

<xsl:variable name="random-nodes" select="document('')//node()" />

And since you'll be iterating over them, you need some way of getting
back to the data:

<xsl:variable name="data" select="/" />

I've used two keys to get the relevant circuit breakers quickly. One
just indexes them by column (this is so you can work out whether you
need to add a cell or whether there's a circuit breaker from higher in
the column that covers it). The other indexes them by row and column.

<xsl:key name="breakers-by-column" match="b:circuit-breaker"
        use="@column" />
<xsl:key name="breakers" match="b:circuit-breaker"
        use="concat(@row, ':', @column)" />

I've assumed that you've stored the maximum number of rows in a
global variable called $max-row and the maximum number of columns in a
global variable called $max-col.  Here's the template that does the
work:

<xsl:template match="/">
<!-- store the right number of nodes for the rows in a variable -->
<xsl:variable name="rows"
select="$random-nodes[position() &lt;= $max-row]" />
<!-- store the right number of nodes for the columns in a variable
-->
<xsl:variable name="columns"
select="$random-nodes[position() &lt;= $max-col]" />
<!-- create the table -->
<table>
<!-- iterate over the right set of nodes to get the rows -->
<xsl:for-each select="$rows">
<!-- store the row number -->
<xsl:variable name="row" select="position()" />
<!-- create the row -->
<tr>
<!-- iterate over the right set of nodes to get the
columns -->
<xsl:for-each select="$columns">
<!-- store the column number -->
<xsl:variable name="col" select="position()" />
<!-- change the current node so that the key works -->
<xsl:for-each select="$data">
<!-- identify the relevant circuit breaker -->
<xsl:variable name="breaker"
select="key('breakers',
concat($row, ':', $col))" />
<xsl:choose>
<!-- if there is one, apply templates to get the
table cell -->
<xsl:when test="$breaker">
<xsl:apply-templates select="$breaker" />
</xsl:when>
<xsl:otherwise>
<!-- find other breakers that start higher in
the column -->
<xsl:variable name="column-breakers"
select="key('breakers-by-column', $col)
[@row &lt; $row]" />
<!-- output an empty cell if there isn't one
that overlaps -->
<xsl:if test="not($column-breakers
[@row + @height &gt; $row])">
<td />
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
</xsl:template>


<!-- template to give the cell for the circuit breaker -->
<xsl:template match="b:circuit-breaker">
  <td rowspan="{@height}">
     <xsl:value-of select="b:amps" />
  </td>
</xsl:template>

If you don't like the 'one big template' approach, then you could
split it down by applying templates to the row and column nodes in
'row' and 'column' modes to distinguish between the two.

I hope that helps,

Jeni



_________________________________________________________________
Get your FREE download of MSN Explorer at http://explorer.msn.com/intl.asp


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.