This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Re: Referencing nodes from an out-of-scope xsl:for-each loop
- To: "Xsl-List" <xsl-list at lists dot mulberrytech dot com>
- Subject: Re: [xsl] Referencing nodes from an out-of-scope xsl:for-each loop
- From: "Joel P Thornton" <joelt at tlchoices dot com>
- Date: Fri, 18 May 2001 10:57:18 -0700
- Reply-To: xsl-list at lists dot mulberrytech dot com
Adam Turoff wrote:
---
[excellent solution here]
(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.
---
Adam - Thanks for your thoughtful response. It still isn't quite there yet,
though; when you mentioned the <B> style information within the <column>
tags being a problem, you were right.
I gave this as a relatively simple example of what I'm hoping to achieve:
<display-columns>
<column label="Name"><B><sql-field name="title"/></B></column>
<column label="Location"><sql-field name="location"/></column>
</display-columns>
But I am really wanting to do more complex stuff, such as this:
<display-columns>
<column label="Name">
<link>
<label>
<B><sql-field name="title"/></B>
</label>
<href>
/viewarea.asp?where=<sql-field name="location"/>
</href>
</link>
</column>
</display-columns>
.. in this way permitting versatile display formatting options while
minimizing xsl work.
Can this be done? I'd love to hear suggestions .. and thanks for those so
far :)
joel
=======================================
---------------------------------------
> 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