By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,682 Members | 1,980 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,682 IT Pros & Developers. It's quick & easy.

Problem with XSL and sorting

P: n/a
I'm trying to come up with a stylesheet where, when the rows are displayed,
duplicate game names are not shown on subsequent rows. It works but doesn't
work properly. If I sort the data using <xsl:sortprior to processing,
it's not checking against the previous row after the sort but instead the
previous row from the original data set. Here is the XML and XSL I'm using:

<GameSets>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>10th Anniversary</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Anarchs</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Ancient Hearts</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Bloodlines</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Camarilla</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Netrunner</gamename>
<setname>Classic</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Dark Sovereigns</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Final Nights</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Gehenna</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Jyhad</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Kindred Most Wanted</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Legacies of Blood</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Netrunner</gamename>
<setname>Netrunner</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Nights of Reckoning</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Promotional</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Netrunner</gamename>
<setname>Proteus</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Sabbat</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Sabbat War</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>The Black Hand</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>V:TES</setname>
</GameSetsRow>
</GameSets>

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:output method="html"/>
<xsl:template match="GameSets">
<html>
<head>
<title>Game Sets</title>
</head>
<body>
<h1>Game Sets</h1>
<table border="1">
<tr>
<th>Position</th>
<th>Game</th>
<th>Set</th>
<th>Previous Game</th>
</tr>
<xsl:for-each select="GameSetsRow">
<xsl:sort select="gamename"/>
<xsl:variable name="pos" select="position()"/>
<tr>
<td><xsl:copy-of select="$pos"/></td>
<td>
<xsl:if test="$pos = 1 or gamename !=
preceding-sibling::GameSetsRow[1]/gamename">
<xsl:copy-of select="gamename"/>
</xsl:if>
</td>
<td><xsl:copy-of select="setname"/></td>
<td><xsl:copy-of
select="preceding-sibling::GameSetsRow[1]/gamename"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

What am I missing? Why isn't the test using the sorted set?

thnx,
Christoph

Sep 9 '06 #1
Share this Question
Share on Google+
6 Replies


P: n/a
>
What am I missing? Why isn't the test using the sorted set?
The result of <xsl:sort/is that the current node is selected from the
node-list (of xsl:for-each or xsl-apply-templates) in sorted order.

This does not change the xml documents and any of the axis relationships
between its nodes -- the preceding sibling of any node still remains the
same.

What you need is to create a completely new document, in which the sorted
nodes will indeed be siblings.

This can be done if the sorting is performed in the body of an xsl:variable.
The resulting variable is of type RTF (Result Tree Fragment) and cannot
directly be operated by XPath (except for treating it as a string). One has
to convert this RTF to a regular tree by applying the xxx:node-set()
extension function on it. The xxx:node-set() ext. fn. is usually provided by
the particular XSLT Processor vendor and the prefix "xxx" is typically bound
to a vendor-specific namespace. If the XSLT Processor supports EXSLT, then
the exslt:node-set() ext. fn. can be used and the xslt code will be portable
accross XSLT processors that support EXSLT.

In XSLT finding unique nodes is also known as "grouping". More on grouping
can be found at:

http://www.jenitennison.com/xslt/grouping/
Cheers,
Dimitre Novatchev

"Christoph" <jc*****@yahoo.comwrote in message
news:45**********************@news.qwest.net...
I'm trying to come up with a stylesheet where, when the rows are
displayed, duplicate game names are not shown on subsequent rows. It
works but doesn't work properly. If I sort the data using <xsl:sort>
prior to processing, it's not checking against the previous row after the
sort but instead the previous row from the original data set. Here is the
XML and XSL I'm using:

<GameSets>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>10th Anniversary</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Anarchs</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Ancient Hearts</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Bloodlines</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Camarilla</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Netrunner</gamename>
<setname>Classic</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Dark Sovereigns</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Final Nights</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Gehenna</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Jyhad</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Kindred Most Wanted</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Legacies of Blood</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Netrunner</gamename>
<setname>Netrunner</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Nights of Reckoning</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Promotional</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Netrunner</gamename>
<setname>Proteus</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Sabbat</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Sabbat War</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>The Black Hand</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>V:TES</setname>
</GameSetsRow>
</GameSets>

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:output method="html"/>
<xsl:template match="GameSets">
<html>
<head>
<title>Game Sets</title>
</head>
<body>
<h1>Game Sets</h1>
<table border="1">
<tr>
<th>Position</th>
<th>Game</th>
<th>Set</th>
<th>Previous Game</th>
</tr>
<xsl:for-each select="GameSetsRow">
<xsl:sort select="gamename"/>
<xsl:variable name="pos" select="position()"/>
<tr>
<td><xsl:copy-of select="$pos"/></td>
<td>
<xsl:if test="$pos = 1 or gamename !=
preceding-sibling::GameSetsRow[1]/gamename">
<xsl:copy-of select="gamename"/>
</xsl:if>
</td>
<td><xsl:copy-of select="setname"/></td>
<td><xsl:copy-of
select="preceding-sibling::GameSetsRow[1]/gamename"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

What am I missing? Why isn't the test using the sorted set?

thnx,
Christoph

Sep 9 '06 #2

