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

Subject: Re: [xsl] having a template remember not to call itself again
From: "Imsieke, Gerrit, le-tex gerrit.imsieke@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Sun, 5 Mar 2023 16:32:11 -0000
Hi Chris,

Michael Kay proposed a way to check (tunnel) parameters when matching in XSLT 4.0: https://github.com/qt4cg/qtspecs/issues/108

We have often used tunnel parameters like $already-processed and xsl:choose that do or do not something based on their values. Michael's proposal can make this more elegant and more efficient.

Apart from that, I'd try to do each micropipeline step in their own mode in order keep the number of templates in a given mode manageable, and how/when they are applied.

Gerrit


On 05.03.2023 17:20, Chris Papademetrious christopher.papademetrious@xxxxxxxxxxxx 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:

B <xsl:template match="CONDITION1_HERE">

B B B <!-- apply this template's processing first -->

B B B <xsl:variable name="result" as="element()">

B B B B B ...PROCESSING1_HERE...

B B B </xsl:variable>

B B B <!-- apply subsequent self-or-children templates last -->

B B B <xsl:apply-templates select="$result"/>

B </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:

B <xsl:template match="CONDITION2_HERE">

B B B <!-- apply subsequent self-or-children templates first -->

B B B <xsl:variable name="result" as="node()*">

B B B B B <xsl:next-match/>

B B B </xsl:variable>

B B B <!-- apply this template's processing last -->

B B B ...PROCESSING2_HERE...

B </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:

B <xsl:template match="CONDITION1_HERE[not($CONDITION1_CALLED)]">

B B B <xsl:param name="CONDITION1_CALLED" as="xs:boolean" select="false()" tunnel="yes"/>

B B B <!-- apply this template's processing -->

B B B <xsl:variable name="result" as="element()">

B B B B B b&PROCESSING1_HEREb&

B B B </xsl:variable>

B B B <!-- apply subsequent self-or-children templates -->

B B B <xsl:apply-templates select="$result">

B B B B B <xsl:with-param name="CONDITION1_CALLED" as="xs:boolean" select="true()" tunnel="yes"/>

B B B </xsl:apply-templates>

B </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/225679> (by email <>)

-- Gerrit Imsieke GeschC$ftsfC<hrer / Managing Director le-tex publishing services GmbH Weissenfelser Str. 84, 04229 Leipzig, Germany Phone +49 341 355356 110, Fax +49 341 355356 510 gerrit.imsieke@xxxxxxxxx, http://www.le-tex.de

Registergericht / Commercial Register: Amtsgericht Leipzig
Registernummer / Registration Number: HRB 24930

GeschC$ftsfC<hrer / Managing Directors:
Gerrit Imsieke, Svea Jelonek, Thomas Schmidt

Current Thread