Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[XSL] Bijbehorende data ophalen na een distinct select

Pagina: 1
Acties:

  • IcE_364
  • Registratie: Februari 2002
  • Nu online
Ik probeer de daap/itunes xml output te parsen (Dus niet de library.xml). Dit heeft de volgende layout:


XML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<daap.databasesongs>
<dmap.listing>
    <dmap.listingitem>
        <daap.songalbum>Album</daap.songalbum>
        <daap.songartist>Artiest</daap.songartist>
        <daap.songbitrate>192</daap.songbitrate>
        <dmap.itemid>1</dmap.itemid>
        <daap.songformat>mp3</daap.songformat>
        <dmap.itemname>Tracknaam</dmap.itemname>
        <daap.songsize>123456789</daap.songsize>
        <daap.songtrackcount>1</daap.songtrackcount>
        <daap.songtracknumber>1</daap.songtracknumber>
        <daap.songyear>2006</daap.songyear>
    </dmap.listingitem>
</dmap.listing>
</daap.databasesongs>


Elke track heeft dus een dmap.listingitem. Ik wil hieruit een lijst genereren die er zo uit ziet:
  • Artist1 - Album
    • Track1
    • Track2
  • Artist2 - Album
    • Track1
    • Track2
Aangezien Artist en Album informatie per track voor komt heb ik al een distinct for-each gemaakt op de albums, ik krijg op dit moment al de volgende output:
  • Artist1 - Album
  • Artist2 - Album
Dit bereik ik met de volgende code:

XML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<xsl:key name="songsByAlbum" match="daap.songalbum" use="."/>

<xsl:for-each select="/daap.databasesongs/dmap.listing/dmap.listingitem[generate-id(daap.songalbum)=generate-id(key('songsByAlbum',daap.songalbum))]">
    <xsl:sort select="daap.songartist"/>
    <xsl:variable name="Artist" select="daap.songartist"/>
                        
    <ul>
        <li>
            <xsl:value-of select="$Artist"/> - <xsl:value-of select="daap.songalbum"/>
            <ul>
                <!-- Hier moeten de tracks komen -->
            </ul>
        </li>
    </ul>
</xsl:for-each>


Mijn vraag: Hoe krijg ik alle tracks die bij het betreffende album horen binnen die for-each in een lijstje?

Ik heb al een nested for-each geprobeerd, maar dit zorgde bij 2500 albums voor het crashen van mn browser :)

  • CrankyGamerOG
  • Registratie: Juni 2003
  • Laatst online: 11:11

CrankyGamerOG

Assumption is the mother.....

geen idee, maar wat wil je er precies mee doen ? (nieuwsgierig ) jah dat weet je van mij he :)

[ Voor 77% gewijzigd door CrankyGamerOG op 09-05-2008 12:52 ]

KPN - Vodafone Ziggo Partner


  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 16-11 19:52

Gerco

Professional Newbie

Als je XSLT2.0 gebruikt kun je dit heel makkelijk doen met <xsl:for-each-group>

Als je dat niet hebt, zul je met een distinct select moeten werken en dan daarbinnen iets als <xsl:for-each select="dmap.listingitem[dmap.songalbum=$Album and dmap.songartist=$Artist]">. Die crash komt waarschijnlijk omdat een distinct for-each bijzonder inefficient is en geheugen *zuipt*. Helaas binnen XSLT1.0 ook de enige manier om dit te bereiken.

[ Voor 23% gewijzigd door Gerco op 09-05-2008 13:37 ]

- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!


  • Sendy
  • Registratie: September 2001
  • Niet online
Mijn XSLT kennis is een beetje roestig, so bare with me. Wat je kan volgens mij kan doen is het volgende:

Maak een template dat werkt op alle eerste combinaties van Artiest+Album. Dat kan je doen door alleen die elementen te matchen waarvoor die combinatie niet eerder voorkomt.

Binnen deze template kan je dan een ander template uitvoeren, met een select waarin je alleen de elementen selecteert die dezelfde Artiest+Album heeft als eerder.

Dit leest (ook) je hele data set voor ieder Artiest+Album, maar goed, daar kom je niet onderuit omdat alle liedjes kris-kras door je data set kunnen staan. (Een extra niveau had het beter/handiger gemaakt.)

  • IcE_364
  • Registratie: Februari 2002
  • Nu online
