Re: [xsl] Legibility, repetition, nesting

Subject: Re: [xsl] Legibility, repetition, nesting
From: "David Birnbaum djbpitt@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Sun, 26 Jul 2020 20:30:53 -0000
Dear xsl-list,

I am grateful to all of those who responded to my inquiry, below.

Packaging the variables inside a map, as several readers suggested, so that
I have to pass only one thing when I hand off responsibility from the
general template (does the common stuff for all items) to the type-specific
ones, reduces the repetition substantially, and calling a function to wrap
up the variables, instead of doing it directly inside the template that
does the calling, as readers also suggested, improves the legibility. So
far, so good.

I thought I had settled on using <xsl:next-match> to transfer control to a
type-specific template for the type-specific processing as needed, but I
ran into a problem because I was invoking <xsl:next-match> inside an
<xsl:-for-each> (actually, two of them), and "using <xsl:for-each> makes
the current template rule null" (Kay, p. 400). I hadnbt known about this
limitation before, and if I have understood correctly, it seems to mean
that I cannot use <xsl:next-match> inside <xsl:for-each>. I could move the
entire for-each processing inside the next-match template, but then I'm
repeating the same for-each code and common processing inside all of the
next-match templates, and I'm trying to avoid repetition. Using template
matching, rather than calling functions, is convenient because I have
values for the type-specific templates like <xsl:template
match="item[paradigm='1*a%1% B' 9']">, that is, values that cannot be used
directly as XML names. Those values come from the original data, and
although I could build a mapping table or function to translate them into
XML names, it would be more legible, more self-documenting (to a developer
who knows the data, that is, me), more convenient, and less error-prone to
use them directly, as is possible with @match values like the one
illustrated above.

So: Is there a way I am overlooking for working around the inability to use
<xsl:next-match> inside <xsl:for-each>, one that would let me, inside
<xsl:for-each> use the original, data-driven <paradigm> values to identify
where the type-specific processing should happen? Ideally the method would
work with Saxon HE and without extension functions.

Best,

David

On Mon, Jul 20, 2020 at 1:03 PM David Birnbaum djbpitt@xxxxxxxxx <
xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:

> Dear XSL-list,
>
> I write here for advice about Best Practice. The question is at the end;
> because I am constitutionally unable to be concise, the long narrative
> before it is context.
>
> I'm developing an XSLT stylesheet that processes 134 different types of
> items (same generic identifier, distinguished by an attribute value). For
> each item, regardless of type, I create several variables, do an
> <xsl:copy>, and inside that first create some other content that is common
> to all items, regardless of type, and then use <xsl:choose> to handle the
> types differently, according to their idiosyncrasies. I began by
> implementing this as a single template with a long <xsl:choose> deeply
> nested inside it, which has the advantage of avoiding unnecessary
> repetition, since the shared operations are outside the <xsl:choose>. It
> works, but perfectionism is a terrible curse ...
>
> Perhaps I'm being arbitrarily fastidious, but the <xsl:choose> inside the
> deep nesting feels awkward; I wind up with one template that runs to more
> than a thousand lines, where the <xsl:choose> is seven levels deep. This
> made me wonder whether off-loading the type-specific tasks to separate
> templates or functions, which could be called from the appropriate place,
> would keep the main template down to a more manageable size. Specifically,
> I'd like to be able to put the code blocks currently inside of the
> <xsl:when> statements somewhere other than deep inside a single main
> template.
>
> One implementation of this approach that works, but comes with its own
> issues, is using an <xsl:next-match> with auxiliary lower-priority
> templates that match item[@type eq 'x']. This lets me break out the
> type-specific code into separate templates. The reason this is not wholly
> satisfactory is that I have to pass all of the variables into these
> separate templates as parameters, so I wind up repeating the same
> <xsl:param> statements inside each of the secondary templates. That much
> repetition feels suboptimal.
>
> The only approach that occurs to me that might simultaneously eliminate
> repetition and avoid putting all of the processing inside a single
> thousand-line template, most of which is the <xsl:choose> with all of the
> type-specific handling inside <xsl:when> children, is to put the
> type-specific processing into separate files, with an <xsl:when> root, and
> then <xsl:include> them inside the <xsl:choose>. One downside seems to be
> that they will not be valid XSLT (they wonbt have the necessary wrapper
> boilerplate and the variables they use wonbt be defined inside them),
which
> I think I could overcome by using an <oXygen/> "master document", which
> would cause them to be validated in context. That isn't ideal, since it's
> tied to a specific development environment, but since that happens to be my
> usual development environment, the objection is philosophical (= can be
> ignored in the interest of Getting The Job Done), rather than practical.
>
> So: Is there a Best Practice approach to breaking out the type-specific
> treatment of the different types of items that avoids both 1) unnecessary
> repetition and 2) embedding a single thousand-line <xsl:choose>, which
> contains all of the type-specific operations, seven levels deep inside a
> template?
>
> Thanks,
>
> David
>
> XSL-List info and archive <http://www.mulberrytech.com/xsl/xsl-list>
> EasyUnsubscribe <http://lists.mulberrytech.com/unsub/xsl-list/3318727> (by
> email <>)

Current Thread