[xsl] Re: How to show distinct node values?

Subject: [xsl] Re: How to show distinct node values?
From: "Dimitre Novatchev" <dnovatchev@xxxxxxxxx>
Date: Wed, 23 Jul 2003 22:22:03 +0200
Just using the good ole Muenchian method for grouping we have:

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

 <xsl:output method="text"/>

  <xsl:key name="kActScene" match="SCENE"
   use="concat(../TITLE, '|', TITLE)"/>

   <xsl:key name="kSpeaker" match="SPEAKER"
    use="concat(generate-id(ancestor::ACT[1]),
               '|',
                generate-id(ancestor::SCENE[1])
                )"/>

   <xsl:key name="kSpkScene" match="SPEAKER"
    use="concat(generate-id(ancestor::ACT[1]),
               '|',
                generate-id(ancestor::SCENE[1]),
                '|',
                .
                )"/>

  <xsl:key name="kSpkLine" match="LINE"
   use="concat(generate-id(ancestor::ACT[1]),
               '|',
                generate-id(ancestor::SCENE[1]),
                '|',
                preceding-sibling::SPEAKER[1]
                )"/>

  <xsl:template match="/">
   <xsl:for-each
    select="PLAY/ACT/SCENE
              [generate-id()
              =
               generate-id(key('kActScene',
                               concat(../TITLE, '|', TITLE)
                               )[1]
                           )
               ]">

      <xsl:value-of
       select="concat('&#xA;',
                      ../TITLE,
                      '&#9;',
                      substring-before(TITLE, '.'),
                      '&#xA;'
                      )"/>
      <xsl:variable name="vidScene" select="generate-id()"/>
      <xsl:variable name="vidAct" select="generate-id(..)"/>

      <xsl:for-each
       select="key('kSpeaker',
                   concat($vidAct,
                          '|',
                          $vidScene
                          )
                   )
                   [generate-id(.)
                   =
                    generate-id(key('kSpkScene',
                                    concat($vidAct,
                                           '|',
                                           $vidScene,
                                           '|',
                                           .
                                           )
                                    )[1]
                                )
                   ]">
         <xsl:value-of
         select="concat('&#9;&#9;',
                         .,
                         '&#9;',
                         count(key('kSpkLine',
                                   concat($vidAct,
                                          '|',
                                          $vidScene,
                                          '|',
                                          .
                                          )
                                   )
                               ),
                         '&#xA;')"/>
       </xsl:for-each>

    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>


When the above transformation (89 lines of code, which could be cut in half
in case I were not writing well-indented code)  is applied on the file:

http://www.andrew.cmu.edu/user/akj/shakespeare/r_and_j.xml (5985 lines)

The wanted result is produced for 84.08 milliseconds (using MSXML4 on a
1.7GHz Pentium with 256MB RAM):



ACT I SCENE I
  SAMPSON 31
  GREGORY 20
  ABRAHAM 5
  BENVOLIO 51
  TYBALT 5
  First Citizen 2
  CAPULET 3
  LADY CAPULET 1
  MONTAGUE 28
  LADY MONTAGUE 3
  PRINCE 23
  ROMEO 66

ACT I SCENE II
  CAPULET 34
  PARIS 4
  Servant 18
  BENVOLIO 20
  ROMEO 27

ACT I SCENE III
  LADY CAPULET 37
  Nurse 61
  JULIET 8
  Servant 4

ACT I SCENE IV
  ROMEO 34
  BENVOLIO 13
  MERCUTIO 73

ACT I SCENE V
  First Servant 9
  Second Servant 5
  CAPULET 56
  Second Capulet 3
  ROMEO 28
  Servant 1
  TYBALT 17
  JULIET 19
  Nurse 15
  BENVOLIO 1

ACT II SCENE I
  ROMEO 2
  BENVOLIO 9
  MERCUTIO 34

ACT II SCENE II
  ROMEO 87
  JULIET 115
  Nurse 2

ACT II SCENE III
  FRIAR LAURENCE 72
  ROMEO 25

ACT II SCENE IV
  MERCUTIO 88
  BENVOLIO 13
  ROMEO 46
  Nurse 46
  PETER 6
  NURSE 9

ACT II SCENE V
  JULIET 44
  Nurse 36

ACT II SCENE VI
  FRIAR LAURENCE 18
  ROMEO 12
  JULIET 7

