xsl-list
[Top] [All Lists]

Re: [xsl] Legibility, repetition, nesting

2020-07-20 15:40:33
David, Andre and List,

+1 I was going to mention visitors (actually I just did in another
context) aka dispatch templates. Plus, tunnel parameters. It should
not be necessary to do any choosing explicitly. An implicit selection
will also be easier to maintain.

What he said -- thanks!
Wendell

On Mon, Jul 20, 2020 at 4:19 PM David Birnbaum djbpitt(_at_)gmail(_dot_)com
<xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com> wrote:

Dear Andre (cc xsl-list),

Thank you for the quick response. This is appealing because it reduces the 
repetition of <xsl:param> inside the secondary templates, since I would pass 
just one item, instead of five separate variables.

Best,

David

On Mon, Jul 20, 2020 at 4:00 PM Andre Cusson akhu01(_at_)gmail(_dot_)com 
<xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com> wrote:

Hi,

Why not put the variables in a structure (ex. markup, map, array), the 
apply-templates with type selector and pass the parameter structure, 
possibly through a tunnel param with an additional dispatch template?

Regards,
ac

Le lun. 20 juil. 2020 à 14:23, David Birnbaum djbpitt(_at_)gmail(_dot_)com 
<xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com> a écrit :

Dear Syd (cc xsl-list),

Thanks for the quick response. As you note, the actual main template does a 
lot of things that are common to all types before it gets to the 
<xsl:choose>, and if I write completely separate templates for each of the 
types, I would need to repeat that shared code verbatim in each of the 
type-specific templates. The variables do have to be inside the templates 
because they are specific to each item. It isn't just variables, there are 
about 30 lines of code common to all items, including variable 
declarations, literal result elements (depending on variables), copies of 
elements and attributes. and a couple of for-each statements, with the 
<xsl:choose> inside the inner for-each.

Best,

David



On Mon, Jul 20, 2020 at 1:32 PM Bauman, Syd 
s(_dot_)bauman(_at_)northeastern(_dot_)edu 
<xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com> wrote:

Hi David!

I don’t feel qualified to pontificate on best practice, but happy to 
suggest pros and cons of alternatives. But first, let’s make sure I have 
this right—the current basic structure is roughly as follows:

  <xsl:template match="item">
    <xsl:variable name="pre-choose-var-1" select="''"/>
    <xsl:variable name="pre-choose-var-2" select="''"/>
    <xsl:copy>
      <xsl:sequence select="common-stuff"/>
      <xsl:choose>
        <xsl:when test="@type eq '001'"><!-- 001-specific --></xsl:when>
        <xsl:when test="@type eq '002'"><!-- 002-specific --></xsl:when>
        <!-- ... -->
        <xsl:when test="@type eq '133'"><!-- 133-specific --></xsl:when>
        <xsl:when test="@type eq '134'"><!-- 134-specific --></xsl:when>
      </xsl:choose>
    </xsl:copy>
  </xsl:template>

If so, I wonder if dividing the one huge template up into 134 small ones 
would be more manageable:

  <xsl:template match="item[@type eq '001']">
    <xsl:variable name="pre-choose-var-1" select="''"/>
    <xsl:variable name="pre-choose-var-2" select="''"/>
    <xsl:copy>
      <xsl:call-template name="do-common-stuff"/>
      <!-- 001-specific -->
    </xsl:copy>
  </xsl:template>

No “main” template at all. If the pre-choose variables do not depend on 
@type, a lot of repetition, though. (I am presuming the variables need to 
be inside the template, which you implied, but did not state, if I read 
right.)

Just a thought. Stay safe, keep coding.

________________________________
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 won’t have the necessary wrapper 
boilerplate and the variables they use won’t 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?


XSL-List info and archive
EasyUnsubscribe (by email)

XSL-List info and archive
EasyUnsubscribe (by email)

XSL-List info and archive
EasyUnsubscribe (by email)

XSL-List info and archive
EasyUnsubscribe (by email)



-- 
...Wendell Piez... ...wendell -at- nist -dot- gov...
...wendellpiez.com... ...pellucidliterature.org... ...pausepress.org...
...github.com/wendellpiez... ...gitlab.coko.foundation/wendell...
--~----------------------------------------------------------------
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>