[xslt] soort van groeperen

Pagina: 1
Acties:

  • raptorix
  • Registratie: Februari 2000
  • Laatst online: 17-02-2022
Hoi ik heb volgende probleem, ik moet voor een menu de level 3 items groeperen in unordered lists van maximaal 3 items, dus output is iets als:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
            <ul>
                <li><a href="#">item 1</a></il>
                <li><a href="#">item 2</a></il>
                <li><a href="#">item 3</a></il>
            </ul>
            <ul>
                <li><a href="#">item 4</a></il>
                <li><a href="#">item 5</a></il>
                <li><a href="#">item 6</a></il>
            </ul>
            <ul>
                <li><a href="#">item 7</a></il>
            </ul>


Ik neem aan dat ik iets met position() en logaritme moet doen, maar weet niet hoe ik dit beste kan doen, iemand suggesties?

  • cariolive23
  • Registratie: Januari 2007
  • Laatst online: 18-10-2024
Hoe ziet de XML eruit die moet worden getransformeerd?

  • raptorix
  • Registratie: Februari 2000
  • Laatst online: 17-02-2022
Ik loop er over heen met iets als:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
  <xsl:template name="render_level3">
    <xsl:param name="item" />
    <xsl:for-each select="$item/child::item[sc:fld('Tonen in',.)='Header navigatie']">
      <ul>
        <li>
          <xsl:call-template name="SimpeleTekstLink">
            <xsl:with-param name="TekstVeld" select="'Pagina Titel'" />
            <xsl:with-param name="Item" select="." />
          </xsl:call-template>
        </li>
      </ul>
    </xsl:for-each>
  </xsl:template>

Dat werkt, maar ik wil dus als ware dat ie alleen elke 3e een UL schrijft.

  • cariolive23
  • Registratie: Januari 2007
  • Laatst online: 18-10-2024
met het volgende kun je kijken of de pointer weer 3 posities is opgeschoven:
code:
1
2
3
<xsl:if test="position() mod 3 = 0 ">
                doe iets
</xsl:if>

Ik ben er alleen nog niet uit hoe je de <ul> er tussen kan zetten (zonder foutmeldingen), waarschijnlijk even een aparte template aanmaken.

  • IntToStr
  • Registratie: December 2003
  • Laatst online: 00:20
In pseudocode:
code:
1
2
3
4
5
6
7
8
9
10
foreach item 
   if (position() mod 3 == 0) 
      <ul>
   endif
         <li>...</li>
   if (position() mod 3 == 2) 
      </ul>
   endif
end foreach
"sluit eventueel laatste open ul af"

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
IntToStr schreef op donderdag 03 september 2009 @ 15:42:
In pseudocode:
code:
1
2
3
4
5
6
7
8
9
10
foreach item 
   if (position() mod 3 == 0) 
      <ul>
   endif
         <li>...</li>
   if (position() mod 3 == 2) 
      </ul>
   endif
end foreach
"sluit eventueel laatste open ul af"
Het nadeel is dat je dan geen well-formed xml hebt, maar daar zal best een oplossing voor bestaan ( Mischien in een CData element o.i.d. ? )

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • raptorix
  • Registratie: Februari 2000
  • Laatst online: 17-02-2022
Woy schreef op donderdag 03 september 2009 @ 16:00:
[...]

Het nadeel is dat je dan geen well-formed xml hebt, maar daar zal best een oplossing voor bestaan ( Mischien in een CData element o.i.d. ? )
Precies, dat trucje had ik al gevonden, maar als ik een cdata doe, dan gaat ie de boel lopen urlencoden......

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Een beetje een hack, maar het kan wel:
XSLT:
1
<xsl:text disable-output-escaping="yes">&lt;...</xsl:text>

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


  • semicolon
  • Registratie: Mei 2004
  • Niet online
XSLT 2.0 ondersteund wel grouping overigens. Leuk voorbeeldje van deze pagina;

