xsl-list
[Top] [All Lists]

Re: [xsl] best practices for using XSLT modes

2019-12-05 08:51:03
Not really about modes, but I would replace the choice that acts on different 
@val values with templates applied to the @val attribute, i.e.:

        <xsl:template match="a">
          <val><xsl:apply-templates select="@val"/></val>
       </xsl:template>

     <xsl:template match="@val[. ge 0]">
        <xsl:value-of select="@val || ': positive'"/>
    </xsl:template>

     <xsl:template match="@val[. lt  0]">
        <xsl:value-of select="@val || ': negative"/>
    </xsl:template>

Note that I handle the bug in the original in that it would produce no result 
when @val is "0" (zero).

The use of templates rather than xsl:choose makes the code cleaner, I think, 
puts the focus at the template level on the @val attribute, which is the focus 
of the business logic, and enables extension and override. For example, if you 
want a value of exactly zero to have a different result, you could do that by 
adding an override template. The original use of xsl:choose would require 
overriding the entire template for the <a> element.

You could make this use modes by putting the @val templates in a specific mode 
rather than in the default mode as I have it, which might be appropriate if 
this handling of @val was neither universal nor limited to just the <a> element 
(if it was just the <a> element you could just add that to the match 
expression).

Cheers,

E.
--
Eliot Kimber
http://contrext.com
 

On 12/4/19, 11:54 PM, "Mukul Gandhi gandhi(_dot_)mukul(_at_)gmail(_dot_)com" 
<xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com> wrote:

    Hi Mike,
    
    
    On Wed, Dec 4, 2019 at 4:14 PM Michael Kay mike(_at_)saxonica(_dot_)com 
<xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com> wrote:
    
    
    ([mukul] I assume, you mean 'mode' here) helps to modularise the logic, and 
in particular, for someone reading the code, if apply-templates uses a specific 
mode then it reduces the effort needed to find the template rules that might 
get invoked -- which is a significant part of the effort of debugging 
stylesheets.
    
    
    
    
    In fact, this was the reason why I wrote an example mentioning modes. 
Thanks for the explanation.
     
    
    then you wonder whether a conditional (e.g. xsl:choose) might not be more 
appropriate.
    
    
    
    
    In fact, I had a third example in my mind as well where I wanted to use 
xsl:choose to produce a similar result. Its mentioned below (this is schema 
aware, and I use the Saxon option -val:strict),
    
    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                             xmlns:xs="http://www.w3.org/2001/XMLSchema";
                             exclude-result-prefixes="xs"
                             version="3.0">
                    
        <xsl:output method="xml" indent="yes"/>
        
        <xsl:import-schema>
           <xs:schema>
                 <xs:element name="root">
                    <xs:complexType>
                        <xs:sequence>
                             <xs:element name="a" maxOccurs="unbounded">
                                 <xs:complexType>
                                     <xs:attribute name="val" 
type="xs:integer"/>
                                 </xs:complexType>
                             </xs:element>
                        </xs:sequence>
                  </xs:complexType>
                </xs:element>
           </xs:schema>
        </xsl:import-schema>
        
        <xsl:template match="root">
           <result>
              <xsl:apply-templates select="a"/>          
           </result>
        </xsl:template>
        
        <xsl:template match="a">
          <xsl:choose>
            <xsl:when test="@val gt 0">
              <val><xsl:value-of select="@val"/>: positive</val>
            </xsl:when>
            <xsl:when test="@val lt 0">
              <val><xsl:value-of select="@val"/>: negative</val>
            </xsl:when>
          </xsl:choose>
        </xsl:template>
        
    </xsl:stylesheet>
    
    The above stylesheet, when given the same input XML, produces output,
    
    <result>
       <val>-1: negative</val>
       <val>-4: negative</val>
       <val>5: positive</val>
       <val>3: positive</val>
       <val>2: positive</val>
    </result>
    
    (The order of "val" elements in this output, is different than what were 
produced by my first two stylesheets. This could be fixed, if required)
     
    
    An interesting recent experience: we have a test driver for running XSLT 
tests, that's written in XSLT. The test assertions might take the form:
    
          <result>
             <assert>/res = 'Success'</assert>
          </result>
    
    or
    
          <result>
             <any-of>
                <assert>/res = 'Success'</assert>
                <error code="XTSE0020"/>
             </any-of>
          </result>
    
    
    Now, firstly, we use a mode for evaluating assertions, that's separate from 
the mode used for processing other things in the test catalog. A good reason 
for that is that all the template rules in that mode return a boolean 
(indicating test success of failure), and the apply-templates call has to know 
that a boolean result is expected. The rules in a mode have to have equivalent 
pre- and post- conditions in terms of things like the expected parameters and 
the required return type, because they are interchangeable as far as the caller 
is concerned.
    
    Secondly, I found it useful recently to split the mode for evaluating 
assertions into two: one mode handles the case where the test produces a normal 
result, the other handles the case where it produces a dynamic error, and we 
issue a different apply-templates instruction for the two cases. The reason for 
this is that the two modes have different default behaviour (the mode that 
handles error outcomes returns "false" for all assertions except the one with 
match="error"): this change eliminated a lot of logic. Perhaps the same effect 
could have been achieved using a generic template rule delegating to specific 
template rules using next-match; but in this scenario where we're basically 
handling a two-dimensional decision tree (X - what is the outcome of a test?, Y 
- what is the assertion being tested?) then using modes for one of the 
dimensions and match patterns for the other can be useful.
    
    
    
    
    
    Thanks, for sharing these experiences. Its enlightening to know.
     
    
    if you're writing complex stylesheets, modes are a powerful tool at your 
disposal and can be used with care to great effect.
    
    
    
    
    
    I agree.
     
    
     
    
    
    -- 
    Regards,
    Mukul Gandhi
    
    
    
    
    XSL-List info and archive 
<http://www.mulberrytech.com/xsl/xsl-list>EasyUnsubscribe 
<http://lists.mulberrytech.com/unsub/xsl-list/1278982>
    (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>