Subject: RE: [xsl] Constructing multi-level lists - any better than this? From: "Geert Josten" <geert.josten@xxxxxxxxxxx> Date: Sat, 15 Sep 2007 19:07:14 +0200 |
Hi, I would have done something like this (pseudo-code): <template match="p"> <copy /> </template> <template match="l1|l2"> <if test="preceding-sibling::*[1][self::p]"> <ul> <apply-templates select="." mode="level1" /> </ul> </if> </template> <template match="*" mode="level1"> <!-- terminate continuation if not l1 or l2 --> </template> <template match="l1" mode="level1"> <copy /> <apply-templates select="following-sibling::*[1]" mode="level1" /> </template> <template match="l2" mode="level1"> <if test="preceding-sibling::*[1][self::p or self::l1]"> <ul> <apply-templates select="." mode="level2" /> </ul> </if> <apply-templates select="following-sibling::*[1]" mode="level1" /> </template> <template match="*" mode="level2"> <!-- terminate continuation if not l2 --> </template> <template match="l2" mode="level2"> <copy /> <apply-templates select="following-sibling::*[1]" mode="level2" /> </template> But it is limited by recursion depth. On the other hand, it doesn't require XSLT 2.0. Kind regards, Geert > Drs. G.P.H. Josten Consultant Daidalos BV Source of Innovation Hoekeindsehof 1-4 2665 JZ Bleiswijk Tel.: +31 (0) 10 850 1200 Fax: +31 (0) 10 850 1199 www.daidalos.nl KvK 27164984 De informatie - verzonden in of met dit emailbericht - is afkomstig van Daidalos BV en is uitsluitend bestemd voor de geadresseerde. Indien u dit bericht onbedoeld hebt ontvangen, verzoeken wij u het te verwijderen. Aan dit bericht kunnen geen rechten worden ontleend. > From: Michael M|ller-Hillebrand [mailto:mmh@xxxxxxxxxxxxx] > Sent: zaterdag 15 september 2007 18:44 > To: XSL-List > Subject: [xsl] Constructing multi-level lists - any better than this? > > Hello, > > I have a working stylesheet, but it uses modes when I think > it could be a bit slimmer and maybe more flexible. > > The task is to create list containers (<ul>) around list > elements in a flat element tree. I tried to follow Jeni > Tennison's advice for constructing hierarchies > <http://jenitennison.com/xslt/hierarchies- > out.xml> and also evaluated xsl:for-each-group, but the > latter seems not to work very well for a stylesheet in push > mode (no changes to the element order). > > To correctly group the <li1>s and <li2>s (even in the third > case) in this example I successfully used the XSL below. I > found no good enough example in the FAQs, so I dare to ask, > whether there is a more elegant solution. (I simplified the > case, in reality there are multiple elements that are either > level 1 or level 2 list elements, and I do not use > starts-with() to detect element names.) > > Any advice is greatly appreciated! > > - Michael M|ller-Hillebrand > > <?xml version="1.0" encoding="UTF-8"?> > <levels> > <p/> > <li1>1</li1> > <li1>2</li1> > <li1>3</li1> > <li1>4</li1> > <p/> > <li1>5</li1> > <li1>6</li1> > <li2>7.1</li2> > <li2>7.2</li2> > <p/> > <li2>8.1</li2> > <li2>8.2</li2> > <li1>9</li1> > <li1>10</li1> > <p/> > </levels> > > --------- > > <xsl:stylesheet version="2.0" > xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> > <xsl:strip-space elements="*"/> > <xsl:output method="xml" indent="yes" /> > > <!-- Root element --> > <xsl:template match="levels"> > <xsl:copy> > <xsl:apply-templates /> > </xsl:copy> > </xsl:template> > > <!-- Keys to identify list elements after first element --> > <xsl:key name="list12-other" > match="*[self::*[starts-with(name(), 'li')] > and preceding-sibling::*[1][starts-with(name(), 'li')]]" > use="generate-id( > preceding-sibling::*[ > starts-with(name(), 'li') > and not(preceding-sibling::*[1][starts-with(name(), 'li')]) > ][1])" /> > > <xsl:key name="list2-other" > match="li2[preceding-sibling::*[1][self::li2]]" > use="generate-id( > preceding-sibling::li2[ > not(preceding-sibling::*[1][self::li2]) > ][1])" /> > > <!-- List 1 Container--> > <xsl:template match="*[starts-with(name(), 'li') > and not(preceding-sibling::*[1][starts-with(name(), 'li')])]" > priority="1"> > <ul level="1"> > <xsl:apply-templates mode="list1" > select=". | key('list12-other', generate-id())" /> > </ul> > </xsl:template> > <!-- List 1 elements --> > <xsl:template match="li1" mode="list1"> > <li tag="{name()}" pos="{position()}"> > <xsl:apply-templates /> > </li> > </xsl:template> > > <!-- or List 2 Container--> > <xsl:template match="li2[not(preceding-sibling::*[1][self::li2])]" > mode="list1" priority="1"> > <ul level="2"> > <xsl:apply-templates mode="list2" > select=". | key('list2-other', generate-id())" /> > </ul> > </xsl:template> > <!-- List 2 elements --> > <xsl:template match="li2" mode="list2"> > <li tag="{name()}" pos="{position()}"> > <xsl:apply-templates /> > </li> > </xsl:template> > > <!-- skip list elements when matched outside list --> > <xsl:template match="li2" mode="list1"/> <xsl:template > match="*[starts-with(name(), 'li')]"/> > > <!-- all other nodes --> > <xsl:template match="node()"> > <xsl:copy> > <xsl:apply-templates /> > </xsl:copy> > </xsl:template> > > </xsl:stylesheet>
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
[xsl] Constructing multi-level list, Michael Müller-Hille | Thread | Re: [xsl] Constructing multi-level , Andrew Welch |
[xsl] Constructing multi-level list, Michael Müller-Hille | Date | [xsl] Hide and show rows, Jonathan Dias |
Month |