Subject: RE: best practices re xsl:{import,include,next-match,apply-imports}
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Wed, 7 May 2008 23:51:49 +0100
|
No magic answer to this one. You could use apply-imports instead of
next-match - interesting to see that there is a use case for this. Is there
any reason the generic match="node()|@*" template can't be moved into the
generic stylesheet module?
Changing the import to include seems to me to be storing up other problems
for the future.
Michael Kay
http://www.saxonica.com/
> -----Original Message-----
> From: James A. Robinson [mailto:jim.robinson@xxxxxxxxxxxx]
> Sent: 07 May 2008 16:44
> To: XSL-List
> Subject: best practices re
> xsl:{import,include,next-match,apply-imports}
>
>
> Hi folks,
>
> For the first time I've had an application where I think
> xsl:next-match or xsl:apply-imports might applicable.
>
> This application needs to be able to transform various
> elements in various schema into be a fairly complicated
> atom:entry format (where atom is the Atom Syndication Format,
> http://www.w3.org/2005/Atom) which we have developed to
> indicate hyperlinking relationships. The constructions of
> the atom:entry takes 15 variables into account when it constructed.
>
> A specific example is the need to transform an element from
> the NLM Journal Publishing DTD, the relateed-article element
> into this format.
> Many of the 15 variables used to create the atom:entry are
> generic when dealing with a related-article element. Two are not.
>
> I thought it'd be nice to keep construction of these entries
> as simple as possible for the people who will be maintaining
> these stylesheets.
> Specificaly I want to make it simple to add new templates for
> transforming new types of related-article elements into these
> atom:entry forms.
>
> I thought what I would do is create a generic library
> stylesheet with a callable template which takes 15 tunneled
> parameters and creates the proper atom:entry.
>
> Then I would create a stylesheet which matches on any
> "related-article"
> element, using a priority of 1, which called the library
> template, constructing and passing along those tunneled
> parameters which are generic (i.e., all those parameters
> which are applicable to all related-article elements).
>
> Finally, I wanted to add a last stylesheet with very specific
> "related-article" element match, one which matched on
> specific attributes, and which had a priority of 2. This top
> level stylesheet would use xsl:next-match to tunnel through
> the one or two parameters which weren't handled by the more
> generic layer.
>
> So I'd have
>
> xsl:template match="related-article[...predicates...]" priority="2"
> -> xsl:next-match w/ tunneled 2 parameters
>
> xsl:template match="related-article" priority="1"
> -> xsl:call-template w/ 13 tunneled parameters
>
> xsl:template name="atom:hyperlink"
> xsl:param ...13 tunneled parameters ...
> <atom:entry>...</atom:entry>
>
> This is the first time I'd used xsl:next-match, and I found
> myself being confounded by how one should use xsl:import vs.
> xsl:include or should use xsl:next-match vs. xsl:apply-imports.
>
> My first reaction was that one should use xsl:import and
> xsl:next-match to offer the most flexibility re future
> changes. E.g., introduction of overridable variables or the
> need to "next-match" at various priorities within the highest
> level stylesheet.
>
> What I've realized is that the rules of xsl:import and
> xsl:next-match and how XSLT defines the next-match, by lower
> priority -or- by lower precedence, means I run into trouble
> if I introduce a template which suppresses the default
> behavior of XSLT to print the string value of elements as it
> walks the tree.
>
> To try and boil this down to a simple set of examples, let's
> say I have three stylesheets and a source document:
>
> (1) A named template stylesheet, t.xsl.
>
> <xsl:stylesheet
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
> xmlns:xs="http://www.w3.org/2001/XMLSchema">
> <xsl:template name="t">
> <xsl:param name="a" as="xs:string?" tunnel="yes" />
> <xsl:param name="b" as="xs:string?" tunnel="yes" />
> <xsl:message select="concat('t: ',
> string-join(($a,$b), ', '))"/>
> </xsl:template>
> </xsl:stylesheet>
>
> (2) A "generic" stylesheet, g.xsl, which matches on an element 't' and
> calls the named template in (1) with a tunneled parameter.
>
> <xsl:stylesheet
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
> <xsl:import href="t.xsl"/>
> <xsl:template mode="t" match="t" priority="1">
> <xsl:call-template name="t">
> <xsl:with-param name="a" select="'g'" tunnel="yes"/>
> </xsl:call-template>
> </xsl:template>
> </xsl:stylesheet>
>
> (3) A "specific" stylesheet, s.xsl, which assumes it can fall-back to
> templates in (2) with a tunneled parameter.
>
> Because it is processing a source document filled with other
> elements and text nodes, it also contains a generic match to
> navigate the document while surpressing default XSLT behavior.
>
> <xsl:stylesheet
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
> <xsl:import href="g.xsl"/>
>
> <xsl:template mode="t" match="@*|node()">
> <xsl:apply-templates mode="#current"/>
> </xsl:template>
>
> <xsl:template mode="t" match="t[@specific eq 'yes']"
> priority="2">
> <xsl:next-match>
> <xsl:with-param name="b" select="'s'" tunnel="yes"/>
> </xsl:next-match>
> </xsl:template>
> </xsl:stylesheet>
>
> (4) A source document with a lot of text nodes in it, none of which I
> want to have emitted. I just want a final result of an
> xsl:message ('t: g, s') to be emitted.
>
> <x>text<y>text<t specific="yes"/>text</y>text</x>
>
>
> Because (3) has a template match "@*|node()", which is lower
> precedence, the xsl:next-match won't ever fall back to (2).
> This means I have to make one of the following changes to (3):
>
> (a) change the xsl:import to xsl:include.
> (b) change the xsl:next-match to xsl:apply-import.
> (c) not use a generic match="@*|node()", require that callers
> specifically target the elements to be processed
>
> I'm wondering if there are any other options available? If
> not, is there one of those which the developers here would
> recommend as being likely to be better for long term maintenance?
>
> I'm disclined to choose (c). The problems I have with (a)
> and (b) are that they seem to imply a limitation in later
> flexibility of the stylesheets (e.g., having parameters w/
> the same name but different precedence in (2) and (3), or
> allowing for xsl:next-match to work on templates introduced into (3))
>
> My inclination, at this point, is that it will be better to
> use xsl:include and require that both generic and specific
> template matches have their priorities renumbered as new
> functionality as added.
>
> I'd appreciate any thoughts on this from you folks!
>
>
> Thank you,
>
> Jim
>
> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
> James A. Robinson jim.robinson@xxxxxxxxxxxx
> Stanford University HighWire Press http://highwire.stanford.edu/
> +1 650 7237294 (Work) +1 650 7259335 (Fax)
|