[XSLT] Sub Groeperen

Pagina: 1
Acties:

  • dominion99
  • Registratie: December 2001
  • Laatst online: 13-08 00:37
Ik ben iets aan het proberen met Key's in XSLT, maar volgens mij werkt het net iets anders dan ik denk.

Onderstaand probleem is geen real-life probleem vandaar de wellicht vreemde combinaties :)

Ik heb een Family, dit kunnen er meerdere zijn, een family heeft meerder contacts. Een contact heeft op zijn beurt een achternaam en voornaam.

Er moet een lijst gegenereerd worden die een overzicht geeft van Family's met daarin welke verschillende achternamen hierin voorkomen, bij elke achternaam moet een lijst van verschillende voornamen komen. De achternamen bij een family moeten uniek zijn.

Ik heb een bestaand voorbeeld gebruikt welke een lijst van achternamen produceert die uniek zijn en de daarbij horende voornamen (hoeven niet uniek te zijn)

Voor de unieke achternamen lijst gebruik ik een Key

XML:
1
<xsl:key name="contacts-by-surname" match="contact" use="surname" />


Deze gebruik ik in een for-each:

XML:
1
<xsl:for-each select="contact[count(. | key('contacts-by-surname', surname)[1]) = 1]">


Dit werkt prima.

Nu wil ik deze lijst per family doen, maar met de bovenstaande key en for-each lus groepeert hij alle achternamen samen, ongeacht bij welke family die hoort.

Mijn gedachte was als ik een for-each gebruik dat dan de key op de huidige node werkt, waar ik op dat moment ben, maar volgens mij gaat het hier dus mis, de key werkt op het gehele document.

Is er een mogelijkheid zodat de Key op de node werkt van dat moment.

Ik krijg dus wel een unieke lijst van achternamen, maar alle famillies zitten door elkaar.

De XSLT en XML heb ik niet gepost voor de overzichtelijkheid van dit topic, dit kan op verzoek nog toegevoegd worden.

  • dominion99
  • Registratie: December 2001
  • Laatst online: 13-08 00:37
Ik heb het volgende toegevoegd:
XML:
1
<xsl:for-each-group select="family" group-by="@id">


Dat betekend dus dat ik eerst door de family's wandel, daarna pas ik de for-each lus toe met de contacts-by-surname key, zie post hierboven.

Dit heeft als resultaat dat bij de eerste family alle namen worden weergegeven die er zijn voor de 1e familie. Bij de 2e familie wordt alleen nog de naam weergegeven die niet lid was van familie 1 en bij familie 3 worden geen namen meer weergegeven omdat de namen die daar gedefineerd zijn al genoemd zijn bij familie 1.

Volgens mij is de expressie bij de for-each-lus niet geldig zodra je met de volgende familie langs komt, maar ik vraag me dan af waarom niet. Het Key element is toch alleen geldig voor de nodes waarin je hem aanroept?

Voor de duidelijkheid heb ik mijn xml data toegevoegd

XML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<?xml version="1.0" encoding="UTF-8"?>
<records>
    <family id="1">
        <contact id="0001">
            <title>Mr</title>
            <forename>John</forename>
            <surname>Smith</surname>
        </contact>
        <contact id="0002">
            <title>Dr</title>
            <forename>Amy</forename>
            <surname>Jones</surname>
        </contact>
        <contact id="0002">
            <title>Dr</title>
            <forename>Amy2</forename>
            <surname>Jones</surname>
        </contact>  
        <contact id="0002">
            <title>Dr</title>
            <forename>Amy2</forename>
            <surname>Test</surname>
        </contact>      
    </family>
    <family id="2">
        <contact id="0010">
            <title>Mr</title>
            <forename>John</forename>
            <surname>Joker</surname>
        </contact>
        <contact id="0012">
            <title>Dr</title>
            <forename>Amy</forename>
            <surname>Jones</surname>
        </contact>
    </family>
        <family id="3">
        <contact id="0020">
            <title>Mr</title>
            <forename>John</forename>
            <surname>Jones</surname>
        </contact>
        <contact id="0021">
            <title>Mr</title>
            <forename>John1</forename>
            <surname>Smith</surname>
        </contact>  
    </family>
</records>

[ Voor 5% gewijzigd door dominion99 op 28-11-2006 21:15 ]


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Waarom (ik heb me verder nog niet echt verdiept in je probleem) gebruik een een for-each en niet gewoon een template binnen een template?

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • dominion99
  • Registratie: December 2001
  • Laatst online: 13-08 00:37
Geen idee, vanuit mijn gedachte gaat een for-each over de elementen die ik aangeef in de foreach, maar goed ik programmeer in .NET en vanuit die gedacht benader ik een for-each.

  • dominion99
  • Registratie: December 2001
  • Laatst online: 13-08 00:37
Ik heb het voor elkaar, voor de geinteresseerden hier is mijn gevonden oplossing, is dit nu te omslachtig? Het is geen script request omdat het voor mij nu werkt, maar als er betere oplossingen zijn dan hoor ik het graag.

Ik heb nu een for-each-group gebruikt en om alle namen te doorlopen met de key heb ik gecheckt of die bij de huidige family hoort.

Dat heb ik tijdelijk opgeslagen in een variabele om daarna ook nog een count te doen van het aantal objecten.


Hier is mijn XSLT:
XML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:xdt="http://www.w3.org/2005/xpath-datatypes">
    <xsl:output version="1.0" encoding="UTF-8" indent="no" omit-xml-declaration="no" media-type="text/html"/>
    <xsl:key name="contacts-by-surname" match="contact" use="surname" />
    
    <xsl:template match="family">
    <html>
        <body>
            <table border="1">
                <xsl:variable name="familyId" select="@id"></xsl:variable>                                  
                <xsl:for-each-group select="contact" group-by="surname">
                    <tr>
                        <td>
                            FamilyId: <xsl:value-of select="$familyId" /> 
                        </td>
                        <td>
                            Surname: <xsl:value-of select="surname" />
                        </td>   
                        <td>
                            <xsl:variable name="names" select="key('contacts-by-surname', surname)[../@id = $familyId]"></xsl:variable>                                 
                            <xsl:value-of select="count($names)"/> <br />
                            <xsl:for-each select="$names">
                                <xsl:value-of select="forename" /> <br />
                            </xsl:for-each>
                        </td>
                    </tr>
                </xsl:for-each-group>
            </table>
            <br/>
        </body>
    </html>
    </xsl:template>
</xsl:stylesheet>

  • dominion99
  • Registratie: December 2001
  • Laatst online: 13-08 00:37
Edit: Kom er ook achter dat de variable vervangen kan worden door current-group(), dat maakt het dan nog wat simpeler, het Key attribuut wordt daardoor overbodig in bovenstaand voorbeeld.

Rest me nog een laatste vraag, hoe kan ik nu bepalen dat ik niet in dezelfde group-by zit. (dus dezelfde surname) ik wil per surname een verschillende stylesheet toepassen (2 verschillende kleuren rijen)

Met position() krijg ik de verkeerde waardes.

[ Voor 40% gewijzigd door dominion99 op 29-11-2006 11:04 ]

Pagina: 1