RE: [xsl] Re: How to output open/close tags independently?

Subject: RE: [xsl] Re: How to output open/close tags independently?
From: "Michael Kay" <michael.h.kay@xxxxxxxxxxxx>
Date: Tue, 31 Dec 2002 10:04:46 -0000
> Not that I'm picking on you specifically Wendell, but your 
> reply was the most blatantly representative of a class of 
> responses of a particularly XSL purist/snobbish nature which 
> I find extremely objectionable.

I get the impression you are using "purist" and "snobbish" as synonyms,
which suggests you dislike purism per se. This is unfortunate. We need
more engineering discipline in software development, not less.

The objection to disable-output-escaping is that it violates an
architectural boundary, namely the boundary between transformation and
serialization. Violating architectural boundaries can often give you a
performance gain, often quite a significant one, but it invariably
incurs a significant cost in terms of the longevity of your software.

We don't know the requirements of your application so we don't know what
the right trade-offs are. The reason that experienced software
architects usually criticize designs that sacrifice software longevity
in favour of speed is that such a tradeoff is usually made without a
proper analysis of the lifetime cost-benefits. This is not snobbishness,
it is wisdom that comes from experience.

As for your performance problem, it appears that Xalan C++ does not
optimize the construct:

       select='.|following-sibling::gnsl:Row[$RowsPerPage >
position()]'>

That is, it doesn't recognize that it only needs to look at the next
$RowsPerPage elements. It might be worth trying a different processor.
Alternatively, you could improve performance by using a key, indexing
Rows according to the value of [position() mod $RowsPerPage]. 

When the need comes to optimize an application, it is always best to do
this without breaking architectural boundaries if you possibly can; and
in this case, you almost certainly can.

Michael Kay
Software AG
home: Michael.H.Kay@xxxxxxxxxxxx
work: Michael.Kay@xxxxxxxxxxxxxx 


  There was a reply from a 
