- From: Tim Mooney <mooney@dogbert.cc.ndsu.NoDak.edu>
- Date: Wed, 13 Oct 2004 15:02:55 -0500 (CDT)
- To: www-xsl-fo@w3.org
In regard to: Re: node after current node in xsl:for-each with xsl:sort...:
> Actually it's a bit tricky in pure xslt 1 to sort and then access the
> sorted list at the same time, as the sorted list information goes to the
> result tree where by design you can't really get it back.
>
> If you can use your processor's node-set extension (if it has one) first
> sort the input into a temporary variable then process every other item
> in this sorted list, and access the next item by
> following-sibling::*[1]
> if xx:node-set() isn't available, ask again:-)
[For the benefit of the list archives]
With David's help and some additional info from the web, especially
archived posts to the xsl-list by Michael Kay
http://www.mail-archive.com/xslt@p2p.wrox.com/msg06645.html
and Jeni Tennison
http://www.xslt.com/html/xsl-list/2002-01/msg00472.html
http://www.jenitennison.com/xslt/index.html (the grouping links)
I eventually arrived at:
<fo:table-body>
<xsl:variable name="sorted_accounts">
<xsl:for-each select="/request/account">
<xsl:sort select="id" />
<xsl:copy-of select="." />
</xsl:for-each>
</xsl:variable>
<xsl:for-each select="exslt:node-set($sorted_accounts)/account">
<!-- output a table row if position() mod 2 = 1 -->
<xsl:if test="position() mod 2 = 1">
<xsl:value-of select="$newline" />
<fo:table-row keep-together="always">
<xsl:value-of select="$newline" />
<xsl:apply-templates select="." mode="cutsheet" />
<xsl:apply-templates
select="following-sibling::*[1]"
mode="cutsheet" />
</fo:table-row>
<xsl:value-of select="$newline" />
</xsl:if>
</xsl:for-each>
</fo:table-body>
Along with an "account" template (two, with two different modes for the
two types of account cells I need to output on different parts of the
form) for each cell in the table, this is working perfectly.
Two notes for future archive searchers:
- it would seem like the exslt:node-set used in the xsl:for-each should
be just
<xsl:for-each select="exslt:node-set($sorted_accounts)">
Since I'm already iterating over /request/account when I create the
variable. That's not the case, though. The node-set($sorted_accounts)
essentially "re-roots" a copy of everything that was included in the
xsl:variable.
- This has implications for the xsl:apply-templates calls, because they're
being called with this "re-rooted" document, so if the templates want to
access something like
<xsl:value-of select="/request/foo/bar" />
that won't work because the template is being applied to this "re-rooted"
document, which doesn't have the same document root as the overall
document. The trick that's used to get around this is to make a variable
that "points to" your main document root, via something like
<xsl:variable name="maindoc_root" select="/" />
near the top of your stylesheet, and then use
<xsl:value-of select="$maindoc_root/request/foo/bar" />
within the template calls that need to access nodes outside the
"re-rooted" nodes they've been called with.
My understanding of these last two points is still hazy so my explanation
is probably poor, but I hope this helps someone else in the future.
Thanks all, especially David!
Tim
--
Tim Mooney mooney@dogbert.cc.ndsu.NoDak.edu
Information Technology Services (701) 231-1076 (Voice)
Room 242-J6, IACC Building (701) 231-8541 (Fax)
North Dakota State University, Fargo, ND 58105-5164
Received on Wednesday, 13 October 2004 20:02:59 UTC