XML bestand:
XML:
1
2
3
4
5
6
7
8
9
10
11
<files>
  <file name="swablr.eps"     size="4313" project="mars"/>
  <file name="batboy.wks"     size="424"  project="neptune"/>
  <file name="potrzebie.dbf"  size="1102" project="jupiter"/>
  <file name="kwatz.xom"      size="43"   project="jupiter"/>
  <file name="paisley.doc"    size="988"  project="neptune"/>
  <file name="ummagumma.zip"  size="2441" project="mars"/>
  <file name="schtroumpf.txt" size="389"  project="mars"/>
  <file name="mondegreen.doc" size="1993" project="neptune"/>
  <file name="gadabout.pas"   size="685"  project="jupiter"/>
</files>

XSL Template:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<xsl:template match="files">
  <book>
    <xsl:for-each-group select="*"
               group-ending-with="*[position() mod 3 = 0]">
      <chapter>
        <xsl:for-each select="current-group()">
          <xsl:copy>
            <xsl:apply-templates  select="@*|node()"/>
          </xsl:copy>
        </xsl:for-each>
      </chapter>
    </xsl:for-each-group>
  </book>
</xsl:template>

Output:
XML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<book>
   <chapter>
      <file name="swablr.eps" size="4313" project="mars"/>
      <file name="batboy.wks" size="424" project="neptune"/>
      <file name="potrzebie.dbf" size="1102" project="jupiter"/>
   </chapter>
   <chapter>
      <file name="kwatz.xom" size="43" project="jupiter"/>
      <file name="paisley.doc" size="988" project="neptune"/>
      <file name="ummagumma.zip" size="2441" project="mars"/>
   </chapter>
   <chapter>
      <file name="schtroumpf.txt" size="389" project="mars"/>
      <file name="mondegreen.doc" size="1993" project="neptune"/>
      <file name="gadabout.pas" size="685" project="jupiter"/>
   </chapter>
</book>

:D/-<


  • Pkunk
  • Registratie: December 2003
  • Laatst online: 11-09 17:52
Ik ben ook wel benieuwd naar je xml, want als je er 3 aparte lijstje van moet maken zou je denken dat er in die lijstjes ook hun eigen plekje in de xml hebben.

Hallo met Tim


  • matthijsln
  • Registratie: Augustus 2002
  • Laatst online: 22:00
Nog een andere weg naar Rome...

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
<xsl:template match="items">
  <xsl:for-each select="item[position() mod 3 = 0]">
    <xsl:call-template name="print-group">
      <xsl:with-param name="items" select="preceding-sibling::node()[position() &lt; 3] | ."/>
    </xsl:call-template>
  </xsl:for-each>

  <xsl:variable name="remainder" select="count(item) mod 3"/>
  <xsl:if test="$remainder != 0">
    <xsl:variable name="count" select="count(item)"/>
    <xsl:call-template name="print-group">
      <xsl:with-param name="items" select="item[position() > $count - $remainder]"/>
    </xsl:call-template>
  </xsl:if>    
</xsl:template>

<xsl:template name="print-group">
  <xsl:param name="items"/>
  <ul>
    <xsl:for-each select="$items">
      <li><xsl:value-of select="."/></li>
    </xsl:for-each>
  </ul>
</xsl:template>

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Pkunk schreef op donderdag 03 september 2009 @ 22:23:
Ik ben ook wel benieuwd naar je xml, want als je er 3 aparte lijstje van moet maken zou je denken dat er in die lijstjes ook hun eigen plekje in de xml hebben.
Hoezo dat? Je hebt zo vaak dat je bijvoorbeeld 3 items per rij wil hebben, maar dat heeft voor de rest niks met de data-set te maken. Dat heeft puur met de presentatie te maken.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • Pkunk
  • Registratie: December 2003
  • Laatst online: 11-09 17:52
Woy schreef op donderdag 03 september 2009 @ 23:14:
[...]
Hoezo dat? Je hebt zo vaak dat je bijvoorbeeld 3 items per rij wil hebben, maar dat heeft voor de rest niks met de data-set te maken. Dat heeft puur met de presentatie te maken.
Een beetje vanuit de semantisch puristisch oogpunt gesproken zou je kunnen denken dat een lijstje uit xml ook netjes in html in 1 list hoort te komen. Het hoeft natuurlijk niet, maar als je je xml zou kunnen aanpassen zou dat een makkelijk oplossing zijn. Just a brainfart zegmaar :p Daarom benieuwd naar de xml.