ACT III SCENE I
  BENVOLIO 53
  MERCUTIO 66
  TYBALT 14
  ROMEO 36
  First Citizen 4
  PRINCE 16
  LADY CAPULET 11
  MONTAGUE 3

ACT III SCENE II
  JULIET 116
  Nurse 31

ACT III SCENE III
  FRIAR LAURENCE 87
  ROMEO 70
  Nurse 22

ACT III SCENE IV
  CAPULET 31
  PARIS 4
  LADY CAPULET 2

ACT III SCENE V
  JULIET 105
  ROMEO 24
  Nurse 25
  LADY CAPULET 37
  CAPULET 64

ACT IV SCENE I
  FRIAR LAURENCE 56
  PARIS 23
  JULIET 48

ACT IV SCENE II
  CAPULET 26
  Second Servant 5
  Nurse 2
  JULIET 12
  LADY CAPULET 1
  LADY  CAPULET 2

ACT IV SCENE III
  JULIET 56
  LADY CAPULET 3

ACT IV SCENE IV
  LADY CAPULET 3
  Nurse 4
  CAPULET 21
  First Servant 1
  Second Servant 2

ACT IV SCENE V
  Nurse 28
  LADY CAPULET 13
  CAPULET 28
  FRIAR LAURENCE 25
  PARIS 6
  First Musician 9
  PETER 27
  Second Musician 4
  Musician 1
  Third Musician 1

ACT V SCENE I
  ROMEO 72
  BALTHASAR 11
  Apothecary 7

ACT V SCENE II
  FRIAR JOHN 13
  FRIAR LAURENCE 17

ACT V SCENE III
  PARIS 33
  PAGE 9
  ROMEO 83
  BALTHASAR 21
  FRIAR LAURENCE 76
  JULIET 14
  First Watchman 19
  Second Watchman 1
  Third Watchman 3
  PRINCE 37
  CAPULET 10
  LADY CAPULET 5
  MONTAGUE 10


As an exercise, one may sort these by speaker or by number of lines (within
a scene).


=====
Cheers,

Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL


"Poort, J." <J.Poort@xxxxxxxxxxxx> wrote in message
news:BA6D7ACFEC40074CB82F14CC17369E259D59CB@xxxxxxxxxxxxxxxxxxx
>
> Hello,
> I'm using a big XML file and want to transform the data by XSL
> I open the XML in IE 6.0 and say  href="r_and_j.xslt".
> In r_and_j.xslt  I enter the XSL-commands.
>
> The XML file contains the play Romeo and Juliet.
> I want now to show in a table for each ACT and each SCENE the names of the
SPEAKER
> and the number of LINES he has to speak.
> Problemn is that I'm not able to show the distinct node values for the
SPEAKER.
> I'm able to count the lines for the SPEAKERS.
> On your site I found solutions like
>    <xsl:key  name="speakers"  match="SPEAKER" use="." />
> or
> <xsl:for-each  select="./SPEAKER[not(.=preceding::speaker)]"  />
> They don't work for me (at least I don't know how!)
>
> Please advise,
> Thanks,
>
> Joek Poort
>
> More info below:
> I get :
> Speakers number lines
> ACT I SCENE I   SAMPSON 10
> GREGORY 8
> SAMPSON 10
> GREGORY 8
> SAMPSON 10
> GREGORY 8
> SAMPSON 10
> GREGORY 8
> SAMPSON 10
> GREGORY 8
> SAMPSON 10
> GREGORY 8
> ABRAHAM 24
> BALTASAR 12
> ABRAHAM 24
> BALTASAR 12
> ABRAHAM 24
> BALTASAR 12
>  Etc.....
>
> I would like to get something like:
>
> Speakers number lines
> ACT I SCENE I   SAMPSON 10
> GREGORY 8
> ABRAHAM 24
> BALTASAR 12
> BENVOLIO 6
> TYBALT 6
> PRINCE 9
> SCENE || SAMPSON 3
> ROMEO 23
> JULIA 2
> Servant 4
>
>
> Small Part of the XML is
> <?xml version="1.0" standalone="yes"?><?xml-stylesheet type="text/xsl"
href="r_and_j.xslt"?>
>
> <PLAY>
> <TITLE>The Tragedy of Romeo and Juliet</TITLE>
> <PLAYSUBT>ROMEO AND JULIET</PLAYSUBT>
> <ACT><TITLE>ACT I</TITLE>
> <SCENE><TITLE>SCENE I.  Verona. A public place.</TITLE>
> <STAGEDIR>Enter SAMPSON and GREGORY, of the house of Capulet,
> armed with swords and bucklers</STAGEDIR>
> <SPEECH>
> <SPEAKER>SAMPSON</SPEAKER>
> <LINE>Gregory, o' my word, we'll not carry coals.</LINE>
> </SPEECH>
> <SPEECH>
> <SPEAKER>GREGORY</SPEAKER>
> <LINE>No, for then we should be colliers.</LINE>
> </SPEECH>
> <SPEECH>
> <SPEAKER>SAMPSON</SPEAKER>
> <LINE>I mean, an we be in choler, we'll draw.</LINE>
> </SPEECH>
> <SPEECH>
> <SPEAKER>GREGORY</SPEAKER>
> <LINE>Ay, while you live, draw your neck out o' the collar.</LINE>
> </SPEECH>
>
> <SPEECH>
> <SPEAKER>SAMPSON</SPEAKER>
> <LINE>'Tis all one, I will show myself a tyrant: when I</LINE>
> <LINE>have fought with the men, I will be cruel with the</LINE>
> <LINE>maids, and cut off their heads.</LINE>
> </SPEECH>
>
> <STAGEDIR>Enter ABRAHAM and BALTHASAR</STAGEDIR>
>
> <SPEECH>
> <SPEAKER>ABRAHAM</SPEAKER>
> <LINE>Do you bite your thumb at us, sir?</LINE>
> </SPEECH>
>
> <SPEECH>
> <SPEAKER>SAMPSON</SPEAKER>
> <LINE>I do bite my thumb, sir.</LINE>
> </SPEECH>
>
> <SPEECH>
> <SPEAKER>BENVOLIO</SPEAKER>
> <LINE>Part, fools!</LINE>
> <LINE>Put up your swords; you know not what you do.</LINE>
> </SPEECH>
> <STAGEDIR>Beats down their swords</STAGEDIR>
> <STAGEDIR>Enter TYBALT</STAGEDIR>
>
> <SPEECH>
> <SPEAKER>TYBALT</SPEAKER>
> <LINE>What, art thou drawn among these heartless hinds?</LINE>
> <LINE>Turn thee, Benvolio, look upon thy death.</LINE>
> </SPEECH>
>
> <SPEECH>
> <SPEAKER>BENVOLIO</SPEAKER>
> <LINE>I do but keep the peace: put up thy sword,</LINE>
> <LINE>Or manage it to part these men with me.</LINE>
> </SPEECH>
>
> <SPEECH>
> <SPEAKER>TYBALT</SPEAKER>
> <LINE>What, drawn, and talk of peace! I hate the word,</LINE>
> <LINE>As I hate hell, all Montagues, and thee:</LINE>
> <LINE>Have at thee, coward!</LINE>
> </SPEECH>
>
> <SPEECH>
> <SPEAKER>PRINCE</SPEAKER>
> <LINE>Rebellious subjects, enemies to peace,</LINE>
> <LINE>Profaners of this neighbour-stained steel,--</LINE>
> <LINE>Will they not hear? What, ho! you men, you beasts,</LINE>
> <LINE>That quench the fire of your pernicious rage</LINE>
> <LINE>With purple fountains issuing from your veins,</LINE>
> <LINE>On pain of torture, from those bloody hands</LINE>
> <LINE>Throw your mistemper'd weapons to the ground,</LINE>
> <LINE>And hear the sentence of your moved prince.</LINE>
> <LINE>Three civil brawls, bred of an airy word,</LINE>
> <LINE>By thee, old Capulet, and Montague,</LINE>
> <LINE>Have thrice disturb'd the quiet of our streets,</LINE>
> <LINE>And made Verona's ancient citizens</LINE>
> <LINE>Cast by their grave beseeming ornaments,</LINE>
> <LINE>To wield old partisans, in hands as old,</LINE>
> <LINE>Canker'd with peace, to part your canker'd hate:</LINE>
> <LINE>If ever you disturb our streets again,</LINE>
> </SPEECH>
> </ACT>
>
> </SCENE>
>
>
>
>  XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
>
>




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


Current Thread