Go Back   Velocity Reviews > Newsgroups > XML
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

Reply

XML - Problem with XSL and sorting

 
Thread Tools Search this Thread
Old 09-09-2006, 11:11 AM   #1
Default Problem with XSL and sorting


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"
xmlnssl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xslutput 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





Christoph
  Reply With Quote
Old 09-09-2006, 05:47 PM   #2
Dimitre Novatchev
 
Posts: n/a
Default Re: Problem with XSL and sorting

>
> 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" <> wrote in message
news:45029257$0$3567$...
> 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"
> xmlnssl="http://www.w3.org/1999/XSL/Transform"
> xmlns:fo="http://www.w3.org/1999/XSL/Format">
> <xslutput 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
>
>
>



  Reply With Quote
Old 09-10-2006, 01:25 AM   #3
Christoph
 
Posts: n/a
Default Re: Problem with XSL and sorting

> 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:sort> sorted data set...
Nothing I've
tried using this method seemed to do the trick.

thnx,
Christoph


  Reply With Quote
Old 09-10-2006, 06:00 AM   #4
Joe Kesselman
 
Posts: n/a
Default Re: Problem with XSL and sorting

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
  Reply With Quote
Old 09-10-2006, 05:54 PM   #5
Dimitre Novatchev
 
Posts: n/a
Default Re: Problem with XSL and sorting


"Christoph" <> wrote in message
news:45034e03$0$3566$...
>> 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:sort> sorted 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
>



  Reply With Quote
Old 09-10-2006, 06:07 PM   #6
Dimitre Novatchev
 
Posts: n/a
Default Re: Problem with XSL and sorting

>
> 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"
xmlnssl="http://www.w3.org/1999/XSL/Transform">
<xslutput 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" <> wrote in message
news:4504435c$0$97249$ reenews.net...
>
> "Christoph" <> wrote in message
> news:45034e03$0$3566$...
>>> 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:sort> sorted 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
>>

>
>



  Reply With Quote
Old 09-10-2006, 08:32 PM   #7
Joe Kesselman
 
Posts: n/a
Default Re: Problem with XSL and sorting

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
  Reply With Quote
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump