[xsl] Re: using keys for counting not sorting

Subject: [xsl] Re: using keys for counting not sorting
From: Dimitre Novatchev <dnovatchev@xxxxxxxxx>
Date: Sat, 29 Dec 2001 23:37:13 -0800 (PST)
"Ahmad J. Reeves" <ahmad at dcs dot qmul dot ac dot uk> wrote:

> I am trying to use keys (as I understand variables cannot change their value)
> for counting rather than sorting:-
> 
> So with the following xml:
> 
> <LOG>      
>       <DIRECT>
>       <COMMUNICATION_TYPE> PAGETELL </COMMUNICATION_TYPE>
>       <Invoc_serial> 27 </Invoc_serial>
>       <Serial> 3087908 </Serial>
>       <USAGE> TELL </USAGE>
>       <MESSAGE_TYPE> EMOTE </MESSAGE_TYPE>
>       <CHARACTER_ID> 10010 </CHARACTER_ID>
>       <CHARACTER_STATUS> 3 </CHARACTER_STATUS>
>       <LOCATION_ID> 45040 </LOCATION_ID>
>       <TARGET_CHARACTER_ID> 444444 </TARGET_CHARACTER_ID>
>       <TARGET_CHARACTER_STATUS> 6 </TARGET_CHARACTER_STATUS>
>       <TARGET_CHARACTER_LOCATION_ID> 23222 </TARGET_CHARACTER_LOCATION_ID>
>       <MESSAGE>hello</MESSAGE>
>       <TIME> 'Mon, 26 Nov 2001 15:40:29 +0000' </TIME>
>       </DIRECT>
> 
> etc etc 50,000 or so times
> </LOG>
> 
> I need to count, then output as a number, the occurences of every CHARACTER_ID
> (so I know they have sent a message) and also where that same ID occurs as
> a TARGET_CHARACTER_ID (so I know they have received a message). So how
> could I perhaps adapt Jennie's example 

[snip]

> to do this instead of sorting them, so the output looks like:-
> 
> CHARACTER_ID 3434343 sent 435 messages, received 234
> CHARACTER_ID 121212 sent 432 messages, received 128
> 
> and also do a total sent and received and an average?

Hi Ahmad,

Here's the solution to your problem:

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

  <xsl:output method="text"/>
  
  <xsl:key name="kByID" match="DIRECT" use="CHARACTER_ID"/>
  <xsl:key name="kByTargetID" match="DIRECT" use="TARGET_CHARACTER_ID"/>
  
    <xsl:variable name="vUniqueCharactersSending" 
                  select="LOG/DIRECT[generate-id() 
                                    = 
                                     generate-id(key('kByID',
                                                      CHARACTER_ID
                                                     )[1]
                                                 )
                                    ]"/>
                                    
    <xsl:variable name="vUniqueCharactersReceiving" 
                  select="$vUniqueCharactersSending
                                   [key('kByTargetID',
                                         CHARACTER_ID
                                        )
                                   ]"/>
                                    
    <xsl:variable name="vNumCharactersSending" 
                  select="count($vUniqueCharactersSending)"/>
    
    <xsl:variable name="vNumCharactersReceiving" 
                  select="count($vUniqueCharactersReceiving)"/>
    
    <xsl:variable name="vTotalSent"
                  select="count(LOG/DIRECT/CHARACTER_ID)"/>
                  
    <xsl:variable name="NL" select="'&#xA;'"/>
    
  <xsl:template match="/">
    <xsl:for-each select="$vUniqueCharactersSending">
      <xsl:value-of select="concat('CHARACTER_ID ',CHARACTER_ID,
                                   ' sent ',
                                   count(key('kByID',CHARACTER_ID)),
                                   ' messages, received ',
                                   count(key('kByTargetID',CHARACTER_ID)),
                                   $NL
                                   )"/>
    </xsl:for-each>
    
    <xsl:value-of select="$NL"/>
    <xsl:value-of select="concat('Number of characters having sent a message: ',
                                  $vNumCharactersSending,
                                  $NL
                                  )"/>
    
    <xsl:value-of select="concat('Number of characters having received a message: ',
                                  $vNumCharactersReceiving,
                                  $NL
                                  )"/>
    
    <xsl:value-of select="$NL"/>
    <xsl:value-of select="concat('Total sent: ',
                                  $vTotalSent,
                                  ', Average sent by a sending character: ',
                                  $vTotalSent div $vNumCharactersSending,
                                  '&#xA;',
                                  
                                  'Total received: ',
                                   $vTotalSent,
                                  ', Average received by a receiving character: ',
                                  $vTotalSent div $vNumCharactersReceiving,
                                  '&#xA;'
                                  
                                 )"/>
  </xsl:template>
</xsl:stylesheet>

