xsl-list
[Top] [All Lists]

Re: [xsl] best practices for using XSLT modes

2019-12-04 23:54:44
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/1167547
or by email: xsl-list-unsub(_at_)lists(_dot_)mulberrytech(_dot_)com
--~--
<Prev in Thread] Current Thread [Next in Thread>