Subject: Re: [xsl] Constructing multi-level lists - any better than this? From: "Andrew Welch" <andrew.j.welch@xxxxxxxxx> Date: Mon, 17 Sep 2007 10:09:32 +0100 |
On 9/17/07, Michael M|ller-Hillebrand <mmh@xxxxxxxxxxxxx> wrote: > Andrew: I was longing for a solution with some XSLT2 but I have a > problem with group-starting-with="*[self::p]", because the p elements > are just placeholders for any other element that does not belong to a > list and may appear any number of times. So the source XML is a > mixture of some non-list elements followed by some list elements > followed by some non-list elements... The source may even begin with > some list elements. Perhaps my example was too much stripped down. > This would have illustrated it better: > > <?xml version="1.0" encoding="UTF-8"?> > <levels> > <li1>1</li1> > <li2>2.1</li2> > <li2>2.2</li2> > <li1>3</li1> > <li1>4</li1> > <p/> > <any/> > <li1>5</li1> > <li1>6</li1> > <li2>7.1</li2> > <li2>7.2</li2> > <any/> > <p/> > <li2>8.1</li2> > <li2>8.2</li2> > <li1>9</li1> > <li1>10</li1> > <any/> > <p/> > </levels> > Ah, in which case you fallen into the trap of describing your potential solution ("groups should start with a <p>") rather than the problem itself ("adjacent <li1> and <li2> should be grouped") :) So with that mind this looks like a good use for group-adjacent, which turns out to be a better solution than the previous one I posted anway: <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:template match="levels"> <xsl:copy> <xsl:for-each-group select="*" group-adjacent="self::li1 or self::li2"> <xsl:choose> <xsl:when test="self::li1 or self::li2"> <ul level="1"> <xsl:for-each-group select="current-group()" group-adjacent="name()"> <xsl:choose> <xsl:when test="self::li1"> <xsl:apply-templates select="current-group()"/> </xsl:when> <xsl:when test="self::li2"> <ul level="2"> <xsl:apply-templates select="current-group()"/> </ul> </xsl:when> </xsl:choose> </xsl:for-each-group> </ul> </xsl:when> <xsl:otherwise> <xsl:copy-of select="current-group()"/> </xsl:otherwise> </xsl:choose> </xsl:for-each-group> </xsl:copy> </xsl:template> <xsl:template match="li1|li2"> <li tag="{name()}" pos="{position()}"> <xsl:apply-templates/> </li> </xsl:template> </xsl:stylesheet> It's a shame you have to effectively repeat the group-adjacent test in the xsl:when to determine if the current-group() is a matching-group or a non-matching-group.... I guess if the test was really complex you could change the outer xsl:when to be: test="current-grouping-key() eq true" or just test="current-grouping-key()" to be the equivalent of test="is-matching-group()" But then that would only work when the grouping key was a boolean... Anyway, I hope this is useful - it's the first time I've ever needed to use group-adjacent :) cheers -- Andrew Welch http://andrewjwelch.com Kernow: http://kernowforsaxon.sf.net/
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Constructing multi-level , Michael Müller-Hille | Thread | [xsl] Trying to understand root-les, Abel Braaksma |
Re: [xsl] Constructing multi-level , Michael Müller-Hille | Date | RE: [xsl] Brain Teaser, Geert Josten |
Month |