W3C home > Mailing lists > Public > public-qt-comments@w3.org > March 2003

RE: result-document from a temporary tree

From: Andre Cusson <ac@hyperbase.com>
Date: Thu, 27 Mar 2003 15:58:19 -0500
To: "Kay, Michael" <Michael.Kay@softwareag.com>, public-qt-comments@w3.org
Cc: michael.h.kay@ntlworld.com
Message-id: <5.2.0.9.0.20030327142146.00a7c250@localhost>

Hi,

Thank you for a great reply.

Iteratively processing the nodeset seems very costly, especially if you 
have many files to potentially generate for each node. For example, if some 
pages are generated when some conditions occur, one might have to reprocess 
the nodeset many times and if the nodeset is large and if you have many 
users doing this, in many applications, ... it is going to bomb ... sooner!

On the other hand, the higher-order functions are interesting.  I already 
use them in different contexts but I think that it is an interesting way to 
get around the problem. It is a bit more twisted but the gain in 
performance and in abstraction may be worth it.  On second thought though, 
in reality, since makepage is called from 50 to 100 different processes in 
the application, it means that I will have about 100 additional templates 
(and mode) and I have to pass parameters to these templates, some of them 
very large.(true, I could extract and pass only what is required to limit 
size but that means that the processing logic has to be split between 
different templates) that is a lot of parameter passing.  Now, if I 
understand well, parameters will have to be passed as attributes of the 
template proxy node, to the makepage template.  This seems possibly 
feasible but non-trivial and the performance gain from not building the 
page temporary tree will probably be offset by the cost of the 
parameter/attribute passing and the additional template 
invocations.  Finally, the program clarity will also probably be affected 
negatively. Although I like the higher-order functions idea, I am not 
convinced that this is the better use of them.  It all seems like a lot of 
work to loose some clarity and maybe efficiency.

For your suggestion that if I would use

<xsl:if test="some condition">
   <xsl:copy-of select="$content"/>
</xsl:if>

instead of

<xsl:copy-of select="$content"/>

I may be faced with dangling references : absolutely, but I would not, 
unless I check for it later (or accept to pay the price to debug it and 
learn the lesson not to forget about it next time, but that is done already 
...;-)

As for the standard, I still feel that the gain (limiting side-effects) is 
not really worth the constraint (limiting recursion).
Of course, I might not have considered all aspects of this.

Although it is expensive, I understand that there are ways to get around 
the problem caused by the new constraints on recursion.
The higher-order functions seems like the most interesting so far.
I will keep looking into it.

I hope the the WG will reconsider.

I thank you for your time, consideration and great help and I whish you the 
best.

Regards,
Andre Cusson
ac@hyperbase.com
01 Communications Inc.

PS: The example I provided is very simple compare to the real world cases 
that I have, where, for example, makepage has 25 parameters and the page 
content parameter that it receives is the result of a sophisticated merge 
of various contents into (nested) XML layout definitions.  The application 
currently has 20K lines of (tight) XSLT.  The impact of a change like the 
result-document can not even be compared with using the Saxon 
extensions.  The extensions are easy to migrate and some of them are now 
even part of the standard.  The change on result-document affects to global 
design.  Very messy.




