[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message] 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>
|
PURCHASE STYLUS STUDIO ONLINE TODAY!Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced! Download The World's Best XML IDE!Accelerate XML development with our award-winning XML IDE - Download a free trial today! Subscribe in XML format
|