Toon posts:

[XSL] Geneste menu's transformeren

Pagina: 1
Acties:

Verwijderd

Topicstarter
Mijn doel is om geneste xml-menu's te transformeren naar geneste html-menu's. Daarnaast wil ik de menu-items (waaronder menu-items liggen) een css-class 'active' meegeven i.v.m. het bereiken van een uitklapeffekt. De xml-menu's zien er als volgt uit:

XML:
1
2
3
4
5
6
7
8
9
10
11
12
<menuItem>
    <hyperLink>http://www.link.com</hyperLink>
    <name>Menu-item</name>
</menuItem>
<menuItem>
    <hyperLink>http://www.link.com</hyperLink>
    <name>Menu-item</name>
    <menuItem>
        <hyperLink>http://www.link.com</hyperLink>
        <name>Submenu-item</name>
    </menuItem>
</menuItem>

Bovenstaande xml tracht ik te transformeren naar:

HTML:
1
2
3
4
5
6
7
8
9
<ul>
    <li><a href="http://www.link.com">Menu-item</a></li>
    <li><a href="http://www.link.com" class="active">Menu-item</a></li>
    <li>
        <ul>
            <li><a href="http://www.link.com">Submenu-item</a></li>
        </ul>
    </li>
</ul>

Om mijn doel te bereiken heb ik twee manieren bedacht:
1. Gebruik maken van recursie. Echter lijkt het mij zeer ingewikkeld om op een dergelijke manier alle nodes door te lopen en te transformeren.
2. Iets te doen met funkties als 'descendant::*'. Echter krijg ik het dan niet voor elkaar om te bepalen of er ingesprongen moet worden voor een dieperliggend menu en of een menu-item de klasse 'active' mee moet krijgen omdat een dieperliggend menu-item aktief is. (Of een menu-item aktief is bepaal ik door de hyperlink van het menu-item te testen tegenover de url van de huidige pagina.

Ik ben benieuwd hoe jullie een dergelijke case opgelost hebben.

[ Voor 71% gewijzigd door Verwijderd op 06-04-2006 11:33 ]


  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 20-02 03:31

Gerco

Professional Newbie

Ik heb hier geen handige XSL processor bij de hand dus ik kan het niet testen, maar een recursieve oplossing als deze moet toch wel werken?

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
<xsl:template match="/">
    <ul>
        <xsl:apply-templates/>
    </ul>
</xsl:template>

<xsl:template match="menuItem">
    <xsl:element name="a">
        <xsl:attribute name="href">
            <xsl:value-of select="hyperLink"/>
        </xsl:attribute>
        <xsl:if test="hier je active test">
            <xsl:attribute name="class">
                <xsl:text>active</xsl:text>
            </xsl:attribute>
        </xsl:if>
        <xsl:value=of select="name"/>
    <xsl:element>

    <xsl:if test="menuItem">
        <ul>
            <xsl:apply-templates select="menuItem"/>
        </ul>
    </xsl:if>
</xsl:template>


Voor het bekijken of een menuItem active moet zijn, moet je kijken of de URL van dat item gelijk is aan de huidige URL en zo niet, of de URLs van 1 van de contained items de huidige URL is (recursief natuurlijk). Zoiets zou kunnen werken:
XML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<xsl:template name="getactive">
    <xsl:choose>
        <xsl:when test="link=$huidigeurl">
            <xsl:attribute name="class">
                <xsl:text>active</xsl:text>
            </xsl:attribute>
        </xsl:when>
        <xsl:otherwise>
            <xsl:for-each select="menuItem">
                <xsl:call-template name="getactive"/>
            </xsl:for-each>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>


Dat kun je dan aanroepen met <xsl:call-template> in plaats van de <xsl:if test="doeactivetest"> hierboven.

[ Voor 95% gewijzigd door Gerco op 06-04-2006 11:31 ]

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


  • Michali
  • Registratie: Juli 2002
  • Laatst online: 09-12-2025
Een genest ul element hoort in een li te staan overigens.

[ Voor 7% gewijzigd door Michali op 06-04-2006 11:32 ]

Noushka's Magnificent Dream | Unity


  • CH4OS
  • Registratie: April 2002
  • Niet online

CH4OS

It's a kind of magic

Verwijderd schreef op donderdag 06 april 2006 @ 11:07:
XML:
1
2
3
4
5
6
7
8
9
10
11
12
<menuItem>
    <hyperLink>http://www.link.com</hyperLink>
    <name>Menu-item</name>
</menuItem>
<menuItem>
    <hyperLink>http://www.link.com</hyperLink>
    <name>Menu-item</name>
    <menuItem>
        <hyperLink>http://www.link.com</hyperLink>
        <name>Submenu-item</name>
    </menuItem>
</menuItem>

Bovenstaande xml tracht ik te transformeren naar:

HTML:
1
2
3
4
5
6
7
<ul>
    <li><a href="http://www.link.com">Menu-item</a></li>
    <li><a href="http://www.link.com" class="active">Menu-item</a></li>
    <ul>
        <li><a href="http://www.link.com">Submenu-item</a></li>
    </ul>
</ul>
Ik weet niet, maar als ik die XML zo bekijk, krijg je geloof ik niet dat je het gewenste effect krijgt. Je wil namelijk een menuItem in een menuItem gooien, maar moet dat niet bijvoorbeeld menuSubItem zijn? Zou (semantisch gezien) ook wel correcter zijn namelijk... :)

[ Voor 18% gewijzigd door CH4OS op 06-04-2006 11:33 ]


Verwijderd

Topicstarter
GJ-tje schreef op donderdag 06 april 2006 @ 11:33:
[...]
Ik weet niet, maar als ik die XML zo bekijk, krijg je geloof ik niet dat je het gewenste effect krijgt. Je wil namelijk een menuItem in een menuItem gooien, maar moet dat niet bijvoorbeeld menuSubItem zijn? Zou (semantisch gezien) ook wel correcter zijn namelijk... :)
Je bedoelt puur kwa naam? Op zich kun je al afleiden dat een menu-item een submenu-item is als hij binnen een menu-item staat.

  • CH4OS
  • Registratie: April 2002
  • Niet online

CH4OS

It's a kind of magic

Verwijderd schreef op donderdag 06 april 2006 @ 11:35:
Je bedoelt puur kwa naam? Op zich kun je al afleiden dat een menu-item een submenu-item is als hij binnen een menu-item staat.
Ah ja, zo ver was ik al wel, daar niet van, maar het kan zijn, dat de XSL parser misschien in de problemen komt ermee? Plus dat het (in mijn ogen dan) semantisch gezien geen juiste benaming is voor een sub menu item om die dan menuItem te noemen... menuSubItem oid zou dan dus beter zijn... :)

Verwijderd

Topicstarter
GJ-tje schreef op donderdag 06 april 2006 @ 11:37:
[...]
Ah ja, zo ver was ik al wel, daar niet van, maar het kan zijn, dat de XSL parser misschien in de problemen komt ermee? Plus dat het (in mijn ogen dan) semantisch gezien geen juiste benaming is voor een sub menu item om die dan menuItem te noemen... menuSubItem oid zou dan dus beter zijn... :)
Tsja, maar dan moet je ook verder gaan in 'subSubMenuItem' etc. Ik houd het dan liever wat abstrakter. :)

  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 20-02 03:31

Gerco

Professional Newbie

Ik heb er een beetje mee geklooid met een XSL processor en dit lijkt te doen wat je wilt. Recursief, dat wel, maar helemaal niet ingewikkeld:

Die controle op de "active" class is alleen wel een beetje traag denk ik zo, aangezien hij voor elk element alle subelementen ook gaat checken. Bij een groot aantal menuitems, kan dat behoorlijk traag gaan worden. Ik zie er alleen niet zo snel een alternatief voor. Van binnen naar buiten werken kan helaas niet vziw.

Bronbestand:
XML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0"?>
<menu>
<menuItem>
    <hyperLink>http://www.link.com/1</hyperLink>
    <name>Menu-item</name>
</menuItem>
<menuItem>
    <hyperLink>http://www.link.com/2</hyperLink>
    <name>Menu-item</name>
    <menuItem>
        <hyperLink>http://www.link.com/3</hyperLink>
        <name>Submenu-item</name>
    </menuItem>
</menuItem>
</menu>


Stylesheet:
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"?>

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

<xsl:variable name="huidigeurl" select="'http://www.link.com/3'"/>

<xsl:template match="/">
    <html>
    <body>
    <ul>
        <xsl:apply-templates/>
    </ul>
    </body>
    </html>
</xsl:template>

<xsl:template name="getactive">
    <xsl:choose>
        <xsl:when test="hyperLink=$huidigeurl">
            <xsl:attribute name="class">
                <xsl:text>active</xsl:text>
            </xsl:attribute>
        </xsl:when>
        <xsl:otherwise>
            <xsl:for-each select="menuItem">
                <xsl:call-template name="getactive"/>
            </xsl:for-each>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

