Re: [xsl] Is XPath and/or XSLT designed such that I should never have to write special case code?

Subject: Re: [xsl] Is XPath and/or XSLT designed such that I should never have to write special case code?
From: "Eliot Kimber ekimber@xxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Tue, 22 Jun 2021 18:36:05 -0000
If I understand what you mean by bspecial case codeb I think you really
mean bhandling edge cases in a one-off or clunky kind of wayb.



With XSLT, if you take the general approach of doing as much as possible with
templates then handling special cases is usually a matter of having templates
that match on all *distinct* cases and also providing appropriate fallback
processing. I think thatbs fundamentally different from having code *within
a template* that uses a condition check to handle a special case.



In the case of your ancestry-reporting code, you could have done that easily
with templates and tunnel parameter that provides the starting node (so you
can generate the bgrandparent-*b string) or the equivalent.



XSLT says bI canbt predict what I *might* get but I know what I *expect*
and I can handle all of those cases using the same fundamental technique:
template matching.



Along those lines, I usually have a catch-all template in each mode that will
be handling arbitrary input to report things that fell through and were
therefore not properly handled. That tells me when my code is complete over my
known input documents (at least as far simply handling each relevant different
case goes).



Within functions that do more involved processing, I either use normal
recursive processing with the usual bstop recursing and returnb check or
delegate to templates from the function.



The xsl:iterate instruction provides a new place where you might need
bspecial caseb processing, but I think that essentially becomes the same
as for recursive functions: you always need a bstop iterating nowb check
of some sort (otherwise youbd just use template matching or for-each (in the
rare cases where for-each is appropriate)).



In practice I do sometimes find myself using xsl:if or xsl:choose as an
expedience instead of using the more appropriate template-based logic when
Ibm in a hurry or the effort simply isnbt justified by the current code.
But usually I regret that later and end up putting in the templates.



As others have mentioned, you can also avoid special cases by using a
multi-stage pipeline that normalizes the data in whatever way is needed to
eliminate special cases. That creates a clearer separation of concerns and
simplifies the logic of the follow-on processing.



Cheers,



Eliot



--

Eliot Kimber

http://contrext.com







From: "Roger L Costello costello@xxxxxxxxx"
<xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Reply-To: <xsl-list@xxxxxxxxxxxxxxxxxxxxxx>
Date: Tuesday, June 22, 2021 at 12:03 PM
To: "xsl-list@xxxxxxxxxxxxxxxxxxxxxx" <xsl-list@xxxxxxxxxxxxxxxxxxxxxx>
Subject: [xsl] Is XPath and/or XSLT designed such that I should never have to
write special case code?



Hi Folks,



I think special case code is evil.



To explain what I mean by "special case code" let's take its opposite: code
selects what is desired under any condition.



So, by "special case code" I mean extra code that is written for dealing with
special conditions.



Last week I posted the following XPath expression to fetch the <Row> element
where Cell[1]/Data equals $element and Cell[2]/Data equals $parent.



$document/Row[Cell[1]/Data eq $element][Cell[2]/Data eq $parent]



However, when $parent is empty, the XPath expression fails.



I was all set to write special case code:



<xsl:if test="empty(Cell[2]/Data)"> do something </xsl:if>



Bad, bad, bad.



But then Mukul showed me an XPath expression that works correctly -- whether
$parent is empty or not -- without any special case code:



$document/Row[Cell[1]/Data eq $element][Cell[2]/string(Data) eq $parent]



Awesome!



Today I was writing some XSLT to generate a bunch of rows showing, for each
element in an XML document, its name, the name of its parent, the name of its
grandparent, and the name of its great-grandparent:



<xsl:template match="*">

    <row>

        <element><xsl:value-of select="name(.)"/></element>

        <parent-element><xsl:value-of select="name(..)"/></parent-element>

        <grandparent-element><xsl:value-of
select="name(../../..)"/></grandparent-element>

        <great-grandparent-element><xsl:value-of
select="name(../../../..)"/></great-grandparent-element>

    </row>

    <xsl:apply-templates select="*" />

</xsl:template>



Obviously as the XSLT traverses through an XML document some elements don't
have a great-grandparent or a grandparent or even a parent. But I didn't need
to write special case code to check those conditions. That is terrific!



Question #1: is XPath and/or XSLT designed such that I should never have to
write special case code?



Question #2: If I find myself writing special case code, should I stop and
say, "How can I modify this XPath and/or XSLT so that I do not have to write
special case code?



/Roger

Current Thread