At 05:18 PM 3/27/2003 +0100, Kay, Michael wrote:
>Thanks for supplying the example, which I think I now understand.
>
>As far as I can see, the main controlling iteration of your stylesheet,
>namely:
>
><xsl:template name="invoicing">
>      <xsl:param name="source"/>
>      <xsl:for-each select="$source/*">
>          <xsl:call-template name="makepage"><!-- TOC (ex: invoicing report
>page-->
>              <xsl:with-param name="content">
>                  <xsl:for-each select="$clients">
>                      <p style="font-weight: bold;"><!-- TOC link to mailing
>-->
>                          <a href="{concat($path, @id,
>'html')}"><xsl:value-of select="@id"/></a>
>                      </p>
>                      <xsl:call-template name="envelope"><!--mailing page-->
>                          <xsl:with-param name="client-id" select="@id"/>
>                      </xsl:call-template>
>                      <xsl:for-each
>select="$outstanding-invoice-for-this-client">
>                          <xsl:call-template name="invoice"><!--invoice
>page-->
>                               <xsl:with-param name="invoice-id"
>select="@id"/>
>                          </xsl:call-template>
>                              <p><!-- TOC link to invoice -->
>                                  <a href="{concat($path, @id,
>'html')}"><xsl:value-of select="@id"/></a>
>                              </p>
>                      </xsl:for-each>
>                  </xsl:for-each>
>              </xsl:with-param>
>          </xsl:call-template>
>      </xsl:for-each>
></xsl:template>
>
>can be rewritten as:
>
><xsl:template name="invoicing">
>      <xsl:param name="source"/>
>      <xsl:for-each select="$source/*">
>          <xsl:call-template name="makepage"><!-- TOC (ex: invoicing report
>page-->
>              <xsl:with-param name="content">
>                  <xsl:for-each select="$clients">
>                      <p style="font-weight: bold;"><!-- TOC link to mailing
>-->
>                          <a href="{concat($path, @id,
>'html')}"><xsl:value-of select="@id"/></a>
>                      </p>
>                      <xsl:for-each
>select="$outstanding-invoice-for-this-client">
>                          <p><!-- TOC link to invoice -->
>                              <a href="{concat($path, @id,
>'html')}"><xsl:value-of select="@id"/></a>
>                          </p>
>                      </xsl:for-each>
>                  </xsl:for-each>
>              </xsl:with-param>
>          </xsl:call-template>
>          <xsl:for-each select="$clients">
>            <xsl:call-template name="envelope"><!--mailing page-->
>              <xsl:with-param name="client-id" select="@id"/>
>            </xsl:call-template>
>            <xsl:for-each select="$outstanding-invoice-for-this-client">
>              <xsl:call-template name="invoice"><!--invoice page-->
>                   <xsl:with-param name="invoice-id" select="@id"/>
>              </xsl:call-template>
>            </xsl:for-each>
>          </xsl:for-each>
>      </xsl:for-each>
></xsl:template>
>
>and it will no longer violate the rule against writing final trees during
>the writing of a temporary tree. Although this involves iterating over
>$clients twice, this seems a more natural solution to me than trying to
>produce two (or even three) different outputs during one iteration. This is
>the structure you would have to use if all the final documents were subtrees
>of some composite single result tree, and the processing model we want to
>use is essentially of this form (indeed, at one stage we did consider
>defining "multiple result documents" as essentially a method of serializing
>a single composite result tree.
>
>You are obviously attached to a rather different processing model. To me,
>your code has the basic problem that it relies on an output document being
>written as a side-effect of computing the value of a parameter. What would
>happen if, for example, your "makepage" template instead of doing;
>
><xsl:copy-of select="$content"/>
>
>did
>
><xsl:if test="some condition">
>   <xsl:copy-of select="$content"/>
></xsl:if>
>
>There would then be circumstances in which the parameter $content is not
>used by the called template. With lazy evaluation, when a parameter is not
>used, it's quite likely that it isn't going to be evaluated, so it becomes
>undefined whether the <xsl:result-document> will ever be executed, and the
>final result of the transformation then becomes implementation-dependent.
>This is precisely why we introduced this restriction in the specification.
>
>I don't feel that this solution to this problem is an unreasonable one,
>though I accept that you've probably become rather locked in to the more
>flexible approach offered by the extensions in earlier releases of Saxon and
>other products offering this facility.
>
>I have to say that my preferred solution would be that instead of passing
>the makepage template a parameter containing the content of the page, it
>should be passed a function (or template) to generate this content, making
>it effectively a higher-order function. Although XSLT 2.0 doesn't provide
>higher-order functions directly, Dimitre Novatchev has shown how to simulate
>them. Essentially you would pass your makepage template a single element
>node as a parameter, and the template would call apply-templates on that
>node, typically in a special mode. The element node that you pass thus
>determines the template that is called to populate the page: in effect, the
>element node acts as a surrogate for a template, so you are effectively
>passing one template as a parameter to another. This design would avoid the
>creation of temporary trees entirely, and might therefore be much more
>efficient in its memory usage.
>
>Regards,
>
>Michael Kay
Received on Thursday, 27 March 2003 15:36:46 GMT

This archive was generated by hypermail 2.2.0+W3C-0.50 : Tuesday, 27 March 2012 18:14:24 GMT