[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

[xsl] Re: distinct moves problem


Subject: [xsl] Re: distinct moves problem
From: Dimitre Novatchev <dnovatchev@xxxxxxxxx>
Date: Mon, 7 Jan 2002 07:51:50 -0800 (PST)

Ahmad J Reeves <ahmad at dcs dot qmul dot ac dot uk> wrote:

> Just wanted to say thanks once again for helping
> questions. This is the best list I've seen for
> genral helpfulness and good things!
> 
> Just a quick question, with the same data..
> 
> <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 also need to track the movement of a character. So
> for example I know that a certain character_id has
> been in say 25 rooms of which 9 were unique, but
> I cant see how I can work out the number of distinct moves he makes
> using xsl.
> 
> So I can get output like this:-
> 
> Ch-ID   in-room     Message  Target-ID  time
> 23470  45040        Hello    12345      10:19
> 23470  43333        Hi       23432      10:23
> 23470  45040        Yo       43333      10:44
> 
> etc..
> etc..
> 
> This tells me he was in a total of three rooms of which
> 2 were unique AND he has made 2 MOVES so far. So I need
> to work out the total number of distinct moves per character-ID,
> with a total and average for all of them.

Hi Ahmad,

This problem is built upon the previous one for which you already have the solution:

http://sources.redhat.com/ml/xsl-list/2001-12/msg01127.html

To calculate the number of distinct rooms a "character" has been in, you can add to
the solution the following:

  <xsl:key name="kLocByCharacter"
           match="LOCATION_ID"
           use="../CHARACTER_ID"/>

  <xsl:key name="kLocByValandChar"
           match="LOCATION_ID"
           use="concat(., '|', ../CHARACTER_ID)"/>

The first key gives all "LOCATION_ID"s (rooms) for a "character".

The second key gives all "LOCATION_ID"s (rooms) that have a given combination of
values for a "LOCATION_ID" (room) and the "character" that was there.

In order to get a list of distinct characters and for each of them a list of
distinct rooms, add this code at the end of the template:

    <xsl:for-each select="$vUniqueCharactersSending">
      <xsl:value-of select="concat('Character_ID: ',
                                   CHARACTER_ID,
                                   ':',
                                   $NL
                                   )"/>
      <xsl:for-each select="key('kLocByCharacter',CHARACTER_ID)
                                [generate-id()
                                 =
                                 generate-id(key('kLocByValandChar',
                                                 concat(.,
                                                        '|',
                                                        current()/CHARACTER_ID
                                                        )
                                                 )[1]
                                             )
                                 ]">


        <xsl:value-of select="concat('    ', ., $NL)"/>

      </xsl:for-each>

    </xsl:for-each>


The complete stylesheet will now be:

<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="TARGET_CHARACTER_ID" use="."/>
  <xsl:key name="kLocByCharacter"
           match="LOCATION_ID"
           use="../CHARACTER_ID"/>

  <xsl:key name="kLocByValandChar"
           match="LOCATION_ID"
           use="concat(., '|', ../CHARACTER_ID)"/>

    <xsl:variable name="vUniqueCharactersSending"
                  select="LOG/DIRECT[generate-id()
                                    =
                                     generate-id(key('kByID',
                                                      CHARACTER_ID
                                                     )[1]
                                                 )
                                    ]"/>

    <xsl:variable name="vUniqueCharactersReceiving"
                  select="LOG/DIRECT/TARGET_CHARACTER_ID
                                  [generate-id()
                                    =
                                     generate-id(key('kByTargetID',
                                                      .
                                                     )[1]
                                                 )
                                    ]"/>

    <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:for-each select="$vUniqueCharactersReceiving
                                     [not(key('kByID', .))]">

      <xsl:value-of select="concat('CHARACTER_ID ', .,
                                   ' sent 0 messages, received ',
                                   count(key('kByTargetID',.)),
                                   $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:value-of select="$NL"/>
    <xsl:value-of select="concat('Room moves by character:', $NL)"/>

    <xsl:for-each select="$vUniqueCharactersSending">
      <xsl:value-of select="concat('Character_ID: ',
                                   CHARACTER_ID,
                                   ':',
                                   $NL
                                   )"/>
      <xsl:for-each select="key('kLocByCharacter',CHARACTER_ID)
                                [generate-id()
                                 =
                                 generate-id(key('kLocByValandChar',
                                                 concat(.,
                                                        '|',
                                                        current()/CHARACTER_ID
                                                        )
                                                 )[1]
                                             )
                                 ]">


        <xsl:value-of select="concat('    ', ., $NL)"/>

      </xsl:for-each>

    </xsl:for-each>

  </xsl:template>
</xsl:stylesheet>


When this transformation is applied upon the following source xml document:

<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>10010</CHARACTER_ID>
    <CHARACTER_STATUS>3</CHARACTER_STATUS>
    <LOCATION_ID>45020</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>45010</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>444444</CHARACTER_ID>
    <CHARACTER_STATUS>3</CHARACTER_STATUS>
    <LOCATION_ID>45030</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>444444</CHARACTER_ID>
    <CHARACTER_STATUS>3</CHARACTER_STATUS>
    <LOCATION_ID>45030</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>45000</LOCATION_ID>
    <TARGET_CHARACTER_ID>60060</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 is:

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

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

Total sent: 7, Average sent by a sending character: 2.3333333333333335
Total received: 7, Average received by a receiving character: 2.3333333333333335

Room moves by character:
Character_ID: 10010:
    45040
    45020
Character_ID: 444444:
    45010
    45030
Character_ID: 50050:
    45000


Hope that this really helped.

Cheers,
Dimitre Novatchev.




__________________________________________________
Do You Yahoo!?
Send FREE video emails in Yahoo! Mail!
http://promo.yahoo.com/videomail/

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



Current Thread
Keywords
xml