This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Re: Hopefully not a terribly silly question
- From: Wendell Piez <wapiez at mulberrytech dot com>
- To: xsl-list at lists dot mulberrytech dot com
- Date: Thu, 03 Jan 2002 13:42:17 -0500
- Subject: Re: [xsl] Hopefully not a terribly silly question
- References: <20020103162337.51519.qmail@web14508.mail.yahoo.com>
- Reply-to: xsl-list at lists dot mulberrytech dot com
Morgan,
At 12:21 PM 1/3/02, you wrote:
>I am trying to iterate through each of the rows, then each of the
>columns. If I am not in the first column then I want to get a hold of the
>name attribute from the first row and apply it.
...
>Unfortunately, I get a the literal string result of the concat()
>function, instead of the actual data value. Is there some sort of eval()
>function that I need to use? Am I approaching this incorrectly?
Yes, unfortunately you are. You can't construct an XPath dynamically and
then evaluate it within your stylesheet. (See other threads ongoing about
whether exactly this feature should be added to the language in a later
version.)
There are several other ways to do what you want, however. The one I'd use,
since it's fairly neat and clean and efficient, is to use keys (and it
looks like whatever the solution is you adopt, you may be reusing it alot
in your ODBC-thing).
You use a key by setting it up with a declaration, then calling the key()
function. The function returns you a set of nodes based on the key name and
value you pass to it.
In your case, you want to be able to get the value of the name attribute on
a column element in your first row, in cases where a subsequent column
element has no name. The column element you want back is the one in the
corresponding location among its siblings to that of the unnamed column
element among its siblings.
So:
<xsl:key name="named-columns" match="/result/row[1]/column" use="position()"/>
This will allow you to get columns from the first row, using the count of
its preceding column siblings as its key value. (Caveat: I would actually
use count(preceding-sibling::column) here instead of position(), since it's
more robust and less likely to introduce hard-to-spot bugs when you do
template-based processing.)
Then when you generate your output:
<xsl:template name="print_name">
<xsl:choose>
<xsl:when test="@name">
Name = <xsl:value-of select="@name"/>
</xsl:when>
<xsl:otherwise>
Name <xsl:value-of select="position()"/>=
<xsl:value-of select="key('named-columns', position())/@name"/>
<!-- this retrieves the @name attribute from the corresponding
named column -->
Value <xsl:value-of select="position()"/>=
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
I hope that helps! Personally I'd drive this through templates: easier to
set up and manage once you get the hang of them. I'd also avoid position(),
as I said: it can be tricky, and beginners often think it's saying
something it's not. (Hint: it's *NOT* saying what the position of an
element is among its siblings.) Replacing it with the expression
count(preceding-sibling::column) will work as well (better) in this case.
Cheers,
Wendell
>"For every complex problem, there is a solution that is simple, neat, and
>wrong."
> -- H.L. Mencken (1880-1956)
... and it's usually position() ...
======================================================================
Wendell Piez mailto:wapiez@mulberrytech.com
Mulberry Technologies, Inc. http://www.mulberrytech.com
17 West Jefferson Street Direct Phone: 301/315-9635
Suite 207 Phone: 301/315-9631
Rockville, MD 20850 Fax: 301/315-8285
----------------------------------------------------------------------
Mulberry Technologies: A Consultancy Specializing in SGML and XML
======================================================================
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list