[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

Re: [xsl] Preferred declarative approach for outputting tallies based on complex triggers


Subject: Re: [xsl] Preferred declarative approach for outputting tallies based on complex triggers
From: Michael Kay <mike@xxxxxxxxxxxx>
Date: Thu, 10 Apr 2014 12:41:12 +0100

I don't find the adjective "declarative" particularly helpful here. I don't
know how to assess whether one stylesheet is more declarative than another.

When you are processing a sequence and the result of processing one item
depends on the results of processing previous items, there are three possible
approaches:

* head/tail recursion

* a higher-order fold() function

* xsl:iterate

At one level all three are equivalent. head/tail recursion is probably the
simplest and most primitive. But advising one against the others is a bit like
arguing between "for" and "while" expressions. It's essentially a matter of
style.

When it comes to streamability, xsl:iterate is preferred because the data flow
is more amenable to static analysis.

Michael Kay
Saxonica

On 10 Apr 2014, at 12:12, David Rudel <fwqhgads@xxxxxxxxx> wrote:

> I have a general question for those who adhere to declarative methods.
> What is your preferred regime for outputting results of analyzing a
> sequence of items? The "analysis" here might be complicated, requiring
> state variables, counters, and triggers (to determine when the
> counting occurs). Then the "results" would be the final values of
> those counters.
>
> The main issue I'm thinking about is determining when the sequence has
> been consumed so you know when to write the outputs to the result
> document.
>
> I simply use the <xsl:iterate> instruction, and then the
> <xsl:on-completion> instruction takes care of this question of
> determining when the sequence is finished.
>
> From my rather inexperienced perspective, a declarative approach to
> this would be something like:
>
> <xsl:variable name="seq" select="<<find the items I need to process>>"/>
>
> <xsl:apply-templates select="$seq" mode="analyze">
> (: put a bunch of with-param elements in here to control counters and
> triggers and anything you need to control the analysis :)
> </xsl:apply-templates>
>
> <xsl:template mode="analyze">
> (: pick up parameters:)
> (: modify the state variables and triggers:)
>
> <xsl:if test="position() = last()">
> (: output results here :)
> </xsl:if>
> </xsl:template>
>
> Another method would be to use a recursive function on a sequence:
>
> <xsl:function name="mynamespace:analyze">
> <xsl:param name="seq" as="item()*">
> (:several other parameters to control analysis: counters, triggers,
> state variables, etc.:)
>
> <xsl:choose>
> <xsl:when test="empty($seq)">
> (:output data :)
> </xsl:when>
> <xsl:otherwise>
> (: Modify counters, triggers, and state variables based on their
> current values and head($seq))
> <xsl:sequence select="mynamespace:analyze(tail($seq), (: new state
> variables and counters:))/>
> </xsl:otherwise>
> </xsl:choose>
> </xsl:function>
>
> I was wondering what experienced users did in these cases and if
> either of the above is wrong-headed.
> -David
>
> --
>
> "A false conclusion, once arrived at and widely accepted is not
> dislodged easily, and the less it is understood, the more tenaciously
> it is held." - Cantor's Law of Preservation of Ignorance.


Current Thread