Subject: Re: [xsl] Referencing nodes from an out-of-scope xsl:for-each loop From: Adam Turoff <ziggy@xxxxxxxxx> Date: Thu, 17 May 2001 21:49:49 -0400 |
On Thu, May 17, 2001 at 01:59:18PM -0700, Joel P Thornton wrote: > I have this xml: > > -- > <sql-recordset> > <row title="Sunshine Home" location="Seattle WA"/> > <row title="Value Village" location="Seattle WA"/> > <row title="Salvation Army" location="Tacoma WA"/> > > <display-columns> > <column label="Name"><B><sql-field name="title"/></B></column> > <column label="Location"><sql-field name="location"/></column> > </display-columns> > </sql-recordset> > -- > > And I want to write an XSL which will transform this into: > > -- > <table> > <th>Name</th> > <th>Location</th> > > <tr> > <td><b>Sunshine Home</b></td><td>Seattle WA</td> > </tr> ... > </table> > -- > > > Currently, I <xsl:for-each> through the collection of <row> nodes, and then > <xsl:for-each> through each of the <column>s for each row. The problem is, > I have a <xsl:template match="sql-field"> template which matches the > <sql-field> tags within the <column> tags. But I don't know how to get that > template to "know" which row it is currently on. I tried using > <xsl:variable> but I'm being told that, within the sql-field template, the > variable is out of scope. > > Ideas? First you need to get into a state where you have the tree fragment of rows as well as the tree fragment of columns. This can be done using <xsl:call-template> for <row>, passing a tree fragment for <display-columns> as a parameter. Once you've cracked that nut, it's a simple case of referring to both nodesets at the same time. :-) The really tricky part is respecting the bolding with <column label="Name"><B><sql-field name="title"/></B></column> as well as no formatting <column label="Location"><sql-field name="location"/></column> It took some trickery to get that working. You should consider a different way for specifying HTML styles to be output, such as putting a style='' attribute on <column> and passing it through to <td>. <xsl:template match="sql-recordset"> <xsl:variable name="display-columns" select="display-columns"/> <!-- table header (simple) --> <table> <tr> <xsl:for-each select="display-columns/column/@label"> <th><xsl:value-of select="."/></th> </xsl:for-each> </tr> <!-- table rows (passing the display format as a parameter --> <xsl:for-each select="row"> <xsl:call-template name="display-row"> <xsl:with-param name="display-columns" select="$display-columns"/> </xsl:call-template> </xsl:for-each> </table> </xsl:template> <!-- Emit the current <row/> as specified --> <xsl:template name="display-row"> <xsl:param name="display-columns"/> <!-- save the tree fragment for the row we're processing --> <xsl:variable name="row" select="."/> <tr> <!-- now loop over the column display order --> <xsl:for-each select="$display-columns/column//sql-field"> <xsl:variable name="column" select="@name"/> <td> <!-- HACK: Respect <b> surrounding <sql-field> --> <xsl:choose> <xsl:when test="name(..) != 'column'"> <xsl:element name="{name(..)}"> <xsl:value-of select="$row/attribute::*[name()=$column]"/> </xsl:element> </xsl:when> <xsl:otherwise> <!-- standard case: just emit the data --> <xsl:value-of select="$row/attribute::*[name()=$column]"/> </xsl:otherwise> </xsl:choose> </td> </xsl:for-each> </tr> </xsl:template> (I suppose you could do the same thing matching on <row> with a lot of ancestor hacking, but I only thought of that after I got this pair of templates working.) Z. XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
[xsl] Referencing nodes from an out, Joel P Thornton | Thread | Re: [xsl] Referencing nodes from an, Jeni Tennison |
[xsl] How to simplify the xslt expr, Yang | Date | Re: [xsl] xpath expression, Dan Diebolt |
Month |