[XSL-LIST Mailing List Archive Home]
[By Thread]
[By Date]
Hi,
I was actually considering whether the node-set could be eliminated or not. My first impression was: easily, but then I noticed you used the keys on the document fragment. Which is actually quite nice.
Can anyone tell me how that fits into the XSLT 1 recommendation?
By the way, I realize that it opens an alternative to the node-set function! Wrap your fragment in some obscure element name (or just use some namespace) and add a key that only matches that element. Should work, I guess..
Very true, here it comes:
<xsl:output method="xml" indent="yes" encoding="utf-8" />
<xsl:key name="folders" match="folder" use="@path" />
<!-- folder-count equals the number of slashes in the path, minus one for the file name -->
<xsl:param name="folder-count" select="string-length($path) - string-length(translate($path, '/', '')) - 1"/>
<!-- apply those folders that are the first ones with a specific path -->
<xsl:apply-templates select="folder[generate-id(.) = generate-id(key('folders', @path)[1])]" mode="merge"/>
</xsl:copy>
</xsl:template>
<xsl:copy-of select="key('folders', @path)/file" />
<xsl:apply-templates select="key('folders', @path)/folder[generate-id(.) = generate-id(key('folders', @path)[1])]" mode="merge"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Re: [xsl] Tree from directory listing
Subject: Re: [xsl] Tree from directory listing From: Geert Josten <Geert.Josten@xxxxxxxxxxx> Date: Thu, 16 Dec 2004 10:23:28 +0100 |
Hi,
Hi Geert, Thanks a lot for pointing the bug.. I was infact testing my stylesheet again, and was getting StackOverFlow error. And your mail pointed the bug.. Thanks for saving my time!
I was actually considering whether the node-set could be eliminated or not. My first impression was: easily, but then I noticed you used the keys on the document fragment. Which is actually quite nice.
Can anyone tell me how that fits into the XSLT 1 recommendation?
By the way, I realize that it opens an alternative to the node-set function! Wrap your fragment in some obscure element name (or just use some namespace) and add a key that only matches that element. Should work, I guess..
I suggest, please post your XSL. It'll help the original poster.
Very true, here it comes:
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exslt="http://exslt.org/common" exclude-result-prefixes="exslt">
<xsl:output method="xml" indent="yes" encoding="utf-8" />
<xsl:key name="folders" match="folder" use="@path" />
<xsl:template match="root"> <xsl:variable name="folders"> <!-- create a temporary tree with a folder structure --> <xsl:copy> <xsl:copy-of select="@*" />
<xsl:for-each select="file"> <!-- sort the files for nicer output --> <xsl:sort select="@path" /> <xsl:sort select="@name" />
<!-- build a folder structure for each file (separately) --> <xsl:apply-templates select="." mode="build-folders"> <xsl:with-param name="path" select="concat(@path, @name)" /> </xsl:apply-templates> </xsl:for-each> </xsl:copy> </xsl:variable>
<!-- we have files in separate folder elements, now merge them --> <xsl:apply-templates select="exslt:node-set($folders)/node()" mode="merge" /> </xsl:template>
<xsl:template match="file" mode="build-folders"> <xsl:param name="path-base" /> <xsl:param name="path" /> <!-- assumption: path always starts with '/' -->
<!-- folder-count equals the number of slashes in the path, minus one for the file name -->
<xsl:param name="folder-count" select="string-length($path) - string-length(translate($path, '/', '')) - 1"/>
<xsl:choose> <!-- should not occur, actually --> <xsl:when test="string-length($path) = 0" />
<!-- path contains slashes, output a folder --> <xsl:when test="$folder-count > 0"> <!-- Note: folder-count = 1 means at least two slashes --> <xsl:variable name="folder-name" select="substring-before(substring-after($path, '/'), '/')" /> <xsl:variable name="folder-path" select="concat($path-base, '/', $folder-name)" /> <xsl:variable name="remainder" select="substring-after(substring-after($path, '/'), '/')" />
<folder name="{$folder-name}" path="{$folder-path}"> <!-- and recurse to add sub folders --> <xsl:apply-templates select="." mode="build-folders"> <xsl:with-param name="path" select="concat('/', $remainder)" /> <xsl:with-param name="path-base" select="$folder-path" /> </xsl:apply-templates> </folder> </xsl:when>
<!-- no more slashes, output the file --> <xsl:otherwise> <!-- note: could do a xsl:copy-of select="." as well --> <file name="{@name}" /> </xsl:otherwise> </xsl:choose> </xsl:template>
<xsl:template match="root" mode="merge"> <xsl:copy> <xsl:copy-of select="@*" />
<!-- insert top-level files --> <xsl:copy-of select="file" />
<!-- apply those folders that are the first ones with a specific path -->
<xsl:apply-templates select="folder[generate-id(.) = generate-id(key('folders', @path)[1])]" mode="merge"/>
</xsl:copy>
</xsl:template>
<xsl:template match="folder" mode="merge"> <xsl:copy> <!-- note: one might want to suppress the path attribute --> <xsl:copy-of select="@*" />
<xsl:copy-of select="key('folders', @path)/file" />
<xsl:apply-templates select="key('folders', @path)/folder[generate-id(.) = generate-id(key('folders', @path)[1])]" mode="merge"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Tree from directory listi, Mukul Gandhi | Thread | Re: [xsl] Tree from directory listi, Mukul Gandhi |
RE: [xsl] [XSLT2.0] xsl:analyze-str, Michael Kay | Date | Re: [xsl] Tree from directory listi, Mukul Gandhi |
Month |