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

Re: [xsl] Ignoring ambiguous matches


Subject: Re: [xsl] Ignoring ambiguous matches
From: Wendell Piez <wapiez@xxxxxxxxxxxxxxx>
Date: Thu, 13 Feb 2014 11:34:26 -0500

Hi Ihe,

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 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 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
Keywords