> Mitch Amiano which actually supplied a suggested approach 
> which "appeared" entirely reasonable, so tried it out.  I've 
> included the core XSL for both approaches below: the "bad" 
> code which had the 'disable-output-escaping' clause and the 
> "good" code which generated the Page element directly.  
> Following are my performance numbers on a test input file 
> which had 22,004 Row elements and was 13,425,501 bytes large 
> (the time output is from the Unix time(1)
> command):
> 
> For the "good" (XSLT-correct) approach:
>   real  2:41:32.6
>   user  2:31:57.0
>   sys         1.9
> 
> For the "bad" (d-o-e) approach:
>   real     1:38.4
>   user     1:31.8
>   sys         1.0
> 
> The "good" approach took hours; the "bad" approach took 
> minutes.  For those that will care, the test environment was 
> a Sun Solaris platform using the interim release of the Xalan 
> C++ 1.4 XSLT processor.
> 
> I'm just curious, do those of you with this hard-line 
> "purist" attitude actually use XSL to do real work or are you 
> mostly academics and tool developers/vendors?  I understand 
> staying true to a paradigm up to a point, but sooner or later 
> "the rubber has to hit the road". 
> 
> Regards,
> Ed Knoll
> 
> p.s. This is not all of the XSL, just the differences.
> 
> 
> ---- "Good" XSL ------------------------------
> 
> <xsl:variable name='PageFirstRows'
>         select='/gnsl:Results/gnsl:Table/gnsl:Row[
>                                         (position() mod 
> $RowsPerPage) = 1]' />
> 
> <xsl:template match="gnsl:Table">
>    <xsl:copy>
>       <xsl:copy-of select="@*" />
>       <xsl:apply-templates select="gnsl:Columns" />
> 
>       <xsl:choose>
>          <xsl:when test="gnsl:Row">
>             <xsl:apply-templates select='$PageFirstRows' />
>          </xsl:when>
>          <xsl:otherwise>
>             <xsl:element name='Page' />
>          </xsl:otherwise>
>       </xsl:choose>
>    </xsl:copy>
> </xsl:template>
> 
> <xsl:template match="gnsl:Row">
>    <xsl:element name="Page">
>       <xsl:for-each
>            select='.|following-sibling::gnsl:Row[$RowsPerPage 
> > position()]'>
>          <xsl:call-template name='CopyAll' />
>       </xsl:for-each>
>    </xsl:element>
> 
> 
> ---- "Bad" XSL ------------------------------
> 
> <xsl:template match="gnsl:Table">
>    <xsl:copy>
>       <xsl:copy-of select="@*" />
>       <xsl:apply-templates select="gnsl:Columns" />
>       <xsl:choose>
>          <xsl:when test="gnsl:Row">
>             <xsl:apply-templates select="gnsl:Row" />
>          </xsl:when>
>          <xsl:otherwise>
>             <xsl:value-of select="$LineBreak" />
>             <xsl:text 
> disable-output-escaping="yes">&lt;Page/&gt;</xsl:text>
>             <xsl:value-of select="$LineBreak" />
>          </xsl:otherwise>
>       </xsl:choose>
>    </xsl:copy>
> </xsl:template>
> 
> <xsl:template match="gnsl:Row">
>    <xsl:if test="(position() mod $RowsPerPage) = 1">
>       <xsl:if test="position() != 1">
>          <xsl:value-of select="$LineBreak" />
>          <xsl:text 
> disable-output-escaping="yes">&lt;/Page&gt;</xsl:text>
>          <xsl:value-of select="$LineBreak" />
>       </xsl:if>
>       <xsl:value-of select="$LineBreak" />
>       <xsl:text disable-output-escaping="yes">&lt;Page&gt;</xsl:text>
>       <xsl:value-of select="$LineBreak" />
>    </xsl:if>
> 
>    <xsl:call-template name="CopyAll" />
> 
>    <xsl:if test="position() = last()">
>       <xsl:value-of select="$LineBreak" />
>       <xsl:text disable-output-escaping="yes">&lt;/Page&gt;</xsl:text>
>       <xsl:value-of select="$LineBreak" />
>    </xsl:if>
> </xsl:template>
> 
> 
> > Hey Mitch,
> > 
> > The horribleness of disable-output-escaping is not (to my 
> mind) really 
> > an
> > issue of the well-formedness constraint either in the 
> stylesheet or in the 
> > output -- that's something of a red herring (though it is a 
> risk and a sign 
> > of the deeper problem). Rather, it's the violation of 
> XSLT's processing 
> > model, in which the transformation of the node tree and the 
> > post-transformation serialization are clearly distinguished 
> and kept 
> > separate by design. *Any* solution that works by writing 
> markup to output 
> > using d-o-e creates a dependency on the serialization step. 
> While this may 
> > be acceptable in certain circumstances (e.g. writing SGML 
> entity references 
> > to output that are not otherwise provided for, when you 
> *know* you're going 
> > to write a file), it's horrible at other times, if only because the 
> > designer has created this dependency unwittingly, and thus doesn't 
> > understand why the transform breaks in a conformant 
> architecture, like 
> > Mozilla or transformation chains in Cocoon, where no file 
> is getting 
> > serialized.
> > 
> > The relevance of grouping is only that the "write markup" 
> approach is
> > usually resorted to by newer XSLT programmers who don't 
> know how else to do 
> > grouping, and who fall back on their Perl or Javascript 
> experience (or just 
> > sheer ingenuity) to suppose that writing markup is the best or only 
> > solution to the problem (it is neither).
> > 
> > I doubt that any experienced XSLTer would have a problem 
> with either 
> > of the
> > solutions you offered (or Dimitre's, or Tom's), since none of them 
> > introduce the dependency on serialization that is the problem with 
> > d-o-e-based techniques for "outputting open/close tags 
> independently". 
> > There the distinctions are much more of coding style and 
> performance; but 
> > none of them use a technique that is prone to break the 
> minute you move 
> > your stylesheet into a different environment.
> > 
> > Cheers,
> > Wendell
> 
> 
> -- 
> Edward L. Knoll   Phone (work)     : (719)484-2717
>                   e-mail (work)    : ed.knoll@xxxxxxxxxxxxxx
>                   e-mail (business): eknoll@xxxxxxxxxx
>                   e-mail (personal): edward@xxxxxxxxxxx
> 
>  XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
> 


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread