Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Grouping data with xsl

Status
Not open for further replies.

harmmeijer

Programmer
Mar 1, 2001
869
CN
The project can be downloaded here:


This Microsoft example works fine and dandy as long as a book does not have more than one author.
How can I make this example work so the result does not show me the titles Midnight Rain twice with one author but only once with the two authors under it.
I was thinking of writing the title conditionally with an if statement checking the previous title (if the current and previous are the same do not write it) but I can set an xml:variable only once.
 
Yes, something analagous to SQL DISTINCT is what is needed. I have not been able to find this yet.

<bb/>
 
Yippee, I managed to group the authors.
You can download it here:

Firs I store the current title in a variable like so:
<xsl:variable name=&quot;title&quot;><xsl:value-of select=&quot;title&quot;/></xsl:variable>

Then I put a condition on making the title table like so:
<xsl:if test=&quot;(not(title = preceding::title)) or (not(genre = preceding::genre))&quot;>
So if the title or the genre does not change nothing will happen

And when it is time to write the authors I will use a loop and combine it with a conditional statement like so:
<xsl:for-each select=&quot;key('categ_key', genre)&quot;>
<xsl:sort select=&quot;author&quot;/>
<xsl:if test=&quot;title = $title&quot;>
…..write author
</xsl:if>
</xsl:for-each>

So for each author in the currently grouped genre check if the title of the book is the title of the variable, if so write the author.
I wonder if I could filter the select”key..” with something like where title = $title (I do not have to go through all the records and filter it with the if statement.
The more many too many relations I use the complicated this will get. At the moment I use author table, link table to books table, books table and genre table.
Imagine if I would use tables like:
author table, link table to books table, books table, linked table to genre table and genre table (one book could have multiple genre’s).
 
Well, my mistake. Grouping does not work at all.
I do not know what value preceding is supposed to give but to me it works a lot like rnd in vb.

What I need is the previos value of title so I can use this in the for-each select=&quot;key('categ_key', genre)&quot;
The first time it will of course be empty.
Every next time if it is the same as the current title I will not write the title.

Is it possible in xsl to group this kind of data??

I cannot seem to find any working example to do so.
 
XSL won't let you change the value of a variable. You may be better off doing some manipulation in ASP or servlet code.

'preceding::*' would reference all preceding nodes in the selected set - excluding ancestors on the current node - in reverse document order. In english, it goes backwards thru all nodes (including text nodes) until it reaches the parent node of the currently selected node.
 
The preceding shows the nodes before current node in physical order.
If I do a sort it gives me values I cannot use.
For example
<root>
<item>
<name>bbb</name>
</item>
<item>
<name>aaa</name>
</item>
.... a lot more items
</root>

in xsl
<xsl:key name=&quot;grp_key&quot; match=&quot;item&quot; use=&quot;name&quot;/>
....
<xsl:template match=&quot;root&quot; mode=&quot;grp&quot;>
<xsl:for-each select=&quot;key('grp_key', name)&quot;>
<xsl:sort select=&quot;name&quot;/>

preceding::name will give me bbb and then empty because physically bbb is the preceding of aaa and nothing is the preceding of bbb.
I want to know how I can get the preceding of the key('grp_key', name) (in this case first time nothing and second time aaa.
For now grouping works because I set the order by clause in the sql statement so the nodes are physically alphbetical (first main group then sub group etc etc.).
If I need to regroup I have to run the sql statement again and re connect to the database.

Thanks for your help uura.
 
I still want to know how to get the previous value of the key(... and not the physical previous value(s) of the current node.
Of course the above example will not work, here is how it should be:
xsl:
<xsl:stylesheet version=&quot;1.0&quot;
xmlns:xsl=&quot;<xsl:key name=&quot;grp_key&quot; match=&quot;item&quot; use=&quot;name&quot;/>

<xsl:template match=&quot;/&quot;>
<xsl:apply-templates select=&quot;root&quot; mode=&quot;grp&quot;/>
</xsl:template>

<xsl:template match=&quot;root&quot; mode=&quot;grp&quot;>
<xsl:for-each select=&quot;key('grp_key', item/name)&quot;>
<xsl:sort select=&quot;name&quot;/>
<xsl:value-of select=&quot;name&quot;/> preceding: <xsl:value-of select=&quot;preceding::name&quot;/><br/>
</xsl:for-each>

</xsl:template>
</xsl:stylesheet>

xml:
<?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?>
<?xml-stylesheet type='text/xsl' href='test.xsl'?>
<root>
<item>
<name>bbb</name>
</item>
<item>
<name>aaa</name>
</item>
</root>
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top