Here's another 1.0 solution for this problem (written a bit
differently but essentially does similar to the other generate-id
solution):
(I wrote this hours ago, and didn't post it as I saw other reasonable
solutions :) posting this anyway.)
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:key name="authorgroup" match="book" use="@author" />
<xsl:template match="doc">
<report>
<xsl:for-each select="book[generate-id(.) =
generate-id(key('authorgroup', @author)[1])]">
<author name="{(_at_)author}">
<xsl:apply-templates select="key('authorgroup',
@author)"
mode="groupByAuthor" />
</author>
</xsl:for-each>
</report>
</xsl:template>
<xsl:template match="book" mode="groupByAuthor">
<title>
<xsl:value-of select="@title" />
</title>
</xsl:template>
</xsl:stylesheet>
Here are probably the reasons why I organized the stylesheet as presented:
1. Writing all of the logic in one template (say in root template,
using a for loop and all), is a monolithic design, and parts of
stylesheet logic are not reusable (I believe, re-usability of logic in
any program is useful for reasons best known to all of us
programmers!).
So I created a template "book" with a mode.
2. I thought using mode was useful, since then the template for "book"
cannot (or would be really really difficult) be invoked accidentally
by another invocation of this template, like for example:
<xsl:apply-templates select="book" /> (which is the side effect I
wanted to avoid with modes!).
PS: I do like 2.0 for-each-group because it doesn't require XSLT keys
for grouping (this is useful because with XSLT 2.0 we don't have to
think about design of key's [a real static wiring of logic in our
brains, which I don't like!] in a stylesheet for grouping), and
grouping with for-each-group can be nested at arbitrary levels, which
is really nice :) Arbitrary nesting of groups in 1.0 get's almost
undoable beyond a certain point. So if we have scale our groups in
XSLT stylesheets, using XSLT 2.0 (and 2.1/3.0 in future :)) is the
only way going forward.
On Fri, Sep 24, 2010 at 7:20 AM, David Frey <dpfrey(_at_)shaw(_dot_)ca> wrote:
I have an XSLT problem that I haven't been able to figure out. The example
below is essentially the simplest version of the problem I have encountered.
Say you have a document like this:
<doc>
<book title="aaa" author="jones"/>
<book title="bbb" author="smith"/>
<book title="ccc" author="douglas"/>
<book title="ddd" author="jones"/>
<book title="eee" author="jones"/>
<book title="fff" author="douglas"/>
<book title="ggg" author="smith"/>
</doc>
How can you produce a document like this?:
<report>
<author name="jones">
<title>aaa</title>
<title>ddd</title>
<title>eee</title>
</author>
<author name="smith">
<title>bbb</title>
<title>ggg</title>
</author>
<author name="douglas">
<title>bbb</title>
<title>fff</title>
</author>
</report>
Restrictions:
- Only XSLT 1.0
- You can't hard-code the names of the books or the authors in the XSLT.
Thanks,
Dave
--
Regards,
Mukul Gandhi
--~------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--