Subject: Re: [xsl] ordering and iteration problem From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx> Date: Fri, 16 Nov 2001 10:40:18 +0000 |
Hi Hector, > How would you modify your solution to accomodate Mark's XML file > modified as follows: [snip] > ..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) If I understand you correctly, each circuit-breaker-panel creates its own table containing just its child circuit-breaker elements. Some of the cells in that table might contain other tables for the nested circuit-breaker-panels. As you've seen, the keys will access *all* the circuit-breaker elements, no matter what circuit-breaker-panel they're on, so you need to change the keys so that you can quickly access only those within a particular circuit-breaker-panel. Since the circuit-breaker-panel elements don't have any kind of ID that you could use to identify them with, you have to make up an ID for them, which you can do with the generate-id() function. So I'd adapt the keys to include information about the parent circuit-breaker-panel of the circuit-breaker, as follows: <xsl:key name="breakers-by-column" match="b:circuit-breaker" use="concat(generate-id(parent::b:circuit-breaker-panel), ':', @column)" /> <xsl:key name="breakers" match="b:circuit-breaker" use="concat(generate-id(parent::b:circuit-breaker-panel), @row, ':', @column)" /> If a circuit-breaker-panel was given an ID of 'abc' then you could get the circuit breaker in the first cell in the first row with: key('breakers', 'abc:1:1') Then I'd change the arrangement of the templates slightly so that the template matched the circuit-breaker-panel in order to create the table, and so that it uses the new keys: <xsl:template match="b:circuit-breaker-panel"> <!-- store the ID of the panel --> <xsl:variable name="panel" select="generate-id()" /> <!-- work out the maximum rows for this table --> <xsl:variable name="max-rows">...</xsl:variable> <!-- work out the maximum columns for this table --> <xsl:variable name="max-cols">...</xsl:variable> <!-- store the right number of nodes for the rows in a variable --> <xsl:variable name="rows" select="$random-nodes[position() <= $max-row]" /> <!-- store the right number of nodes for the columns in a variable --> <xsl:variable name="columns" select="$random-nodes[position() <= $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($panel, ':', $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', concat($panel, ':', $col)) [@row < $row]" /> <!-- output an empty cell if there isn't one that overlaps --> <xsl:if test="not($column-breakers [@row + @height > $row])"> <td /> </xsl:if> </xsl:otherwise> </xsl:choose> </xsl:for-each> </xsl:for-each> </tr> </xsl:for-each> </table> </xsl:template> The template that gives the cell for the circuit breaker also needs to be different. I don't know whether you still want it to contain the value of the amps child of the circuit-breaker, but it needs to go on to process the circuit-breaker-panel child to create the nested table: <!-- template to give the cell for the circuit breaker --> <xsl:template match="b:circuit-breaker"> <td rowspan="{@height}"> <xsl:value-of select="b:amps" /> <!-- generate the nested table --> <xsl:apply-templates select="b:circuit-breaker-panel" /> </td> </xsl:template> I hope that helps, Jeni --- Jeni Tennison http://www.jenitennison.com/ XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] ordering and iteration pr, Hector Echegoyen | Thread | Re: [xsl] ordering and iteration pr, Mark Nahabedian |
RE: [xsl] xml 2 csv, Michael Kay | Date | RE: [xsl] MS XML Parser, Chris Bayes |
Month |