Subject: [xsl] Flat list to nested list,grouping From: "Kjellaug Johansen" <kjellaug.johansen@xxxxx> Date: Thu, 31 Mar 2011 15:10:43 +0200 |
I've been trying for a long time, but I can't figure it out. The problem is making structured lists out of a flat xml. I've got it almost right. The list's first level is ok, but the second level only prints out the first point. The third level is not printed in my output at all. I guess there is something to do with the key name kListGroup1. PS: This is XSL 1.0 PS: There can be a various number of levels in the list from time to time. Anyone with a solution? Thanks! Kjellaug. The result I want: <myresult> <Title>Numericlist</Title> <List level="1"> <Pkt> <A>List level1, Point 1</A> </Pkt> <Pkt> <A>List level1, Point 2</A> <A>New paragraph in point 2</A> <A>Another paragraph in point 2</A> </Pkt> <Pkt> <A>List level1, Point 3</A> <List level="2"> <Pkt> <A>List level2, point 1</A> </Pkt> <Pkt> <A>List level2, point 2</A> <A>New paragraph under point 2 list 2</A> </Pkt> <Pkt> <A>List level2, point 3</A> <List level="3"> <Pkt> <A>List level3, point 1</A> <A>New paragraph under point 1 list 3</A> </Pkt> </Pkt> </Liste> </Pkt> <Pkt> <A>List level1, point 4</A> </Pkt> </Liste> </myresult> Here's my input xml: <myxml> <p val="X">Div elements</p> <p val="Tit">Numericlist</p> <p val="LNum1">List level1, Point 1</p> <p val="LNum1">List level1, Point 2</p> <p val="LPara1">New paragraph in point 2</p> <p val="LPara1">Another paragraph in point 2</p> <p val="LNum1">List level1, Point 3</p> <p val="LNum2">List level2, point 1</p> <p val="LNum2">List level2, point 2</p> <p val="LPara2">New paragraph under point 2 list 2</p> <p val="LNum2">List level2, point 3</p> <p val="LNum3">List level3, point 1</p> <p val="LPara3">New paragraph under point 1 list 3</p> <p val="LNum1">List level1, point 4</p> <p val="Y">Other elements</p> </myxml> This is my xsl: <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:fo="http://www.w3.org/1999/XSL/Format"> <xsl:output method="xml" indent="yes"/> <xsl:key name="kListGroup1" match="p[contains(@val,'LNum')]" use="generate-id(preceding-sibling::node()[self::p[contains(@val,'LNum') or contains(@val,'LPara')]][1])"/> <!--This is probably not correct--> <xsl:key name="kListGroup2" match="p[contains(@val,'LNum')]" use="generate-id(preceding-sibling::node()[not(self::p[contains(@val,'LN um') or contains(@val,'LPara')])][1])"/> <!--This works fine--> <xsl:template match="myxml"> <xsl:element name="myresult"> <xsl:apply-templates/> </xsl:element> </xsl:template> <xsl:template match="p[@val='X']"/> <xsl:template match="p[@val='Y']"/> <xsl:template match="p[@val='Tit']"> <xsl:element name="Title"> <xsl:value-of select="."/> </xsl:element> <xsl:if test="following::p[1]/@val='LNum1'"> <!--Discovers the numeric list--> <xsl:apply-templates select="following-sibling::node()[1]" mode="liste"/> </xsl:if> </xsl:template> <xsl:template match="p" mode="liste"> <xsl:variable name="listlevel" select="substring(@val,5)"/> <xsl:element name="List"> <xsl:attribute name="level"><xsl:value-of select="$listlevel"/></xsl:attribute> <xsl:apply-templates mode="listgroup" select="key('kListGroup2', generate-id(preceding-sibling::p[1]))[substring(@val,5) = $listlevel]"/> <!--This works fine, lists all at level 1--> </xsl:element> </xsl:template> <xsl:template match="p" mode="innerlist"> <xsl:variable name="listlevel" select="substring(@val,5)"/> <xsl:element name="List"> <xsl:attribute name="level"><xsl:value-of select="$listlevel"/></xsl:attribute> <xsl:apply-templates mode="listgroup" select="key('kListGroup1', generate-id(preceding-sibling::p[1]))[substring(@val,5) = $listlevel]"/> <!--This DOESN'T work, lists only the first element at the second level--> </xsl:element> </xsl:template> <xsl:template match="p" mode="para"> <xsl:element name="A"> <xsl:value-of select="."/> </xsl:element> </xsl:template> <xsl:template match="p" mode="listgroup"><!--the logic of the list-content goes here, works fine--> <xsl:element name="Pkt"> <xsl:element name="A"> <xsl:value-of select="."/> </xsl:element> <xsl:variable name="level"> <xsl:value-of select="substring(@val,5)"/> </xsl:variable> <xsl:variable name="vNextAvs" select="following-sibling::p[1][contains(@val,'LPara')][1]"/> <xsl:if test="$vNextAvs"> <!--if there are more paragraphs in the listpoint, do this....it works fine--> <xsl:apply-templates select="following-sibling::p[contains(@val,'LPara')][generate-id(precedi ng-sibling::p[contains(@val,'LNum')][1]) = generate-id(current())]" mode="para"/> </xsl:if> <xsl:variable name="vNext" select="following-sibling::p[1][contains(@val,'LNum')][number(substring( @val,5) > number($level))][1]"/> <xsl:if test="$vNext"> <xsl:apply-templates select="following-sibling::node()[1]" mode="innerlist"/> </xsl:if> </xsl:element> </xsl:template> </xsl:stylesheet>
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] xsl elements in template , Wolfgang Laun | Thread | Re: [xsl] Flat list to nested list,, Murray McDonald |
Re: [xsl] xsl elements in template , Wolfgang Laun | Date | Re: [xsl] Flat list to nested list,, Murray McDonald |
Month |