This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Is recursion in XSL really this difficult?


[xmlhack]


> I posted a question about recursion a day or two ago, but all of my
efforts
> since then have been unsuccessful.
>
> What I need to do is search a text node for a string and add bolding
around
> that string when it's found (for HTML output).  I CAN do that thanks to
> Kay's example in the XSLT book.  But what I need to do now is recurse over
> THE ENTIRE string -- not just a piece of it -- a second and third time to
> find matches for a second and third string.
>
> Based on what I've seen in my failed attempts, I think what I need to do
is
> store the entire text node in a string (or node set...no more temp trees,
> right?), process it the first time, process it a second time, and process
it
> a third time.  But, all my attempts to do this have resulted in the text
> node being output 3 times.

I think you're on the right track but there are a few details that aren't
right.  They have to do with xsl:param being used incorrectly, as if it were
a variable.

The idea is this:  for each pass create a variable containing the results of
the processing for that pass.  Then call the template for the next pass,
using an xsl:with-param whose value equals the variable you just created.
You're not quite doing this.

Actually, you may not even have to call other templates and pass parameters
to them at all.

Here's a 3-pass stylesheet that does three passes, then outputs the results.
It starts with the value 6, multiplies it first by 2, then by 3, then adds 4
for a final result of 40:

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

<xsl:variable name='raw-data' select='6'/>

<xsl:template match="/">
<results>
 <xsl:variable name='first-pass' select='2*$raw-data'/>
 <xsl:variable name='second-pass' select='3*$first-pass'/>
 <xsl:variable name='third-pass' select='4+$second-pass'/>
 <xsl:value-of select='$third-pass'/>
</results>
</xsl:template>

</xsl:stylesheet>

The output (for any input file) is, as expected:

<results>40</results>

At any stage, you could call another template instead of computing the
result in-line as I did in this simple example.  Here, I call a template for
the third pass:

<xsl:template match="/">
<results>
 <xsl:variable name='first-pass' select='2*$raw-data'/>
 <xsl:variable name='second-pass' select='3*$first-pass'/>

 <xsl:variable name='third-pass'>
  <!--===== Call a template for the third pass =====-->
  <xsl:call-template name='last-pass'>
   <xsl:with-param name='second-pass' select='$second-pass'/>
  </xsl:call-template>
 </xsl:variable>

   <xsl:value-of select='$third-pass'/>
</results>
</xsl:template>

<!--=========== Third pass processing ===========-->
<xsl:template name='last-pass'>
     <xsl:param name='second-pass'/>
     <xsl:value-of select='4+$second-pass'/>
</xsl:template>


You only hitch might be if you need to keep iterating over node-sets,
because you will be getting back result-tree-fragments.  You can probably
work around this, if it arises, by using xsl:for-each on the initial pass,
or by using a processor (like saxon) that has an extension function to
convert an RTF to a node set.

Remember, when you get stuck, simplify as much as possible, then take little
steps until you get unstuck. 6*2 is much easier to work with than a complex
match-and-replace operation.

Cheers,

Tom P


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]