Re: [xsl] recursive addition

Subject: Re: [xsl] recursive addition
From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx>
Date: Thu, 15 Jan 2004 13:59:35 -0500
Brendan,

This was a fun problem so I looked at it last night.

Here's my solution. It uses the EXSL node-set extension function. I tried to think about how to do it without, but it made my brain hurt. That is not to say that it can't be done. (Actually now I see Josh may have done that. :-)

To use exslt:node-set() in this way is, in effect, to run more than one pass over the document. Rather than taking the flat linked structure and making a true hierarchy to traverse, however, this approach is to traverse the virtual hierarchy and collect the data points as it goes into a uniform flat structure with no links and no implicit hierarchy, then go from there.

Basically the key is used to retrieve folders recursively from one another, traversing the hierarchy. The count of files in each is then written to a result-tree; the stylesheet simply sums the files from the result tree (converted into a node set using the extension function) and reports the sum.

<xsl:stylesheet version="1.0"
    xmlns:exslt="http://exslt.org/common";
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>

<xsl:output method="text"/>

<xsl:param name="start" select="'dir0'"/>

<xsl:key name="folder-by-id" match="folder" use="@id"/>

<xsl:variable name="collected">
  <xsl:apply-templates select="key('folder-by-id',$start)" mode="collect"/>
</xsl:variable>

<xsl:template match="folder" mode="collect">
  <files>
    <xsl:value-of select="@files"/>
  </files>
  <xsl:apply-templates select="key('folder-by-id',file/@id)" mode="collect"/>
</xsl:template>

<xsl:template match="/">
  <xsl:value-of select="sum(exslt:node-set($collected)/files)"/>
</xsl:template>

</xsl:stylesheet>

You can pass a parameter in to designate which folder you want to get the count of. There does have to be one folder at the "top" of your count (though this starting folder can be anywhere).

Note it should be really easy to write an instance document that would send your processor into orbit using this stylesheet -- all you need to do is have a folder "contain" itself at some level. Different processors have different ways of handling infinite loops.

Cheers,
Wendell

At 07:46 PM 1/14/2004, you wrote:
Perhaps the way to go is to write an xslt to convert from the flat file format to a nested one.


======================================================================
Wendell Piez                            mailto:wapiez@xxxxxxxxxxxxxxxx
Mulberry Technologies, Inc.                http://www.mulberrytech.com
17 West Jefferson Street                    Direct Phone: 301/315-9635
Suite 207                                          Phone: 301/315-9631
Rockville, MD  20850                                 Fax: 301/315-8285
----------------------------------------------------------------------
  Mulberry Technologies: A Consultancy Specializing in SGML and XML
======================================================================


XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list



Current Thread