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

Subject: [xsl] Re: How to output open/close tags independently?
From: "Edward L. Knoll" <ed.knoll@xxxxxxxxxxxxxx>
Date: Mon, 30 Dec 2002 15:44:55 -0700
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.  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


Current Thread