Subject: Re: [xsl] Flat list to nested list,grouping From: "Murray McDonald" <m.mcdonald@xxxxxxxxx> Date: Thu, 31 Mar 2011 18:43:05 -0400 |
Kjellaug, Here's a SS that uses a pseudo-recursive approach to stick in the <list> markup and a kludge to stick in the <Pkt> markup. This works with AltovaXML, I believe it should work with other XSLT 1.0 processors but you never know. Regards, Murray <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output version="1.0" method="xml" indent="no" encoding="UTF-8"/> <xsl:template match="/"> <xsl:element name="myresult"> <xsl:call-template name="handleElement"> <xsl:with-param name="thisElement" select="child::*[1]/child::*[1]"/> <xsl:with-param name="currentLevel" select="0"/> </xsl:call-template> </xsl:element> </xsl:template> <xsl:template name="handleElement"> <xsl:param name="thisElement"/> <xsl:param name="currentLevel"/> <xsl:variable name="thisVal" select="$thisElement/@val"></xsl:variable> <xsl:variable name="thisLevel" select="concat(substring-after($thisVal, 'LNum'), substring-after($thisVal, 'LPara'))"/> <xsl:choose> <!-- look for start of new list --> <xsl:when test="contains($thisVal, 'LNum') and string($currentLevel) < $thisLevel"> <xsl:element name="list"> <xsl:attribute name="level"><xsl:value-of select="$currentLevel + 1"/></xsl:attribute> <xsl:call-template name="handleElement"> <xsl:with-param name="thisElement" select="$thisElement"/> <xsl:with-param name="currentLevel" select="$currentLevel + 1"/> </xsl:call-template> <xsl:value-of select="'</Pkt>'" disable-output-escaping="yes"/> </xsl:element> <!-- spin forward to end of this list --> <xsl:choose> <xsl:when test="$currentLevel = 0"> <xsl:variable name="endofList" select="$thisElement/following::p[not(starts-with(@val, 'L'))][1]/preceding::*[1]"/> <!-- at lowest level we process the next node --> <xsl:call-template name="nextElement"> <xsl:with-param name="thisElement" select="$endofList"/> <xsl:with-param name="currentLevel" select="0"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:variable name="endofList" select="$thisElement/following::p[not(starts-with(@val, 'L')) or substring(@val, string-length(@val)) < string($currentLevel)][1]/preceding::*[1]"/> <!-- at non-zero level we need to look for "included" list nodes --> <xsl:if test="starts-with($endofList/@val, 'L') and substring($endofList/@val, string-length($endofList/@val)) = string($currentLevel)"> <xsl:value-of select="'</Pkt>'" disable-output-escaping="yes"/> <xsl:call-template name="handleElement"> <xsl:with-param name="thisElement" select="$endofList"/> <xsl:with-param name="currentLevel" select="$currentLevel"/> </xsl:call-template> </xsl:if> </xsl:otherwise> </xsl:choose> </xsl:when> <!-- new list item at same level --> <xsl:when test="contains($thisVal, 'LNum') and string($currentLevel) = $thisLevel"> <xsl:variable name="pktLevel" select="$thisElement/preceding::*[contains(@val, 'LNum') or not(starts-with(@val, 'L'))][1]/@val"/> <xsl:if test="$thisElement/@val = $pktLevel"> <xsl:value-of select="'</Pkt>'" disable-output-escaping="yes"/> </xsl:if> <xsl:value-of select="'<Pkt>'" disable-output-escaping="yes"/> <xsl:element name="A"> <xsl:value-of select="$thisElement"/> </xsl:element> <xsl:call-template name="nextElement"> <xsl:with-param name="thisElement" select="$thisElement"/> <xsl:with-param name="currentLevel" select="$currentLevel"/> </xsl:call-template> </xsl:when> <!-- list paragrpah --> <xsl:when test="contains($thisVal, 'LPara')"> <xsl:element name="A"> <xsl:value-of select="$thisElement"/> </xsl:element> <xsl:call-template name="nextElement"> <xsl:with-param name="thisElement" select="$thisElement"/> <xsl:with-param name="currentLevel" select="$currentLevel"/> </xsl:call-template> </xsl:when> <!-- horse of a different colour --> <xsl:otherwise> <xsl:choose> <xsl:when test="$currentLevel = 0"> <!-- node at level 0 not "inside" any list --> <xsl:copy-of select="$thisElement"/> <xsl:call-template name="nextElement"> <xsl:with-param name="thisElement" select="$thisElement"/> <xsl:with-param name="currentLevel" select="0"/> </xsl:call-template> </xsl:when> <xsl:otherwise><!-- stop recursing --></xsl:otherwise> </xsl:choose> </xsl:otherwise> </xsl:choose> </xsl:template> <!-- feed next element to element handler if it exists --> <xsl:template name="nextElement"> <xsl:param name="thisElement"/> <xsl:param name="currentLevel"/> <xsl:if test="$thisElement/following::*"> <xsl:call-template name="handleElement"> <xsl:with-param name="thisElement" select="$thisElement/following::*[1]"/> <xsl:with-param name="currentLevel" select="$currentLevel"/> </xsl:call-template> </xsl:if> </xsl:template> </xsl:stylesheet>
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
[xsl] Flat list to nested list,grou, Kjellaug Johansen | Thread | |
[xsl] Flat list to nested list,grou, Kjellaug Johansen | Date | |
Month |