<xsl:template match="menuItem">
    <li>
    <xsl:element name="a">
        <xsl:attribute name="href">
            <xsl:value-of select="hyperLink"/>
        </xsl:attribute>
        <xsl:call-template name="getactive"/>
        <xsl:value-of select="name"/>
    </xsl:element>

    <xsl:if test="menuItem">
        <ul>
            <xsl:apply-templates select="menuItem"/>
        </ul>
    </xsl:if>
    </li>
</xsl:template>
</xsl:stylesheet>


Levert bij mij op:
XML:
1
2
3
4
5
6
7
8
9
10
11
12
<html>
  <body>
    <ul>
      <li><a href="http://www.link.com/1">Menu-item</a></li>
      <li><a href="http://www.link.com/2" class="active">Menu-item</a>
        <ul>
          <li><a href="http://www.link.com/3" class="active">Submenu-item</a></li>
        </ul>
      </li>
    </ul>
  </body>
</html>

[ Voor 59% gewijzigd door Gerco op 06-04-2006 11:50 ]

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


  • CH4OS
  • Registratie: April 2002
  • Niet online

CH4OS

It's a kind of magic

Verwijderd schreef op donderdag 06 april 2006 @ 11:40:
Tsja, maar dan moet je ook verder gaan in 'subSubMenuItem' etc. Ik houd het dan liever wat abstrakter. :)
Zo zou het (semantisch gezien) wel correcter zijn ja, als je een subSubItem in een subItem hebt... :)

Abstracter houden kan ook, maar dan is de vraag of de XSL parser het slikt ja of nee... ;) En ik denk, dat als je het semantisch gezien correcter aanpakt, dat je jezelf er dan ook op kan verzekeren dat het (goed) werkt, ook al is het wel wat meer werk voor het maken ervan... :)

  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 20-02 03:31

Gerco

Professional Newbie

GJ-tje schreef op donderdag 06 april 2006 @ 11:48:
Zo zou het (semantisch gezien) wel correcter zijn ja, als je een subSubItem in een subItem hebt... :)
Het lijkt mij semantisch correcter om het zo te doen:
XML:
1
2
3
4
5
6
7
8
9
10
<menu>
  <menuItem>
    blahblah
    <menu>
      <menuItem>
        blahblahblah
      </menuItem>
    </menu>
  </menuItem>
</menu>


Zo kun je oneindig diep en alles wat "menu" heet is ook een menu en alles wat "menuItem" heet is een menu item. Het nivo waarop dat item zich bevind verandert toch niet opeens wat het is? Overigens kan de XSL processor er dus prima mee overweg. Als je die <menu> tags ertussen zou doen, had wel die <xsl:if> niet gehoeven en dat had wel zo mooi geweest natuurlijk.

[ Voor 20% gewijzigd door Gerco op 06-04-2006 11:56 ]

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


  • CH4OS
  • Registratie: April 2002
  • Niet online

CH4OS

It's a kind of magic

Gerco schreef op donderdag 06 april 2006 @ 11:54:
Het lijkt mij semantisch correcter om het zo te doen:
XML:
1
2
3
4
5
6
7
8
9
10
<menu>
  <menuItem>
    blahblah
    <menu>
      <menuItem>
        blahblahblah
      </menuItem>
    </menu>
  </menuItem>
</menu>


Zo kun je oneindig diep en alles wat "menu" heet is ook een menu en alles wat "menuItem" heet is een menu item. Het nivo waarop dat item zich bevind verandert toch niet opeens wat het is?
Lijkt mij dat als je een item hebt in je menu, die ook weer nieuwe items heeft, dat je die subItems noemt, omdat ze niet gelijk zijn aan menuItem, maar in de hierachie net een niveau lager zijn... :) Dus dit zou mijns inziens juist niet semantisch moeten zijn, natuurlijk kan je ook het menu van een menuItem als nieuw menu'tje zien, maar lijkt mij meer een geheel en dus een sub(Sub)Item... :)

[ Voor 18% gewijzigd door CH4OS op 06-04-2006 11:57 ]


  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 20-02 03:31

Gerco

Professional Newbie

GJ-tje schreef op donderdag 06 april 2006 @ 11:56:
Lijkt mij dat als je een item hebt in je menu, die ook weer nieuwe items heeft, dat je die subItems noemt, omdat ze niet gelijk zijn aan menuItem, maar in de hierachie net een niveau lager zijn... :)
Wat is het verschil tussen een menuItem en een menuSubItem dan? Behalve het nivo? De hierarchie is al in de XML vastgelegd. Dat een menuItem binnen een ander menuItem staat, betekent al dat het er een onderdeel van is.

Als er nu nog een ander verschil zou zijn (bijvoorbeeld dat subitems geen hyperLink hebben ofzo), zou je kunnen praten over een ander element. In de situatie zoals die nu is, is het gewoon precies hetzelfde en moet het dus ook hetzelfde heten.

Zie je jezelf dit al transformeren?
XML:
1
2
3
4
5
6
7
8
<menu>
  <menuItem>
    <menuSubItem>
      <menuSubSubItem>
      </menuSubSubItem>
    </menuSubItem>
  </menuItem>
</menu>


Zeg nu zelf, dat gaat toch helemaal nergens over? Bovendien leg je jezelf ook een limiet op wbt het aantal nivos. Je zult voor elk nivo een template in je XSL moeten maken die dat transformeert en dus moet je genoegen nemen met een beperking aan het aantal nivos.

[ Voor 4% gewijzigd door Gerco op 06-04-2006 12:03 ]

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


Verwijderd

Topicstarter
Gerco schreef op donderdag 06 april 2006 @ 11:54:
[...]

Het lijkt mij semantisch correcter om het zo te doen:
XML:
1
2
3
4
5
6
7
8
9
10
<menu>
  <menuItem>
    blahblah
    <menu>
      <menuItem>
         blahblahblah
      </menuItem>
     </menu>
  </menuItem>
</menu>


Zo kun je oneindig diep en alles wat "menu" heet is ook een menu en alles wat "menuItem" heet is een menu item. Het nivo waarop dat item zich bevind verandert toch niet opeens wat het is? Overigens kan de XSL processor er dus prima mee overweg. Als je die <menu> tags ertussen zou doen, had wel die <xsl:if> niet gehoeven en dat had wel zo mooi geweest natuurlijk.
Je hebt helemaal gelijk, echter ben ik binnen het gebruikte cms gebonden aan de gegeven strukturen. Ik ga even jouw oplossing implementeren. Dat active-gebeuren ziet er verder goed uit, alleen is het lastige dat ik werk met meerdere dieperliggende menu-items. Dus:

HTML:
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
<ul>
    <li><a href="http://www.link.com">menu-item</a></li>
    <li><a href="http://www.link.com" class="active">menu-item</a></li>
    <li>
        <ul>
            <li><a href="http://www.link.com">menu-item</a></li>
            <li><a href="http://www.link.com">menu-item</a></li>
            <li>
                <ul>
                    <li><a href="http://www.link.com">menu-item</a></li>
                </ul>
            </li>
            <li><a href="http://www.link.com">menu-item</a></li>
        </ul>
    </li>
    <li><a href="http://www.link.com">menu-item</a></li>
    <li>
        <ul>
            <li><a href="http://www.link.com">menu-item</a></li>
            <li>
                <ul>
                    <li><a href="http://www.link.com">menu-item</a></li>
                </ul>
            </li>
        </ul>
    </li>
</ul>


Maar waarschijnlijk is dat m.b.v. recursiviteit ook wel doen. Ik ga eens kijken.

[ Voor 21% gewijzigd door Verwijderd op 06-04-2006 12:21 ]


  • CH4OS
  • Registratie: April 2002
  • Niet online

CH4OS

It's a kind of magic

Gerco schreef op donderdag 06 april 2006 @ 12:03:
Zie je jezelf dit al transformeren?
XML:
1
2
3
4
5
6
7
8
<menu>
  <menuItem>
    <menuSubItem>
      <menuSubSubItem>
      </menuSubSubItem>
    </menuSubItem>
  </menuItem>
</menu>


Zeg nu zelf, dat gaat toch helemaal nergens over? Bovendien leg je jezelf ook een limiet op wbt het aantal nivos. Je zult voor elk nivo een template in je XSL moeten maken die dat transformeert en dus moet je genoegen nemen met een beperking aan het aantal nivos.
Waarom zou je oneindig aantal niveau's willen hebben in je menu? Maakt je menu alleen maar onoverzichtelijk voor de gebruikers, dus schiet je er niets tot nauwelijks iets mee op... ;) Ik zou, als ik een menu maak, niet verder gaan dan zoals jouw XML file nu gaat... :) Waarom zou je nog verder willen in je menu? Maakt het (zoals eerder gezegt) alleen maar onduidelijker voor de gebruikers... :) En dat (en dat is logisch) is niet gewenst lijkt me... :)

  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 20-02 03:31

Gerco

Professional Newbie