Ik ben nu voor de nested oplossing van Gerco gegaan aangezien ik van XSLT2.0 helemaal niets af weet. Het processen duurt zo'n 6 minuten nu met xsltproc, ben maar van de browser afgestapt. Ik heb nu de volgende code:

XML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<xsl:key name="songsByAlbum" match="daap.songalbum" use="."/>

<xsl:for-each select="/daap.databasesongs/dmap.listing/dmap.listingitem[generate-id(daap.songalbum)=generate-id(key('songsByAlbum',daap.songalbum))]">
    <xsl:sort select="daap.songartist"/>
    <xsl:variable name="Artist" select="daap.songartist"/>
    <xsl:variable name="Album" select="daap.songalbum"/>
                        
    <ul>
        <li>
            <xsl:value-of select="$Artist"/> - <xsl:value-of select="$Album"/>
            <ul>
                <xsl:for-each select="/daap.databasesongs/dmap.listing/dmap.listingitem[daap.songalbum=$Album and daap.songartist=$Artist]">
                    <xsl:sort select="daap.songtracknumber" data-type="number"/>
    
                    <li>
                        <xsl:value-of select="daap.songtracknumber"/>. <xsl:value-of select="dmap.itemname"/>
                    </li>
                </xsl:for-each>
            </ul>
        </li>
    </ul>
</xsl:for-each>


Optimalisaties zijn alsnog welkom. De methode van Sendy heb ik nog niet geimplementeerd maar ik denk dat deze (als het inderdaad kan) mijn implementatie niet veel zal ontlopen qua processtime

  • CrankyGamerOG
  • Registratie: Juni 2003
  • Laatst online: 11:11

CrankyGamerOG

Assumption is the mother.....

ik denk toch dat de implementatie van de code van sendy je een kortere processtime oplevert, dus ik zou zeggen probeer het gewoon

[ Voor 93% gewijzigd door CrankyGamerOG op 09-05-2008 15:37 ]

KPN - Vodafone Ziggo Partner


  • Sendy
  • Registratie: September 2001
  • Niet online
Nou, dat weet ik eigenlijk zelf niet :) Mijn methode gebruikt geen for-each, maar verder zal-ie er bijna hetzelfde uitzien als de laatste post van IcE. Ik ben niet bekend met die generate-id truc. Ik zou zoiets gebruiken:
code:
1
select="Items/Item[not(@Name=preceding-sibling::Item/@Name) ]">

Dit matcht alle elementen Items/Item waarvoor geldt dat het argument Name niet gelijk is aan een
preceding-siblings Items Name. Dat zijn dus alleen de eerste elementen met die @Name.
Dat zal jouw generate-id ook doen? Is dat sneller/beter om hetzelfde te bereiken? De tweede test is bijna precies de code van mijn voorstel, behalve dan "for-each". Dat wordt een apply-templates.

Ik heb ooit eens begrepen dat for-each een vreemde eend in de bijt is; en je hebt 't ook niet nodig :)
offtopic:
Is dit trouwens de Muenchian methode :?

[ Voor 34% gewijzigd door Sendy op 09-05-2008 22:27 ]


  • BHR
  • Registratie: Februari 2002
  • Laatst online: 18-11 20:21

BHR

Dit kan ook nog:

XML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<xsl:key name="songsByAlbum" match="daap.songalbum" use="."/>
<xsl:key name="songsByArtistAlbum" match="daap.songalbum" use="concat(daap.songartist, daap.songalbum)"/>

<xsl:for-each select="/daap.databasesongs/dmap.listing/dmap.listingitem[generate-id(daap.songalbum)=generate-id(key('songsByAlbum',daap.songalbum))]">
    <xsl:sort select="daap.songartist"/>
    <xsl:variable name="Artist" select="daap.songartist"/>
    <xsl:variable name="Album" select="daap.songalbum"/>
                        
    <ul>
        <li>
            <xsl:value-of select="$Artist"/> - <xsl:value-of select="$Album"/>
            <ul>
                <xsl:for-each select="key('songsByArtistAlbum', concat($Artist, $Album))">
                    <xsl:sort select="daap.songtracknumber" data-type="number"/>
    
                    <li>
                        <xsl:value-of select="daap.songtracknumber"/>. <xsl:value-of select="dmap.itemname"/>
                    </li>
                </xsl:for-each>
            </ul>
        </li>
    </ul>
</xsl:for-each>

[ Voor 13% gewijzigd door BHR op 09-05-2008 23:36 ]

No amount of key presses will shut off the Random Bug Generator

Pagina: 1