xsl-list
[Top] [All Lists]

Re: [xsl] How do I pass the mode as a string?

2020-03-04 02:52:53
And, yes, I did forget something which is a minor improvement:  Can put
those dynamic matching templates in their own mode as well:

*<xsl:mode name="dynamic-mode" on-no-match="fail" />*
<xsl:template match="dm:inputs" *mode="dynamic-mode"*
xmlns:dm="dynamic:match">
    <xsl:param name="context" as="node()" />

    <xsl:apply-templates select="$context" mode="inputs" />
</xsl:template>

<xsl:template match="dm:outputs" *mode="dynamic-mode"*
xmlns:dm="dynamic:match">
    <xsl:param name="context" as="node()" />

    <xsl:apply-templates select="$context" mode="outputs" />
</xsl:template>

which then requires the apply-template to reference that mode.

<xsl:apply-templates select="dm:matchElement($mode)" *mode="dynamic-mode"*
xmlns:dm="dynamic:match">
    <xsl:with-param name="context" select="current()" />
</xsl:apply-templates>

This way, everything is quite "à la mode"!

On Wed, Mar 4, 2020 at 9:39 AM Alan Painter 
alan(_dot_)painter(_at_)gmail(_dot_)com <
xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com> wrote:

Another option is to take one of the tricks that Dimitre Novatchev
employed in the excellent FXSL for XSLT2.0.


http://conferences.idealliance.org/extreme/html/2006/Novatchev01/EML2006Novatchev01.html

This can be a way to work around the absence of higher-ordered functions
in the community editions of the XSLT processors.

The trick is to select your desired template by performing an
xsl:apply-templates against a generated "special" element.

For instance, in the original example, there are two desired modes and we
want to call either mode "inputs" or "outputs".
For illustration purposes, we can define those modes and the templates
that are declared for those modes:

<!-- templates for mode "inputs" -->
<xsl:mode name="inputs" on-no-match="fail" />
<xsl:template match="element()" mode="inputs" > .. </xsl:template>
<xsl:template match="attribute()" mode="inputs" > .. </xsl:template>
...

<!-- templates for mode "outputs" -->
<xsl:mode name="outputs" on-no-match="fail" />
<xsl:template match="element()" mode="outputs" > .. </xsl:template>
<xsl:template match="attribute()" mode="outputs" > .. </xsl:template>

(Not required to declare the mode, of course, but I like to do this in
order to set a fail in case I've missed a match condition somewhere.)

Now, the question is, how to match those modes "dynamically".  We can set
some other templates that cal  xsl:apply-templates themselves using these
modes.

<xsl:template match="dm:inputs" xmlns:dm="dynamic:match">
    <xsl:param name="context" as="node()" />

    <xsl:apply-templates select="$context" mode="inputs" />
</xsl:template>

<xsl:template match="dm:outputs" xmlns:dm="dynamic:match">
    <xsl:param name="context" as="node()" />

    <xsl:apply-templates select="$context" mode="outputs" />
</xsl:template>

(Can obviate the re-definition of the 'dm' namespace by declaring it
within the enclosing stylesheet or package element.)

Now, finally, we need to call these templates.  We need to be able to
perform an "apply-templates" on a "dm:inputs" element or a "dm:outputs"
element.  For this, we can use a helper function:

<xsl:function name="dm:matchElement"
as="element()" xmlns:dm="dynamic:match">
    <xsl:param name="localName" as="xs:string" />

    <xsl:element name="dm:{$localName}" namespace="dynamic:match" />
</xsl:function>

Now we can perform an apply-templates that matches templates in either of
the modes:

<xsl:apply-templates select="dm:matchElement($mode)"
xmlns:dm="dynamic:match">
    <xsl:with-param name="context" select="current()" />
</xsl:apply-templates>

where the variable 'mode' can be either "inputs" or "outputs" in this
example.

(Again, can obviate the delcaration of the 'dm' namespace by declaring in
the enclosing stylesheet or package element.)

I've constrained the templates matching to "node()" values here but this
could work with "item()" values as well if I'm not mistaken.

Anyway, that's another twist that XSLT offers (even XSLT 2.0) which would
allow you to have the equivalent of being able to assign a mode dynamically.

Obviously, easier to do as higher-order-functions, but it's another tool
that's available in the community editions.

On Wed, Mar 4, 2020 at 3:07 AM Liam R. E. Quin 
liam(_at_)fromoldbooks(_dot_)org <
xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com> wrote:

On Tue, 2020-03-03 at 22:47 +0000, Wendell Piez 
wapiez(_at_)wendellpiez(_dot_)com
wrote:
I am also hoping that Liam suggests generating the templates
dynamically, then using the transform() function to apply them.

:-)

Well, i mentioned shadow attributes because David Carlisle’s assertion
was no longer entirely true, which i thought it worth pointing out.

It’s true you could write an XSLT transform to create a stylesheet
using a given mode, and then apply it, all in-memoy, with
fn:transform().

But i prefer to keep things as simple and maintainable as possible!

Liam

--
Liam Quin, https://www.delightfulcomputing.com/
Available for XML/Document/Information Architecture/XSLT/
XSL/XQuery/Web/Text Processing/A11Y training, work & consulting.
Barefoot Web-slave, antique illustrations:  http://www.fromoldbooks.org

XSL-List info and archive <http://www.mulberrytech.com/xsl/xsl-list>
EasyUnsubscribe <http://lists.mulberrytech.com/unsub/xsl-list/552232> (by
email <>)

--~----------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
EasyUnsubscribe: http://lists.mulberrytech.com/unsub/xsl-list/1167547
or by email: xsl-list-unsub(_at_)lists(_dot_)mulberrytech(_dot_)com
--~--
<Prev in Thread] Current Thread [Next in Thread>