Verwijderd schreef op donderdag 06 april 2006 @ 12:18:
Je hebt helemaal gelijk, echter ben ik binnen het gebruikte cms gebonden aan de gegeven strukturen. Ik ga even jouw oplossing implementeren. Dat active-gebeuren ziet er verder goed uit, alleen is het lastige dat ik werk met meerdere dieperliggende menu-items. Dus:

...

Maar waarschijnlijk is dat m.b.v. recursiviteit ook wel doen. Ik ga eens kijken.
Dat is al gedaan hoor :) Als je die code van mij hierboven toepast worden het item waarvan de URL de huidige is op class="active" gezet, maar ook al zijn parent items. Als je dus op het 100e nivo van je menu een actief item hebt, zijn alle 99 nivos daarboven ook actief (alleen de parents van de active items he). Zoiets dus:
  • Inactief
  • Actief
  • [list]
  • Actief
    • Inactief
    • Actief <- Deze is dus nu geselecteerd
  • Inactief
  • [/]
  • Inactief
GJ-tje schreef op donderdag 06 april 2006 @ 12:30:
Waarom zou je oneindig aantal niveau's willen hebben in je menu? Maakt je menu alleen maar onoverzichtelijk voor de gebruikers, dus schiet je er niets tot nauwelijks iets mee op... ;) Ik zou, als ik een menu maak, niet verder gaan dan zoals jouw XML file nu gaat... :) Waarom zou je nog verder willen in je menu? Maakt het (zoals eerder gezegt) alleen maar onduidelijker voor de gebruikers... :) En dat (en dat is logisch) is niet gewenst lijkt me... :)
Waarom zou je niet? Het is op deze manier overzichtelijker in je XML, makkelijker te transformeren en naar mijn idee correcter.

Waarom zou je het jezelf moeilijk maken? Nu kun je met 1 recursieve template je hele menu transformeren. Als je SubSubSubMenuItems gaat gebruiken, moet je voor elk nivo een template maken. Je code wordt dus langer, minder overzichtelijk en minder flexibel. Kan aan mij liggen, maar ik zou voor de recursie gaan hoor.

[ Voor 40% gewijzigd door Gerco op 06-04-2006 13:11 ]

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


Verwijderd

Topicstarter
GJ-tje schreef op donderdag 06 april 2006 @ 12:30:
[...]
Waarom zou je oneindig aantal niveau's willen hebben in je menu? Maakt je menu alleen maar onoverzichtelijk voor de gebruikers, dus schiet je er niets tot nauwelijks iets mee op... ;) Ik zou, als ik een menu maak, niet verder gaan dan zoals jouw XML file nu gaat... :) Waarom zou je nog verder willen in je menu? Maakt het (zoals eerder gezegt) alleen maar onduidelijker voor de gebruikers... :) En dat (en dat is logisch) is niet gewenst lijkt me... :)
Je vergeet dat geneste menu's niet perse genest weergegeven hoeven te worden. W.d.b. hoeven geneste menu's niet per definitie onduidelijk te zijn voor de gebruiker.

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 09-12-2025
Gerco schreef op donderdag 06 april 2006 @ 11:47:
XML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<xsl:template name="getactive">
    <xsl:choose>
        <xsl:when test="hyperLink=$huidigeurl">
            <xsl:attribute name="class">
                <xsl:text>active</xsl:text>
            </xsl:attribute>
        </xsl:when>
        <xsl:otherwise>
            <xsl:for-each select="menuItem">
                <xsl:call-template name="getactive"/>
            </xsl:for-each>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>
Is dit niet beter zo te doen trouwens:
XML:
1
2
3
4
5
6
7
<xsl:template name="getactive">
    <xsl:if test="descendant-or-self::hyperLink=$huidigeurl">
        <xsl:attribute name="class">
            <xsl:text>active</xsl:text>
        </xsl:attribute>
    </xsl:if>
</xsl:template>

Noushka's Magnificent Dream | Unity


  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 20-02 03:31

Gerco

Professional Newbie

Michali schreef op donderdag 06 april 2006 @ 15:19:
Is dit niet beter zo te doen trouwens:
Waarschijnlijk wel ja, maar ik kende die functie nog niet :)

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


  • Michali
  • Registratie: Juli 2002
  • Laatst online: 09-12-2025
Hier kun je alle axes vinden. Goed om ze te kennen, want het kan je veel tijd schelen en zijn echt vereist bij sommige problemen.

Noushka's Magnificent Dream | Unity


Verwijderd

Topicstarter
Ik heb de funktie geimplementeerd. Hartelijk bedankt Gerco en Michali!

[ Voor 5% gewijzigd door Verwijderd op 06-04-2006 16:51 ]

Pagina: 1