[xsl] create a new node-set and then reference a key problem

Subject: [xsl] create a new node-set and then reference a key problem
From: Donal Regan <donal_regan10@xxxxxxxxxxx>
Date: Tue, 20 Jul 2004 11:49:47 +0100 (BST)
Hello,
I have the following source XML

<rooms>
	<roomType id="1" count="3" type="1D"/>
	<roomType id="2" count="6" type="2D"/>
	<roomType id="3" count="4" type="3D"/>
	<roomType id="4" count="0" type="4D"/>

	<roomType id="1" count="3" type="1D"/>
	<roomType id="2" count="0" type="2D"/>
	<roomType id="3" count="4" type="3D"/>
	<roomType id="4" count="1" type="4D"/>

	<roomType id="1" count="3" type="1D"/>
	<roomType id="2" count="0" type="2D"/>
	<roomType id="3" count="2" type="3D"/>
	<roomType id="4" count="2" type="4D"/>

	<roomType id="1" count="3" type="1D"/>
	<roomType id="2" count="2" type="2D"/>
	<roomType id="3" count="3" type="3D"/>
	<roomType id="4" count="1" type="4D"/>

	<roomType id="1" count="3" type="1D"/>
	<roomType id="2" count="1" type="2D"/>
	<roomType id="3" count="6" type="3D"/>
	<roomType id="4" count="1" type="4D"/>
</rooms>


I want to display the roomType whose first occurence
has a higher "count" value than the other first
occurences of roomType and whose subsequent "count"
values are all greater than zero i.e. type 2D in the
above XML source. I only want to display this room
type once.
So what I want to do is group my roomTypes together
using the "id" value as a key, select the first
occurence of each roomType,sort them in descending
order, and then loop through them breaking out of the
loop once a valid roomType has been found. I'm having
trouble with the last bit.
I wrote the following stylesheet which displayed all
roomTypes which don't have a "count='0'" at any stage.
<xsl:key name="roomID" match="roomType" use="@id"/>

<xsl:template match="/rooms">
 <table>
  <tr>
   <td>
    <table>
     <tr>
      <td>&#160;</td>
      <td>Room Type</td>
     </tr>
     <xsl:apply-templates
select="roomType[generate-id() =
generate-id(key('roomID',@id))]" mode="vacancies">
       <xsl:sort data-type="number" select="count"
order="descending" />
      </xsl:apply-templates>
    </table>
   </td>
  </tr>
</table>
</xsl:template>

<xsl:template match="roomType" mode="vacancies">
 <tr>
  <xsl:attribute name="id">
   <xsl:value-of select="@id"/>
  </xsl:attribute>
  <xsl:choose>
   <xsl:when test = "key('roomID',@id)/@count = 0">
<!--Don't do anyting--->
   </xsl:when>
   <xsl:otherwise>
   <xsl:attribute name="onClick">
    <xsl:value-of select="'roomClick(this.id)'"/>
   </xsl:attribute>
   <td>ok</td>
   <td style="cursor:hand" align="center"
class="text1">
     <font color="blue"><xsl:value-of
select="@type"/></font>
   </td>
  </xsl:otherwise>
</xsl:choose>
</tr>
</xsl:template>

I realised that this wouldn't do because more than 1
roomType wil be displayed, so I replaced 
 
<xsl:apply-templates select="roomType[generate-id() =
generate-id(key('roomID',@id))]" mode="vacancies">
	<xsl:sort data-type="number" select="count"
order="descending" />
</xsl:apply-templates>

with

<xsl:call-template
name="get_available_room_with_highest_count">
	<xsl:with-param name="sortedRooms">
		<xsl:copy-of select="roomType[generate-id() =
generate-id(key('roomID',@id))]"/>
	</xsl:with-param>
</xsl:call-template>

and added 

<xsl:template
name="get_available_room_with_highest_count">
 <xsl:param name="sortedRooms"/>
  <xsl:for-each
select="msxsl:node-set($sortedRooms)/roomType">
   <xsl:sort data-type="number" select="count"
order="descending" />
   <xsl:choose>
    <xsl:when test = "key('roomID',@id)/@count = 0">		
	<tr><td><xsl:value-of
select="@count"/></td></tr><!--This is just output for
testing purposes at the moment-->
   </xsl:when>
   <xsl:otherwise>
    <tr><td><xsl:value-of select="@type"/></td></tr>
   </xsl:otherwise>
  </xsl:choose>
 </xsl:for-each>
</xsl:template>

to see if it was going to be possible to try something
with recursive templates.
The <xsl:when test = "key('roomID',@id)/@count = 0">
seems to be ignored and I'm not sure why. 
Am I going the right way about this? Any pointers
would be greatly appreciated.

Cheers,
Donal


	
	
		
___________________________________________________________ALL-NEW Yahoo! Messenger - sooooo many all-new ways to express yourself http://uk.messenger.yahoo.com

Current Thread