Subject: Re: [xsl] Grouping hierarchy path elements From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx> Date: Mon, 23 Aug 2004 14:04:45 +0100 |
Hi Daniel, > I've been working on an XSLT for days now, and cannot find the solution to > one problem. I have a source XML document containing one level of elements. > Each element contains a path element that holds information on what path > the element was extracted from. > > Now, through XSL transformation, I would like to recreate the tree > structure of the items. Here's a set of templates that works with your example. The main template is the transformDocument template. This takes a path (an initial part of a path) and a set of items (whose paths should all start with the $path). It works out the next step in the path for the first item and from that creates a new path. Then it sorts the items into three groups: - items whose path *is* the new path, which should just be output - items whose path *starts with* the new path, which need to be processed again by this template, with the new path - items whose path *doesn't* start with the new path, which need to be processed again by this template, with the current path The result of the first two of these groups gets put within a <path> element, and the result of the third of these groups gets inserted afterwards. <xsl:template name="transformDocument"> <xsl:param name="path"/> <xsl:param name="items" select="/.."/> <xsl:if test="$items"> <xsl:variable name="step"> <xsl:variable name="rest" select="substring-after($items[1]/path, concat($path, '\'))" /> <xsl:choose> <xsl:when test="contains($rest, '\')"> <xsl:value-of select="substring-before($rest, '\')" /> </xsl:when> <xsl:otherwise> <xsl:value-of select="$rest" /> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="newPath" select="concat($path, '\', $step)" /> <path name="{$step}"> <xsl:apply-templates select="$items[path = $newPath]"/> <xsl:call-template name="transformDocument"> <xsl:with-param name="path" select="$newPath" /> <xsl:with-param name="items" select="$items[starts-with(path, $newPath) and path != $newPath]"/> </xsl:call-template> </path> <xsl:call-template name="transformDocument"> <xsl:with-param name="path" select="$path"/> <xsl:with-param name="items" select="$items[not(starts-with(path, $newPath))]"/> </xsl:call-template> </xsl:if> </xsl:template> The next template matches the <items> element and starts off the processing. I've assumed that there's only one root here. <xsl:template match="items"> <transformedDocument> <xsl:variable name="root" select="substring-before(item[1]/path, '\')" /> <path name="{$root}"> <xsl:call-template name="transformDocument"> <xsl:with-param name="path" select="$root" /> <xsl:with-param name="items" select="item" /> </xsl:call-template> </path> </transformedDocument> </xsl:template> The final template just outputs whatever you want for each item; here, a copy of the <item> element without its child <path> element. <xsl:template match="item"> <item id="{@id}" /> </xsl:template> Cheers, Jeni --- Jeni Tennison http://www.jenitennison.com/
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
[xsl] Grouping hierarchy path eleme, Daniel Geske | Thread | [xsl] recursive sub-grouping, Robin Wyles |
[xsl] recursive sub-grouping, Robin Wyles | Date | Re: [xsl] stylesheet licensing?, Eliot Kimber |
Month |