P: n/a
extension function on it. The xxx:node-set() ext. fn. is usually provided
by the particular XSLT Processor vendor and the prefix "xxx" is typically
bound to a vendor-specific namespace. If the XSLT Processor supports
EXSLT, then the exslt:node-set() ext. fn. can be used and the xslt code
will be portable accross XSLT processors that support EXSLT.
Is there a XSLT processor that works in both IE and Firefox?
In XSLT finding unique nodes is also known as "grouping". More on grouping
can be found at:
http://www.jenitennison.com/xslt/grouping/
I've read alot about the Muenchian Method alot today while looking into how
I
might be able to solve this problem. The main thing I've been running into
is that
it doesn't seem to work properly with a <xsl:sortsorted data set...
Nothing I've
tried using this method seemed to do the trick. :(

thnx,
Christoph
Sep 9 '06 #3

P: n/a
Christoph wrote:
Is there a XSLT processor that works in both IE and Firefox?
Well, you could write an applet that downloads and runs Xalan... but
that's not a particularly efficient solution. If you aren't willing to
trust the XSLT processor provided by the browser (or that the browser
provides one at all), you may want to do this processing in the server.
--
() ASCII Ribbon Campaign | Joe Kesselman
/\ Stamp out HTML e-mail! | System architexture and kinetic poetry
Sep 10 '06 #4

P: n/a

"Christoph" <jc*****@yahoo.comwrote in message
news:45**********************@news.qwest.net...
>extension function on it. The xxx:node-set() ext. fn. is usually provided
by the particular XSLT Processor vendor and the prefix "xxx" is typically
bound to a vendor-specific namespace. If the XSLT Processor supports
EXSLT, then the exslt:node-set() ext. fn. can be used and the xslt code
will be portable accross XSLT processors that support EXSLT.

Is there a XSLT processor that works in both IE and Firefox?
>In XSLT finding unique nodes is also known as "grouping". More on
grouping can be found at:
http://www.jenitennison.com/xslt/grouping/

I've read alot about the Muenchian Method alot today while looking into
how I
might be able to solve this problem. The main thing I've been running
into is that
it doesn't seem to work properly with a <xsl:sortsorted data set...
Nothing I've
tried using this method seemed to do the trick. :(
As I said before, nothing will work if you do not include the sorted nodes
in an RTF and transform them to a temporary tree. Then you can perform the
Muenchian method on this temporary tree.
Cheers,
Dimitre Novatchev.
>
thnx,
Christoph

Sep 10 '06 #5

P: n/a
>
As I said before, nothing will work if you do not include the sorted nodes
in an RTF and transform them to a temporary tree. Then you can perform the
Muenchian method on this temporary tree.
Actually, you'll be able to:

1. Perform the Muenchian method (no sorting is necessary).

2. Do the sorting
So, this is a very simple exercise in grouping.

This transformation:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>

<xsl:key name="kGN" match="gamename" use="." />

<xsl:template match="/">
<games>
<xsl:for-each select=
"/*/*/gamename[generate-id()
=
generate-id(key('kGN',.)[1])
]">
<xsl:sort/>
<xsl:copy-of select=".."/>
</xsl:for-each>
</games>
</xsl:template>
</xsl:stylesheet>
when applied on your original source xml document:

<GameSets>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>10th Anniversary</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Anarchs</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Ancient Hearts</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Bloodlines</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Camarilla</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Netrunner</gamename>
<setname>Classic</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Dark Sovereigns</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Final Nights</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Gehenna</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Jyhad</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Kindred Most Wanted</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Legacies of Blood</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Netrunner</gamename>
<setname>Netrunner</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Nights of Reckoning</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Promotional</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Netrunner</gamename>
<setname>Proteus</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Sabbat</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>Sabbat War</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>The Black Hand</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>V:TES</setname>
</GameSetsRow>
</GameSets>

produces the desired sorted output for all (2 in this case) uniquely named
games:

<games>
<GameSetsRow>
<gamename>Netrunner</gamename>
<setname>Classic</setname>
</GameSetsRow>
<GameSetsRow>
<gamename>Vampire: The Eternal Struggle</gamename>
<setname>10th Anniversary</setname>
</GameSetsRow>
</games>

Hope this helped.
Cheers,
Dimitre Novatchev
"Dimitre Novatchev" <di******@tpg.com.auwrote in message
news:45***********************@authen.yellow.readf reenews.net...
>
"Christoph" <jc*****@yahoo.comwrote in message
news:45**********************@news.qwest.net...
>>extension function on it. The xxx:node-set() ext. fn. is usually
provided by the particular XSLT Processor vendor and the prefix "xxx" is
typically bound to a vendor-specific namespace. If the XSLT Processor
supports EXSLT, then the exslt:node-set() ext. fn. can be used and the
xslt code will be portable accross XSLT processors that support EXSLT.

Is there a XSLT processor that works in both IE and Firefox?
>>In XSLT finding unique nodes is also known as "grouping". More on
grouping can be found at:
http://www.jenitennison.com/xslt/grouping/

I've read alot about the Muenchian Method alot today while looking into
how I
might be able to solve this problem. The main thing I've been running
into is that
it doesn't seem to work properly with a <xsl:sortsorted data set...
Nothing I've
tried using this method seemed to do the trick. :(

As I said before, nothing will work if you do not include the sorted nodes
in an RTF and transform them to a temporary tree. Then you can perform the
Muenchian method on this temporary tree.
Cheers,
Dimitre Novatchev.
>>
thnx,
Christoph


Sep 10 '06 #6

P: n/a
Dimitre Novatchev wrote:
As I said before, nothing will work if you do not include the sorted nodes
in an RTF and transform them to a temporary tree. Then you can perform the
Muenchian method on this temporary tree.
Yep, that's the right approach.

--
() ASCII Ribbon Campaign | Joe Kesselman
/\ Stamp out HTML e-mail! | System architexture and kinetic poetry
Sep 10 '06 #7

This discussion thread is closed

Replies have been disabled for this discussion.