Subject: Re: [xsl] most efficient flat file listing to hierarchical From: James Fuller <jim.fuller@xxxxxxxxxxxxxx> Date: Thu, 11 Jan 2007 11:38:46 +0100 |
On 1/11/07, James Fuller <jim.fuller@xxxxxxxxxxxxxx> wrote:
Hello All,
Can anyone propose a pure xslt (1 or 2) solution to transforming the following flat xml structure of directory paths into a hierarchical (nested) xml.
<?xml version='1.0'?> <listing> <item>cn/test.xml</item> <item>en</item> <item>en/test.html</item> <item>en/test1.html</item> <item>en/resource</item> <item>en/resource/style</item> <item>en/resource/style/test.css</item> <item>favicon.ico</item> <item>cn</item> </listing>
to
<dir> <file name="favicon.ico"/> <dir name="cn"> <file name="test.xml"/> </dir> <dir name="en"> <file name="test.html"/> <file name="test1.html"/> <dir name="resource"> <dir name="style"> <file name="test.css"/> </dir> </dir> </dir> </dir>
...trickier than it first looks :)
This should do the job:
<xsl:stylesheet version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="xs">
<xsl:template match="listing"> <dir> <xsl:call-template name="process"> <xsl:with-param name="depth" select="1" as="xs:integer"/> <xsl:with-param name="seq" select="item"/> </xsl:call-template> </dir> </xsl:template>
<xsl:template name="process">
<xsl:param name="depth" as="xs:integer"/>
<xsl:param name="seq"/>
<xsl:for-each-group select="$seq" group-by="tokenize(., '/')[$depth]">
<xsl:variable name="part" select="tokenize(., '/')[$depth]"/>
<xsl:choose>
<xsl:when test="contains($part, '.')">
<file name="{$part}"/>
</xsl:when>
<xsl:otherwise>
<dir name="{$part}">
<xsl:call-template name="process">
<xsl:with-param name="depth" select="$depth + 1"/>
<xsl:with-param name="seq" select="$seq[tokenize(., '/')[$depth]
= $part]"/>
</xsl:call-template>
</dir>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
The output is:
<dir> <dir name="cn"> <file name="test.xml"/> </dir> <dir name="en"> <file name="test.html"/> <file name="test1.html"/> <dir name="resource"> <dir name="style"> <file name="test.css"/> </dir> </dir> </dir> <file name="favicon.ico"/> </dir>
<dir name="root"> <xsl:call-template name="pdir"> <xsl:with-param name="n" select="1"/> <xsl:with-param name="in" select="//item"/> </xsl:call-template> </dir> </xsl:template> <xsl:template name="pdir"> <xsl:param name="n"/> <xsl:param name="in"/> <xsl:for-each-group select="$in" group-by="tokenize(.,'/')[$n]"> <dir src="{.}"> <xsl:call-template name="pdir"> <xsl:with-param name="n" select="$n+1"/> <xsl:with-param name="in" select="current-group()"/> </xsl:call-template> </dir> </xsl:for-each-group> </xsl:template> </xsl:stylesheet>
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] most efficient flat file , George Cristian Bina | Thread | Re: [xsl] most efficient flat file , Andrew Welch |
Re: [xsl] most efficient flat file , George Cristian Bina | Date | Re: [xsl] text indent problem, Oliver Müller |
Month |