[XSL] For loopje adhv oplopende integer doorlopen

Pagina: 1
Acties:

  • r0bert
  • Registratie: September 2001
  • Laatst online: 26-05 09:56
Ik heb vage oplossing gevonden met xsl:variable's enzo, maar ik zoek even de beste oplossing die in zo veel mogelijk browsers werkt.. Zal het even toelichten.. Heb bijv de volgende datafeed

XML:
1
2
3
4
5
6
<data>
   <msg number="1" size="255" />
   <msg number="2" size="243" />
   <msg number="4" size="190" />
   <msg number="8" size="98" />
</data>

Nu moet de output zo worden:
XHTML:
1
2
3
4
5
6
7
1 - 255
2 - 243
3 - ???
4 - 190
6 - ???
7 - ???
8 - 98

Daarvoor moet ik dus een loopje van 1 tot 8 doorlopen.. hoe doe ik dat het meest praktisch (en het liefst op zo'n manier dat het in zo veel mogelijk browsers werkt.. dus meer dan alleen ie 6).. Heb gezocht, maar kon in de hele waslijst nix vinden over een oplopende loopje..

//edit:
eigenlijk wil ik het zelfs nog zo krijgen, dat het aantal loopjes dat ie maakt, gelijk is het aan het hoogste 'number' attribuut, maar dat kan ik denk ik zelf ook nog wel vinden .. iets met max() en het attribuut ofzo denk ik.. als ik helemaal fout zeg, laat plz iemand het zeggen, anders zoek ik me voor nix de pleures :P

[ Voor 27% gewijzigd door r0bert op 08-12-2003 23:41 ]


  • Genoil
  • Registratie: Maart 2000
  • Laatst online: 12-11-2023
tsja is dit nou een script-request of niet?
eigenlijk moet dat ontmoedigd worden he, maar kvond het wel een leuk probleempje om voor het slapen gaan op te lossen :7

alsjeblieft!
code:
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
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version = '1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
    <xsl:output method="html" />    
    <xsl:template match="//msg">
        <xsl:value-of select="@number" />
        <xsl:text> - </xsl:text>
        <xsl:value-of select="@size" />
        <br />
        <xsl:call-template name="foo" >
            <xsl:with-param name="bar" select="1" />
        </xsl:call-template>
    </xsl:template>
    
    <xsl:template name="foo">
        <xsl:param name="bar" />
        <xsl:variable name="bas" select="number(following::msg/@number)" />
        <xsl:variable name="baz" select="@number+$bar" />       
        <xsl:if test="$bas &gt; 0 and $bas != $baz">
            <xsl:value-of select="$baz" />
            <xsl:text> - </xsl:text>
            ???<br />               
            <xsl:call-template name="foo" >
                <xsl:with-param name="bar" select="$bar+1" />
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
    
</xsl:stylesheet>


kwilt morgen wel ff uitleggen..maar nu eerst slapen :z

[edit]

ok goeiemorgen :)

ik heb geen idee of dit efficienter kan (maar aan de complexiteit ervan tov de moeilijkheid vh probleem zou je denken van wel), maar het probleem zit em er dus in dat je met XSLT geen variabele kunt ophogen in een loopje. Tenminste, niet op een iteratieve manier zoals bij een procedurele programmeertaal.

"foo" is zo'n recursief template dat voor elke <msg> in 1 keer aangeroepen wordt, en zich afh. van bepaalde condities zichzelf weer aanroept. de parameter $bar houdt bij hoevaak "foo" zichzelf heeft aangeroepen + 1 (de keer dattie aangeroepen wordt vanuit het andere tpl), dit is dus het "loopje" aspect.