Hallo met Tim


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Pkunk schreef op donderdag 03 september 2009 @ 23:19:
[...]

Een beetje vanuit de semantisch puristisch oogpunt gesproken zou je kunnen denken dat een lijstje uit xml ook netjes in html in 1 list hoort te komen. Het hoeft natuurlijk niet, maar als je je xml zou kunnen aanpassen zou dat een makkelijk oplossing zijn. Just a brainfart zegmaar :p Daarom benieuwd naar de xml.
Vanuit semantisch puristisch oogpunt heb je natuurlijk gelijk, maar zebra-achtige dingen in CSS zijn niet heel makkelijk (wegens gebrekkige CSS3-ondersteuning). Ik wil je dat nog wel eens zien doen zonder Javascript. :)

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • raptorix
  • Registratie: Februari 2000
  • Laatst online: 17-02-2022
Was ik weer ;)

Voor duidelijk, het resultaat wordt iets als dit:

Afbeeldingslocatie: http://i27.tinypic.com/1zxw0wp.jpg

Kortom, het zijn niet altijd precies eenheden van 3, het kunnen er ook 7 of 9 zijn.

Acties:
  • 0 Henk 'm!

  • raptorix
  • Registratie: Februari 2000
  • Laatst online: 17-02-2022
Pkunk schreef op donderdag 03 september 2009 @ 22:23:
Ik ben ook wel benieuwd naar je xml, want als je er 3 aparte lijstje van moet maken zou je denken dat er in die lijstjes ook hun eigen plekje in de xml hebben.
Het is niet echt als in "group by" zoals in sql, maar dat er gewoon om de 3 entries een nieuw UL gedefinieerd wordt....

Ik weet dat dit in XSLT 2 eenvoudig is, echter dat is geen optie.

Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
raptorix schreef op vrijdag 04 september 2009 @ 10:54:
Voor duidelijk, het resultaat wordt iets als dit:

[afbeelding]

Kortom, het zijn niet altijd precies eenheden van 3, het kunnen er ook 7 of 9 zijn.
Dat lijken mij gewoon 2 kolommen. Kun je dat niet beter gewoon met CSS oplossen?

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • raptorix
  • Registratie: Februari 2000
  • Laatst online: 17-02-2022
pedorus schreef op vrijdag 04 september 2009 @ 12:42:
[...]

Dat lijken mij gewoon 2 kolommen. Kun je dat niet beter gewoon met CSS oplossen?
Ja waarschijnlijk wel, maar wij werken hier met aparte frontend developers, en tijd was beetje kort om nu dingen te gaan lopen aanpassen. Overigens ga ik het nu oplossen vanuit usercontrol oplossen, maar als iemand elegante oplossing heeft, dan is het altijd leerzaam :)

Acties:
  • 0 Henk 'm!

  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 18-09 10:39

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
raptorix schreef op vrijdag 04 september 2009 @ 12:58:
[...]

Ja waarschijnlijk wel, maar wij werken hier met aparte frontend developers, en tijd was beetje kort om nu dingen te gaan lopen aanpassen. Overigens ga ik het nu oplossen vanuit usercontrol oplossen, maar als iemand elegante oplossing heeft, dan is het altijd leerzaam :)
Bij een horizontale opbouw: doe 2 keer dezelfde selectie, eentje met
code:
1
[position() mod 2=1]
erachter, en eentje met
code:
1
[position() mod 2=0]

Bij een vertikale opbouw: zoals matthijsln de remainder afhandelt.

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • raptorix
  • Registratie: Februari 2000
  • Laatst online: 17-02-2022
Daar zaten mooie voorbeelden bij, ik denk dat deze meest practisch is door hem iets aan te passen en dan recursief aan te roepe:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<xsl:template match="title">
  <xsl:variable name="card-no" select="position()" />
  <card id="{$card-no}">
    <select>
      <xsl:for-each select=". | following-sibling::title[position() &lt;
$group-size]">
        <choice><xsl:value-of select="." /></choice>
      </xsl:for-each>
      <xsl:if test="following-sibling::title[position() = $group-size]">
        <choice onpick="#{$card-no + 1}">More</choice>
      </xsl:if>
    </select>
  </card>
</xsl:template>
Pagina: 1