distinct grouping of sorted results

K

kristofera

I am trying to do a distinct grouping of some nodes sorted by a numeric
value but for some reason the distinct (preceding-sibling filter) is
applied to the result as if not sorted. If I don't use the
preceding-sibling filter, the nodes are properly sorted. Is this a bug
in the xslt processor I'm using (.net framework 1.1) or is this correct
behaviour?

Any alternative solutions that will show me the lowest priced item in
each category? (xml and xslt snippets below)

XML:

<Items>
<Item>
<ItemCategory>Cat A</ItemCategory>
<ItemName>Item 1</ItemName>
<Price>5</Price>
</Item>
<Item>
<ItemCategory>Cat B</ItemCategory>
<ItemName>Item 2</ItemName>
<Price>3</Price>
</Item>
<Item>
<ItemCategory>Cat A</ItemCategory>
<ItemName>Item 3</ItemName>
<Price>2</Price>
</Item>
</Items>



XSLT snippets:

<xsl:apply-templates select="Item">
<xsl:sort select="ItemCategory" />
<xsl:sort select="Price" data-type="number" order="ascending" />
</xsl:apply-templates>

<xsl:template match="Item">
<xsl:if test="not(ItemCategory=preceding-sibling::Item/ItemCategory)">
Item: <xsl:value-of select="ItemName" />
Price: <xsl:value-of select="Price" />
</xsl:if>
</xsl:template>


Expected output:
Item: Item 3
Price: 2

Item: Item 2
Price: 3


Actual output:
Item: Item 1
Price: 5

Item: Item 2
Price: 3
 
J

Joris Gillis

Tempore 05:35:01 said:
I am trying to do a distinct grouping of some nodes sorted by a numeric
value but for some reason the distinct (preceding-sibling filter) is
applied to the result as if not sorted. If I don't use the
preceding-sibling filter, the nodes are properly sorted. Is this a bug
in the xslt processor I'm using (.net framework 1.1) or is this correct
behaviour?

Hi,

This is correct behaviour, the 'preceding-sibling' axis contains nodes in (reversed) document order, while the order of the nodes in the current node-set within your template 'Item' is altered by the sorting instruction. This order conflict results in unexpected behaviour.

Try it with the muenchian grouping:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:eek:utput method="xml" indent="yes"/>
<xsl:key name="cat" match="Item" use="ItemCategory"/>

<xsl:template match="Items">
<xsl:for-each select="Item[generate-id()=generate-id(key('cat',ItemCategory))]">
<xsl:sort select="ItemCategory" />
<xsl:apply-templates select="key('cat',ItemCategory)">
<xsl:sort select="Price" data-type="number" order="ascending" />
</xsl:apply-templates>
</xsl:for-each>
</xsl:template>

<xsl:template match="Item">
<xsl:if test="position()=1">
Item: <xsl:value-of select="ItemName" />
Price: <xsl:value-of select="Price" />
</xsl:if>
</xsl:template>

</xsl:stylesheet>




regards,
 
K

kristofera

Thanks.

I tried the Muenchian grouping but couldn't get it to work. I'm not
sure I fully understand how the Muenchian grouping works but suspect
the reason it doesn't work for me is that I have several subtrees
similar to the Items/Item tree in my document:

<Stores>
<Store>
<Items>
<Item>
.....
<Store>
<Items>
<Item>
.....

....and a subsequent key lookup will go off and grab stuff from the
wrong subtree...
 
J

Joris Gillis

Tempore 11:20:03 said:
I tried the Muenchian grouping but couldn't get it to work. I'm not
sure I fully understand how the Muenchian grouping works but suspect
the reason it doesn't work for me is that I have several subtrees
similar to the Items/Item tree in my document:

That ought to be the problem.

Try this one:
<xsl:stylesheet version="1.1"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:eek:utput method="xml" indent="yes"/>
<xsl:key name="cat" match="Item" use="concat(generate-id(..),ItemCategory)"/>

<xsl:template match="Items">
<xsl:for-each select="Item[generate-id()=generate-id(key('cat',concat(generate-id(..),ItemCategory)))]">
<xsl:sort select="ItemCategory" />
<xsl:apply-templates select="key('cat',concat(generate-id(..),ItemCategory))">
<xsl:sort select="Price" data-type="number" order="ascending" />
</xsl:apply-templates>
</xsl:for-each>
</xsl:template>

<xsl:template match="Item">
<xsl:if test="position()=1">
Item: <xsl:value-of select="ItemName" />
Price: <xsl:value-of select="Price" />
</xsl:if>
</xsl:template>

</xsl:stylesheet>

regards,
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top