na het uitprinten van elke msg, wordt in "foo" gekeken of het attr. @number van de volgende (following) msg gelijk is die van de huidige <msg> (dit blijft dezelfde node todat de volgende //msg wordt afgehandeld) ($bas). Is dat niet het geval, dan print ie de waarde van het huidige @number + het aantal keer dat die check is uitgevoerd ($baz = @number + $bar), en dan roept ie zichzelf weer aan met een opgehoogde waarde voor $bar. Checken op $bas>0 is tenslotte nog even nodig om te zorgen dattie stopt na de laaste msg.

[ Voor 112% gewijzigd door Genoil op 09-12-2003 17:17 ]


  • r0bert
  • Registratie: September 2001
  • Laatst online: 26-05 09:56
Even simpel pseudo:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
$variabele = 1

sorteren //msg[@number]

foreach //msg
{
     if (.[@number] == $variabele)
        value of "$variabele - @size"
     else
        value of "$variabele - ???"
     
     $variabele + 1
}

Zoiets kan ik 'rvan bakken.. Dan stopt ie ook automatisch als ie de laatste msg heeft gehad! Ik moet nu even naar de les, want zit op school.. reageer vanmiddag wel verder! Iig alvast bedankt :)

  • Genoil
  • Registratie: Maart 2000
  • Laatst online: 12-11-2023
r0bert schreef op 09 december 2003 @ 11:07:
Even simpel pseudo:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
$variabele = 1

sorteren //msg[@number]

foreach //msg
{
     if (.[@number] == $variabele)
        value of "$variabele - @size"
     else
        value of "$variabele - ???"
     
     $variabele + 1
}

Zoiets kan ik 'rvan bakken.. Dan stopt ie ook automatisch als ie de laatste msg heeft gehad! Ik moet nu even naar de les, want zit op school.. reageer vanmiddag wel verder! Iig alvast bedankt :)
Ja dat zou lekker zijn. Maar die pseudo code kan nooit werken, omdat:
- <xsl:for-each> in geval van je voorbeeld maar 4 keer doorlopen wordt, gewoon voor elke msg
- je in XSLT geen waarde kunt toekennen aan een variabele, waarin de waarde van de variabele zelf in de select zit. dus:

code:
1
2
3
4
        <xsl:for-each select="msg">
            <xsl:variable name="counter" select="$counter + 1" />
            <xsl:value-of select = "$counter" />
        </xsl:for-each>


kan NIET! dat lijkt op het eerste gezicht genoeg reden om XSLT dan maar weer naar de prullenbak te verwijzen, maar wat je eigenlijk moet doen is al je procedurele programmeerkennis in de prullenbak gooien en declaratief gaan denken. ;)

oja en mijn oplossing gaat idd wel uit van een lijst die gesorteerd is op @number. als dat niet zo is moet die nog even met xsl:sort gesorteerd worden...

[ Voor 11% gewijzigd door Genoil op 09-12-2003 12:12 ]


  • r0bert
  • Registratie: September 2001
  • Laatst online: 26-05 09:56
Oeps ja, dat was wel een hele domme denkfout :S ik ga ff wat knutselen en post ik zometeen het resultaat even! Raar dat je trouwens niets kan toekennen aan een variabele dan :S moet toch gewoon 1 bij een variabele (number()?) op kunnen tellen :S Nou iig alvast bedankt, ik laat wat horen!

Edit:

Hier gaat het bij mij fout :'(
code:
1
<xsl:variable name="bas" select="number(following::les@uur)" />

Dit lijkt gelukkig al beter:)
code:
1
<xsl:variable name="bas" select="number(following::les[@uur])" />

was al bang dat het aan number() lag..

Maar het werkt nog steeds niet.. krijg nog steeds geen tussennummer te zien :S

http://www.robertdewilde.nl/tmpTemp.xml

edit
code:
1
number(following::msg[@number])

geeft NaN :?

[ Voor 74% gewijzigd door r0bert op 09-12-2003 15:32 ]


  • marcusk
  • Registratie: Februari 2001
  • Laatst online: 26-09-2023