When applied to the following source xml document:

groupSendReceive.xml:
--------------------
<LOG>
  <DIRECT>
    <COMMUNICATION_TYPE>PAGETELL</COMMUNICATION_TYPE>
    <Invoc_serial>27</Invoc_serial>
    <Serial>3087908</Serial>
    <USAGE>TELL</USAGE>
    <MESSAGE_TYPE>EMOTE</MESSAGE_TYPE>
    <CHARACTER_ID>10010</CHARACTER_ID>
    <CHARACTER_STATUS>3</CHARACTER_STATUS>
    <LOCATION_ID>45040</LOCATION_ID>
    <TARGET_CHARACTER_ID>444444</TARGET_CHARACTER_ID>
    <TARGET_CHARACTER_STATUS>6</TARGET_CHARACTER_STATUS>
    <TARGET_CHARACTER_LOCATION_ID>23222</TARGET_CHARACTER_LOCATION_ID>
    <MESSAGE>hello</MESSAGE>
    <TIME>'Mon, 26 Nov 2001 15:40:29 +0000'</TIME>
  </DIRECT>

  <DIRECT>
    <COMMUNICATION_TYPE>PAGETELL</COMMUNICATION_TYPE>
    <Invoc_serial>27</Invoc_serial>
    <Serial>3087908</Serial>
    <USAGE>TELL</USAGE>
    <MESSAGE_TYPE>EMOTE</MESSAGE_TYPE>
    <CHARACTER_ID>10010</CHARACTER_ID>
    <CHARACTER_STATUS>3</CHARACTER_STATUS>
    <LOCATION_ID>45040</LOCATION_ID>
    <TARGET_CHARACTER_ID>444444</TARGET_CHARACTER_ID>
    <TARGET_CHARACTER_STATUS>6</TARGET_CHARACTER_STATUS>
    <TARGET_CHARACTER_LOCATION_ID>23222</TARGET_CHARACTER_LOCATION_ID>
    <MESSAGE>hello</MESSAGE>
    <TIME>'Mon, 26 Nov 2001 15:40:29 +0000'</TIME>
  </DIRECT>

  <DIRECT>
    <COMMUNICATION_TYPE>PAGETELL</COMMUNICATION_TYPE>
    <Invoc_serial>27</Invoc_serial>
    <Serial>3087908</Serial>
    <USAGE>TELL</USAGE>
    <MESSAGE_TYPE>EMOTE</MESSAGE_TYPE>
    <CHARACTER_ID>444444</CHARACTER_ID>
    <CHARACTER_STATUS>3</CHARACTER_STATUS>
    <LOCATION_ID>45040</LOCATION_ID>
    <TARGET_CHARACTER_ID>10010</TARGET_CHARACTER_ID>
    <TARGET_CHARACTER_STATUS>6</TARGET_CHARACTER_STATUS>
    <TARGET_CHARACTER_LOCATION_ID>23222</TARGET_CHARACTER_LOCATION_ID>
    <MESSAGE>hello</MESSAGE>
    <TIME>'Mon, 26 Nov 2001 15:40:29 +0000'</TIME>
  </DIRECT>

  <DIRECT>
    <COMMUNICATION_TYPE>PAGETELL</COMMUNICATION_TYPE>
    <Invoc_serial>27</Invoc_serial>
    <Serial>3087908</Serial>
    <USAGE>TELL</USAGE>
    <MESSAGE_TYPE>EMOTE</MESSAGE_TYPE>
    <CHARACTER_ID>50050</CHARACTER_ID>
    <CHARACTER_STATUS>3</CHARACTER_STATUS>
    <LOCATION_ID>45040</LOCATION_ID>
    <TARGET_CHARACTER_ID>444444</TARGET_CHARACTER_ID>
    <TARGET_CHARACTER_STATUS>6</TARGET_CHARACTER_STATUS>
    <TARGET_CHARACTER_LOCATION_ID>23222</TARGET_CHARACTER_LOCATION_ID>
    <MESSAGE>hello</MESSAGE>
    <TIME>'Mon, 26 Nov 2001 15:40:29 +0000'</TIME>
  </DIRECT></LOG>

The result of the transformation is:

CHARACTER_ID 10010 sent 2 messages, received 1
CHARACTER_ID 444444 sent 1 messages, received 3
CHARACTER_ID 50050 sent 1 messages, received 0

Number of characters having sent a message: 3
Number of characters having received a message: 2

Total sent: 4, Average sent by a sending character: 1.3333333333333332
Total received: 4, Average received by a receiving character: 2


Hope this helped.

Cheers,
Dimitre Novatchev.


__________________________________________________
Do You Yahoo!?
Send your FREE holiday greetings online!
http://greetings.yahoo.com

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread