This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Re: one key or a whole bunch?
- From: Jeni Tennison <jeni at jenitennison dot com>
- To: Marina Sorreta <milkmandeg at yahoo dot com>
- Cc: XSL-List at lists dot mulberrytech dot com
- Date: Tue, 21 May 2002 18:12:43 +0100
- Subject: Re: [xsl] one key or a whole bunch?
- Organization: Jeni Tennison Consulting Ltd
- References: <20020521082528.91456.qmail@web20511.mail.yahoo.com>
- Reply-to: xsl-list at lists dot mulberrytech dot com
Hi Marina,
> I need to get a count of all the groups of <SHELF_NO>'s that are the
> same. I need the output to be in the form (with the example above):-
>
> Shelf Groups Number of Copies
> 0 0 <--i.e. no instance of no shelf number
> 1 1 <--i.e. 1 instance of just one unique shelf number
> 2 0 <--i.e no instance of two shelf numbers the same
> 3 1 <--i.e. 1 instance where three shelf numbers were the same
> etc etc
If I understand you properly, that's quite a difficult analysis to do,
especially in one step. The best thing to do would be to break it down
into two steps:
- create a list of the unique shelf numbers and the number of
occurrences of each of those shelf numbers
- use a recursive template to go up through the possible numbers of
repeats, and count how many there are of each.
The first step involves your kShelf key:
<xsl:key name="kShelf" match="SPORTS | LEISURE | CLOTHES | GIFTS"
use="SHELF_NO"/>
To create the node set of unique SHELF_NO elements, you need to use
the Muenchian method, as you'd started doing:
<xsl:variable name="shelves-rtf">
<xsl:for-each select="SHOP/*[generate-id() =
generate-id(key('kShelf',
SHELF_NO)[1])]">
<SHELF_NO count="count(key('kShelf', SHELF_NO))">
<xsl:value-of select="SHELF_NO" />
</SHELF_NO>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="shelves" select="exsl:node-set($shelves-rtf)" />
That will give you $shelves, as a node set containing something like:
<SHELF_NO count="1">4567</SHELF_NO>
<SHELF_NO count="3">3344</SHELF_NO>
You can then pass this node set to a recursive template that steps up
from 0 through to however many is required, counting how many SHELF_NO
elements have a particular value for their count attribute. The
recursive call adds one to the count, and only passes on those
SHELF_NO elements that don't have the particular count (gradually
working through the list of SHELF_NO elements). Something like:
<xsl:template name="frequency-table">
<xsl:param name="count" select="0" />
<xsl:param name="shelves" select="/.." />
<xsl:if test="$shelves">
<xsl:variable name="shelves-with-count"
select="$shelves[@count = $count]" />
<xsl:variable name="nshelves-with-count"
select="count($shelves-with-count)" />
<xsl:value-of select="$count" />
<xsl:text> </xsl:text>
<xsl:value-of select="$nshelves-with-count" />
<xsl:call-template name="frequency-table">
<xsl:with-param name="count" select="$count + 1" />
<xsl:with-param name="shelves"
select="$shelves[count(.|$shelves-with-count) !=
$nshelves-with-count]" />
</xsl:call-template>
</xsl:if>
</xsl:template>
Once you'd created the $shelves variable (as above), you could call
this template with:
<xsl:call-template name="frequency-table">
<xsl:with-param name="shelves" select="$shelves" />
</xsl:call-template>
Cheers,
Jeni
---
Jeni Tennison
http://www.jenitennison.com/
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list