[xsl] modular xslt design question

Subject: [xsl] modular xslt design question
From: "Dave Gomboc" <dave@xxxxxxxxxxxxxx>
Date: Thu, 1 Mar 2001 00:28:58 -0700
I'm developing a set of related, but different, transformations using
apply-templates with various modes.  This is relatively unstructured
data, where many tags can include many other tags, but are not required
to do so, so I'm using push-style (apply-templates).

I intended to use different modes to handle the various classes of
related transformations (e.g. rendering in three different styles: foo,
bar, and wow.)

<xsl:template match="A" mode="foo">
  ...some stuff here...
  <xsl:apply-templates select="." mode="foo"/>
</xsl:template>

Similarly,

<xsl:template match="A" mode="bar">...</xsl:template>
<xsl:template match="A" mode="wow">...</xsl:template>
<xsl:template match="B" mode="foo">...</xsl:template>
<xsl:template match="B" mode="bar">...</xsl:template>
<xsl:template match="B" mode="wow">...</xsl:template>
<xsl:template match="C" mode="foo">...</xsl:template>
<xsl:template match="C" mode="bar">...</xsl:template>
<xsl:template match="C" mode="wow">...</xsl:template>

Now, I have some items that should be handled in the same way,
regardless of the mode.

<xsl:template match="D" mode="foo bar wow">...</xsl:template>

Of course, the above isn't legal, because mode only holds a QName, not a
list of them.  I would like to avoid cut-and-pasting the common template
n times (where n is the number of styles I have -- it will be more than
three!).  I also don't see a way to apply-templates (back in A, B, and
C) in document order such that the child elements can be matching in
different modes.

My intended workaround was to use templates without modes to manage the
general flow, with a parameter being passed through all(!) of them to
indicate the intended mode/style.  Templates with behaviour common to
all modes can be implemented directly; others can be implemented by
dispatching to mode-specific named templates, e.g.

<xsl:template match="A">
    <xsl:param name="mode"/>
    <xsl:call-template name="A" mode="$mode">
        <xsl:with-param value="$mode"/>
    </xsl:call-template>
</xsl:template>

<xsl:template match="A" name="A" mode="foo">
    <!-- foo-specific handling here-->
    <xsl:apply-templates>
        <xsl:with-param value="$mode"/>
    </xsl:apply-templates>
</xsl:template>

<xsl:template match="A" name="A" mode="bar">
    <!-- bar-specific handling here-->
    <xsl:apply-templates>
        <xsl:with-param value="$mode"/>
    </xsl:apply-templates>
</xsl:template>

<xsl:template match="A" name="A" mode="wow">
    <!-- wow-specific handling here-->
    <xsl:apply-templates>
        <xsl:with-param value="$mode"/>
    </xsl:apply-templates>
</xsl:template>

<!-- B and C would be similar to A -->

<xsl:template match="D">
    <xsl:param name="mode"/>

    <!-- can implement D directly here -->

    <xsl:apply-templates>
        <xsl:with-param name="mode" select="$mode"/>
    </xsl:apply-templates>
</xsl:template>

Unfortunately, this is busted, because call-template doesn't support
modes (why not?), and even if it did, the mode QName cannot be
constructed at runtime anyway [Kay p.388].

So, I'm badly in need of a bright idea.  Any takers? :-)

Dave Gomboc



 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread