Re: [xsl] having a template remember not to call itself again

Subject: Re: [xsl] having a template remember not to call itself again
From: "Dimitre Novatchev dnovatchev@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Sun, 5 Mar 2023 18:18:16 -0000
With all due respect, this seems most likely the result of messy
design/algorithm.

There is nothing wrong in general to have the same template called many
times in a chain of calls. And due to XSLT being a functional language,
recursion is one often-used practice.

Also, there are many examples where the same processing chain must be
applied many times until the necessary precision is reached -- for example
calculating the limit of a sequence or the sum of a series with desired
precision.

For recursive processing, my preferred way of maintaining full confidence
that the recursion will end is totally similar to a mathematical induction
proof. Yes, one must be able to **prove** that the algorithm is correct.

That is:

  1. It is a fact that some statement P is true (the algorithm produces
the correct result) for a range of numbers, say 1 to N.

  2. We can prove that if P is true for K, then it is true for K+1

Based on these two steps we conclude that P is true for all natural numbers.

And if someone cannot perform a similar "proof" of their recursion
algorithm, then this indicates that most likely there are flaws in the
algorithm


Thanks,
Dimitre



On Sun, Mar 5, 2023 at 8:20b/AM Chris Papademetrious
christopher.papademetrious@xxxxxxxxxxxx <
xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:

> Hi everyone,
>
>
>
> I have a stylesheet with many templates that must all chain together and
> play nice with each other. So I write them in the following form:
>
>
>
>   <xsl:template match="CONDITION1_HERE">
>
>
>
>     <!-- apply this template's processing first -->
>
>     <xsl:variable name="result" as="element()">
>
>       ...PROCESSING1_HERE...
>
>     </xsl:variable>
>
>
>
>     <!-- apply subsequent self-or-children templates last -->
>
>     <xsl:apply-templates select="$result"/>
>
>   </xsl:template>
>
>
>
> When a template applies its processing first then calls other templates
> last, I will call it btail-callb template chaining (although I donbt
know
> the correct term).
>
>
>
> For btail-callb chaining to work, PROCESSING1_HERE must transform the
> content so that CONDITION1_HERE is not met again (or at least not met in a
> way that loops infinitely).
>
>
>
> But, what if PROCESSING1_HERE is very complex (nested moded templates,
> recursion, etc.) and sometimes CONDITION1_HERE will match after this
> template was previously applied, and there is no practical way to embed the
> complexity of predetermining PROCESSING1_HEREbs failure to remove the
> condition into CONDITION1_HEREbs match expression?
>
>
>
> This could be avoided by using bhead-callb chaining:
>
>
>
>   <xsl:template match="CONDITION2_HERE">
>
>
>
>     <!-- apply subsequent self-or-children templates first -->
>
>     <xsl:variable name="result" as="node()*">
>
>       <xsl:next-match/>
>
>     </xsl:variable>
>
>
>
>     <!-- apply this template's processing last -->
>
>     ...PROCESSING2_HERE...
>
>   </xsl:template>
>
>
>
> But now, all bets are off on what PROCESSING2_HERE will encounter. Maybe
> the result will have multiple elements, or be filtered out to zero
> elements, or might have text() nodes interspersed due to reformatting and
> styling templates. Maybe <xsl:next-match/> modified the content such that
> CONDITION2_HERE isnbt even matched any more. PROCESSING2_HERE must handle
a
> much wider range of possible input, and the more templates that exist in
> the stylesheet, the more varied the input from <xsl:next-match/> might be.
> (I actually had all my templates written as bhead-callb chaining, and I
am
> converting them to btail-callb chaining due to such issues.)
>
>
>
> So now Ibm back to btail-callb chaining, and figuring out how to get
a
> template to not call itself when it fails to remove the condition
> triggering the match. I tried setting a tunnelling variable that would give
> a heads-up to the template not calling itself again:
>
>
>
>   <xsl:template match="CONDITION1_HERE[not($CONDITION1_CALLED)]">
>
>     <xsl:param name="CONDITION1_CALLED" as="xs:boolean" select="false()"
> tunnel="yes"/>
>
>
>
>     <!-- apply this template's processing -->
>
>     <xsl:variable name="result" as="element()">
>
>       b&PROCESSING1_HEREb&
>
>     </xsl:variable>
>
>
>
>     <!-- apply subsequent self-or-children templates -->
>
>     <xsl:apply-templates select="$result">
>
>       <xsl:with-param name="CONDITION1_CALLED" as="xs:boolean"
> select="true()" tunnel="yes"/>
>
>     </xsl:apply-templates>
>
>   </xsl:template>
>
>
>
> but the templatebs $CONDITION1_CALLED parameter is out-of-scope in its
> match expression.
>
>
>
> So now the only solution I can think of is to put some kind of temporary
> marker attribute in the matching element, then have a final document-down
> cleanup pass to remove the markers. And if multiple templates need markers,
> Ibll need to clean them all up. Icky.
>
>
>
> Is there a more elegant way to handle this that am missing?
>
>
>
> Thanks as always for your collective wisdom, and thanks for making it this
> far!
>
>
>
>    - Chris
>
>
>
> -----
> Chris Papademetrious
>
> Tech Writer, Implementation Group
>
> (610) 628-9718 home office
>
> (570) 460-6078 cell
>
>
> XSL-List info and archive <http://www.mulberrytech.com/xsl/xsl-list>
> EasyUnsubscribe <http://lists.mulberrytech.com/unsub/xsl-list/782854> (by
> email <>)

Current Thread