[xsl] Complex recursion in XSLT 1.0

Subject: [xsl] Complex recursion in XSLT 1.0
From: "Marroc" <marrocdanderfluff@xxxxxxxxxxx>
Date: Mon, 18 Feb 2008 10:17:33 -0000
Hi all,

I haven't written to the list with this one up until now because I doubted
my ability to describe it adequately for you. But now I'm really stuck and I
feel like it is down to the inadequacies of XSLT 1.0 so I wanted to find out
if I'm right or wrong. 

Basically, I've tried every approach I can think of but each time I find
that XSLT 1.0 lacks any kind of 'memory' of what it has done. I can't find a
way of passing parameters back up the tree to effectively say 'done this
one' or stop processing these sub-nodes now.

The scenario is that, I have a set of xhtml files that together describe a
table of contents (toc) with different branches expanded. I only ever know
the name of the first one, that is, 'toc.htm'. From toc.htm, I can read the
second level of toc in files with names similar to 'toc41837.htm'. Inside
these are further topic and toc filenames, potentially up to 5 or 6 levels
deep but I'm only dealing with 3 levels at the moment. From these files, I
need to create a mapping file of the form:

<mappings>
	<relationship topic="123.htm" toc="toc.htm" />
	<relationship topic="456.htm" toc="toc41837.htm" />
</mappings>

This is then used by the next xsl to relate topics to toc's in all
hyperlinks so that they can remain synchronised when a page is generated
server-side by asp.net.

So, I started by attempting a recursive a template that uses several
repeated 'mode' templates level1, level2 through levela (to give 10).

<xsl:template match="/">
	<xsl:variable "container"
		<xsl:call-template name="toc_load"
			<xsl:with-param name="toc_name">toc.htm</
		</
	</
<!-- sort and output to output document -->
</xsl:template>

<xsl:template "load_toc" open first document and process links
	<apply-templates select="a"
		<xsl:with-param "toc_name"

<xsl:template process links to topics (a @href not starting with 'toc')
	<xsl:with-param "toc_name"
	< create mapping using current @href and current toc_name

<xsl:template process links to other toc's
	<xsl:with param "toc_name"
		but don't process same toc again
		<xsl:call-template "load_toc2"
			<xsl:with-param name="toc_name" select="toc_name" />
			<xsl:with-param name="toc_name2" select="@href" />

<!-- Level2 -->	

<xsl:template "load_toc2"
	same again with mode="level2" and param toc_name and toc_name2

<xsl:template process links to topics (a @href not starting with 'toc')
mode="level2"

<xsl:template process links to other toc's
	<params toc_name and toc_name2
	<call toc_load3

<!-- Level3 -->

etc. to Levela passing params for all previously opened tocs


Now the problem was that each toc mentions all the earlier tocs and all the
later tocs as follows:

		<a href="toc.htm" target="TOC"><img src="minus.gif" /></a><a
href="1598.htm">Topic abc</a><br/>
expanding-->	<a href="toc15974.htm"><img src="plus.gif" /></a><a
href="1601.htm">Topic def</a><br/>
topic-->    	<a href="1604.htm">Topic hij</a><br/>
		<a href="toc159710.htm" target="TOC"><img
src="plus.gif"/></a><a href="1599.htm">Topic klm</a><br/>
		<a href="toc159717.htm" target="TOC"><img
src="plus.gif"/></a><a href="1600.htm">Topic nop</a><br/>

So, once Levela is finished, the transform works it's way up to finish off
the stack of templates it has completed. But, it has now forgotten that it
processed that Levela template and so it is called again where it is found.

I need a way to either give the transform an overall memory of what it has
already processed, or, stop processing subsequent nodes once the first toc
file has been called from within a branch. 

I hope someone can suggest some sensible ideas on this one because I've
tried everytning I can find and still can't get this particular recursion to
work!

Richard

Current Thread