xsl-list
[Top] [All Lists]

Re: [xsl] Legibility, repetition, nesting

2020-07-20 12:32:05
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: 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>