Re: [xsl] Tree from directory listing

Subject: Re: [xsl] Tree from directory listing
From: Mukul Gandhi <mukul_gandhi@xxxxxxxxx>
Date: Tue, 14 Dec 2004 10:52:27 -0800 (PST)
Below is a XSLT 1.0 solution. I have used the node-set
extension function..

<?xml version="1.0"?> 
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
version="1.0" xmlns:exslt="http://exslt.org/common";
exclude-result-prefixes="exslt">
 
<xsl:output method="xml" indent="yes" /> 

<xsl:key name="x" match="file" use="@parentfolder" />
<xsl:key name="y" match="file" use="concat(@folder,
'', @parentfolder)" />

<xsl:template match="/">
 <xsl:variable name="RTF">
   <temp>
     <xsl:for-each select="root/file">
       <xsl:variable name="folder-name">
         <xsl:call-template name="get-folder-name">
           <xsl:with-param name="path" select="@path"
/>
         </xsl:call-template>
       </xsl:variable>
       <xsl:variable name="parent-folder-name">
         <xsl:call-template
name="get-parent-folder-name">
           <xsl:with-param name="path" select="@path"
/>   
         </xsl:call-template>
       </xsl:variable>
       <file name="{@name}" folder="{$folder-name}"
parentfolder="{$parent-folder-name}" />
     </xsl:for-each>
   </temp>
 </xsl:variable>
 <root>
   <xsl:apply-templates
select="exslt:node-set($RTF)/temp" />  
 </root>
</xsl:template>
 
<xsl:template name="get-folder-name">
  <xsl:param name="path" />
  <xsl:choose>
    <xsl:when test="(string-length($path) -
string-length(translate($path, '/', ''))) = 2">
      <xsl:value-of
select="substring-before(substring-after($path, '/'),
'/')" />
    </xsl:when>
    <xsl:otherwise>
      <xsl:call-template name="get-folder-name">
        <xsl:with-param name="path"
select="substring-after(@path, '/')" />
      </xsl:call-template>
    </xsl:otherwise>
  </xsl:choose> 
</xsl:template>
 
<xsl:template name="get-parent-folder-name">
  <xsl:param name="path" />
  <xsl:choose>
     <xsl:when test="(string-length($path) -
string-length(translate($path, '/', ''))) = 2">
       <xsl:value-of select="substring-before($path,
'/')" />
     </xsl:when>
     <xsl:otherwise>
       <xsl:call-template
name="get-parent-folder-name">
         <xsl:with-param name="path"
select="substring-after(@path, '/')" />
       </xsl:call-template>
     </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<xsl:template match="temp">
  <xsl:apply-templates select="file[generate-id(.) =
generate-id(key('x', @parentfolder)[1])]" /> 
</xsl:template>

<xsl:template match="file">
  <xsl:if test="@parentfolder != ''">
  <folder name="{@parentfolder}">    
    <xsl:for-each select="key('x',
@parentfolder)[generate-id(.) = generate-id(key('y',
concat(@folder, '', @parentfolder))[1])]">
      <folder name="{@folder}">
        <xsl:for-each select="key('y', concat(@folder,
'', @parentfolder))">
          <file name="{@name}" />
        </xsl:for-each>
      </folder>
    </xsl:for-each>
  </folder>
 </xsl:if>
</xsl:template>
    
</xsl:stylesheet>

When the above XSL is applied to XML -
<?xml version="1.0" encoding="UTF-8"?>
<root>
  <file name ="f1.xyz" path="/test/"/> 
  <file name ="f2.xyz" path="/test/folderInFolder/"/> 
  <file name ="f3.xyz" path="/test/folderInFolder/"/> 
  <file name ="f4.xyz" path="/test/folderInFolder2/"/>

  <file name ="f5.xyz"
path="/test2/folderInFolder3/"/> 
</root>

it produces o/p -
<?xml version="1.0" encoding="UTF-8"?>
<root>
  <folder name="test">
   <folder name="folderInFolder">
     <file name="f2.xyz"/>
     <file name="f3.xyz"/>
   </folder>
   <folder name="folderInFolder2">
     <file name="f4.xyz"/>
   </folder>
  </folder>
  <folder name="test2">
    <folder name="folderInFolder3">
      <file name="f5.xyz"/>
    </folder>
  </folder>
</root>

Regards,
Mukul

--- Thomas Zvchling <thomas.zoechling@xxxxxx> wrote:

> Hi list!
> 
> Does someone know a method to create a nested xml
> Tree structure from file
> listing with paths?
> 
> eg.
> ...
> <file name ="f1.xyz" path="/test/"/>
> <file name ="f2.xyz" path="/test/folderInFolder/"/>
> <file name ="f3.xyz" path="/test/folderInFolder/"/>
> <file name ="f4.xyz" path="/test/folderInFolder2/"/>
> <file name ="f5.xyz"
> path="/test2/folderInFolder3/"/>
> ...
> 
> to
> 
> <folder name="test">
>     <folder name="folderInFolder">
>         <file name="f2.xyz"/>
>         <file name="f3.xyz"/>
>     </folder
>     <folder name="folderInFolder2">
>         <file name="f4.xyz"/>
>     </folder
> <folder name ="test">
>     <folder name="folderInFolder3">
>         <file name="f5.xyz">
>     </folder>
> </folder>
> 
> Maybe anyone solved a similar problem?



		
__________________________________ 
Do you Yahoo!? 
Send holiday email and support a worthy cause. Do good. 
http://celebrity.mail.yahoo.com

Current Thread