Hier was ik gisteren mee bezig, maar aangezien Genoil al iets gepost had heb ik het niet gepost. Maar aangezien die niet werkt, voici:

code:
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
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template match="/">  
    <xsl:call-template name="print-data"/>
  </xsl:template>
  
  <xsl:template name="print-data">
    <xsl:param name="index" select="1"/>
    
    <xsl:variable name="size" select="data/msg[@number = $index]/@size"/>

    <xsl:value-of select="$index"/> -
    <xsl:choose>
      <xsl:when test="$size">
        <xsl:value-of select="$size"/>
      </xsl:when>
      <xsl:otherwise>
        ???
      </xsl:otherwise>
    </xsl:choose>    
    <br/>
    
    <xsl:if test="data/msg[@number &gt; $index]">
      <xsl:call-template name="print-data">
        <xsl:with-param name="index" select="$index + 1"/>
      </xsl:call-template>
    </xsl:if>
  </xsl:template>

</xsl:stylesheet>

Deze is ook recursief (lijkt mij de enige manier waarop je dit kunt doen).

  • r0bert
  • Registratie: September 2001
  • Laatst online: 26-05 09:56
Lijkt aardig te werken! :)

Zit nog met 1 laatste probleem!

Als ik nou dit heb
XML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<data>
   <group>
      <msg number="1" size="255" />
      <msg number="2" size="243" />
      <msg number="4" size="190" />
      <msg number="8" size="98" />
   </group>
   <group>
      <msg number="1" size="255" />
      <msg number="2" size="243" />
      <msg number="4" size="190" />
      <msg number="5" size="98" />
   </group>
</data>


edit:

psuedo:
code:
1
2
3
4
5
6
7
8
9
10
11
<template msg>
    <apply-template num>
         <with-paran name="index" select="@number" />
    </apply-template>
</template>

<template match="num" name="num">
     <paran name="index" />

     <xsl:value-of select="$index" /><br />
</template>

Zoiets moet het worden zodat de $index niet steeds op 1 begint, maar met het getal van het number attribuut van de laatste msg node! Hoe krijg ik dat voor elkaar :? Ben aan het proberen, maar nix lijkt te werken

[ Voor 210% gewijzigd door r0bert op 09-12-2003 17:16 ]


  • Genoil
  • Registratie: Maart 2000
  • Laatst online: 12-11-2023
ow...die van mij heb ik alleen getest met Sablotron 0.9 (PHP extensie)

maar MSXML slikt dus blijkbaar following::msg@number niet. weird...

[edit]

code:
1
<xsl:variable name="bas" select="number(following::msg/@number)" />


|:(

nu werkt ie wel

marcusk ook fraaie oplossing!

[edit2]

wat wil je nou preices met die groepen? kun je een voorbeeld output posten?

[ Voor 125% gewijzigd door Genoil op 09-12-2003 17:21 ]


  • r0bert
  • Registratie: September 2001
  • Laatst online: 26-05 09:56
Hier voorbeeldje zoals het ong. moet worden..

xml:
XML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<data>
   <group ref="Gisteren">
      <msg number="1" size="255" />
      <msg number="2" size="243" />
      <msg number="4" size="190" />
      <msg number="8" size="98" />
   </group>
   <group ref="Vandaag">
      <msg number="1" size="123" />
      <msg number="2" size="40" />
      <msg number="3" size="183" />
      <msg number="5" size="12" />
   </group>
</data>


xsl:
code:
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
<xsl:template match="//group">
    <div>
        <h1><xsl:value-of select="@ref" /></h1>
    
        <xsl:apply-templates select="msg">
            <xsl:with-param name="index" select="msg/@number" />
        </xsl:apply-templates>
    </div>
</xsl:template>

<xsl:template name="msg" match="msg">
    <xsl:param name="index" />
    
    <xsl:choose>
        <xsl:when test="number(@number) = $index">
            <div class="stlBestaat">
                <xsl:value-of select="@number" /><!-- of $index //-->
                 - 
                <xsl:value-of select="@size" />
            </div>
        </xsl:when>
        <xsl:otherwise>
            <div class="stlBestaatNiet">
                <xsl:value-of select="$index" /> - ???
            </div>
        </xsl:otherwise>
    </xsl:choose> 
    
    <xsl:if test="following-sibling::msg/@number &gt; $index">
        <xsl:call-template name="msg">
            <xsl:with-param name="index" select="$index + 1"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>


output:
Text output:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
GISTEREN
1 - 255
2 - 243
3 - ???
4 - 190
5 - ???
6 - ???
7 - ???
8 - 98
VANDAAG
1 - 123
2 - 40
3 - 183
4 - ???
5 - 12


maar dit stukje (xsl) werkt dus niet lekker:
code:
1
<xsl:with-param name="index" select="msg/@number" />

dat was eerst:
code:
1
<xsl:with-param name="index" select="1" />

maar dan reset ie steeds naar 1 terwijl het nog niet moet..


http://www.robertdewilde.nl/_projects/Rms/tmpTemp.xml

[ Voor 153% gewijzigd door r0bert op 09-12-2003 18:07 ]


  • Genoil
  • Registratie: Maart 2000
  • Laatst online: 12-11-2023
Ja ik gebruik natuurlijk wel m'n eigen oplossing ;)

code:
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
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version = '1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
    <xsl:output method="html" />    
    
     <xsl:template match="//group">
        <h2><xsl:value-of select="@ref" /></h2>
        <xsl:apply-templates />
     </xsl:template>
     
     <xsl:template match="msg">     
        <xsl:value-of select="@number" />
        <xsl:text> - </xsl:text>
        <xsl:value-of select="@size" />
        <br />
        <xsl:call-template name="emptylinechecker" >
            <xsl:with-param name="counter" select="1" />
        </xsl:call-template>
    </xsl:template>
    
    <xsl:template name="emptylinechecker">
        <xsl:param name="counter" />
        <xsl:variable name="nextnumber" select="number(following-sibling::msg/@number)" />
        <xsl:variable name="linenumber" select="number(@number)+$counter" />        
        <xsl:if test="$nextnumber &gt; 0 and $nextnumber != $linenumber">
            <xsl:value-of select="$linenumber" />
            <xsl:text> - </xsl:text>
            ???<br />                
            <xsl:call-template name="emptylinechecker" >
                <xsl:with-param name="counter" select="$counter+1" />
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
    
</xsl:stylesheet>


het extra templateje voor de groups is natuurlijk niet zo'n probleem. verder zit er een kleine aanpassing in: following-sibling ipv following...

(btw hij doet het deze keer wel gewoon in IE)

edit:

maar ff wat logischer benamingen gekozen dan foo en bar enzo :P

[ Voor 48% gewijzigd door Genoil op 09-12-2003 18:24 ]


  • r0bert
  • Registratie: September 2001
  • Laatst online: 26-05 09:56
Moet ik even weer alles ombouwen :P Ik maak wel gewoon even allebei de manieren :) Des te meer kans dat een van beiden werkend zal zijn :)

Ben zo klaar! :)

Edit:
Relaxed! het werkt! Eindelijk! Ik ga het nog ff beetje goed doornemen en dan kan ik eindelijk verder! :P Super bedankt! :)

[ Voor 31% gewijzigd door r0bert op 09-12-2003 18:26 ]


  • Genoil
  • Registratie: Maart 2000
  • Laatst online: 12-11-2023
r0bert schreef op 09 december 2003 @ 18:18:
Edit:
Relaxed! het werkt! Eindelijk! Ik ga het nog ff beetje goed doornemen en dan kan ik eindelijk verder! :P Super bedankt! :)
jij ook bedankt he! ik moet nog veel leren over xslt, problemen van anderen helpen daar goed bij :)
Pagina: 1