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

Re: [xsl] Ignoring ambiguous matches

Subject: Re: [xsl] Ignoring ambiguous matches
From: Ihe Onwuka <ihe.onwuka@xxxxxxxxx>
Date: Thu, 13 Feb 2014 16:51:09 +0000

On Thu, Feb 13, 2014 at 4:34 PM, Wendell Piez <wapiez@xxxxxxxxxxxxxxx> wrote:
> Hi Ihe,

Hi Wendell,

> Function composition, yes ... when faced with problems like this I
> have sometimes resorted to a "visitor pattern". This is a technique
> inspired by Dimitre's ingenious implementation of FXSL.

The visitor pattern. Have read a whole book on the thing
and had to code it in compiler class.

I still couldn't explain it's whys or wherefores to you.

> The idea is to bind each process to an element, something like so:
> <xsl:template match="data">
>   <xsl:variable name="processes" as="element()+">
>     <ihe:process1/>
>     <ihe:process2/>
>     <ihe:process3/>
>   </xsl:variable>
>   <xsl:apply-templates select="$processes">
>     <xsl:with-param name="context" select="."/>
>   </xsl:apply-templates>
> </xsl:template>
> Then deploy templates to match the elements in the 'ihe' namespace to
> execute your processes.
> This is really good for managing, for example, sets of tests that have
> to be performed over your data.
> In your case it sounds like there is an additional requirement: each
> process needs, as input, not the original matched element, but the
> results of other processes.
> For that, work one process at a time, passing the results forward:
>   <xsl:apply-templates select="$processes[1]">
>     <xsl:with-param name="results-so-far" select=".">
>     <xsl:with-param name="processes-remaining"
>        select="remove($processes,1)"/>
>   </xsl:apply-templates>
> Your receiving templates (matching in the 'ihe' namespace) must know
> how to pass their results forward into the first process in the
> $processes-remaining stack, or to return their results instead when
> $processes-remaining is empty, something like:
> <xsl:template match="ihe:process1">
>   <xsl:param name="results-so-far" required="yes"/>
>   <xsl:param name="processes-remaining" select="()"/>
>   <xsl:variable name="new-results">
>     ... do your thing ...
>   </xsl:variable>
>   <xsl:choose>
>     <xsl:when test="empty($processes-remaining)">
>       <xsl:sequence select="$new-results"/>
>     </xsl:when>
>     <xsl:otherwise>
>       <xsl:apply-templates select="$processes-remaining[1]">
>         <xsl:with-param name="results-so-far" select="$new-results"/>
>         <xsl:with-param name="processes-remaining"
>            select="remove($processes-remaining,1)"/>
>     </xsl:otherwise>
>   </xsl:choose>
> </xsl:template>
> Using this method, priority setting is not needed; the order of
> processes is indicated by their sequence order.
> That being said, the overhead (syntactic and conceptual) is high
> enough that it may not be worth it except as the complexity of the
> problem goes up. It does support arbitrary mixing and matching of data
> to processes; and exposing the processes by binding them to their
> proxy elements may have other advantages.

I'm guessing this was conceived from XSLT 1.0 because I am trying to
see what it has over the next-match based solution (granted that may
have required explicit priority settings) - I never did try it in the
end - pressure of deadline.

Is this not a graphic illustration of Norvig's point  though - pattern
usage necessitated by what was a missing language feature?

> I hope this helps.
> Cheers, Wendell
> --
> Wendell Piez | http://www.wendellpiez.com
> XML | XSLT | electronic publishing
> Eat Your Vegetables
> _____oo_________o_o___ooooo____ooooooo_^

Current Thread