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: Wed, 26 Mar 2003 16:32:32 -0500
To: saxon-help@lists.sourceforge.net, public-qt-comments@w3.org
Cc: michael.h.kay@ntlworld.com
Message-id: <5.2.0.9.0.20030326154619.03162b88@localhost>

At 01:39 PM 3/10/2003 +0000, you wrote:

I had a word with my colleagues on the WG about this (though not on the
official agenda) and could find little support for relaxing the current
rule. There was a general feeling that outputting a result document
while producing a temporary tree is a side-effect and should not be
allowed; also that it should be possible to achieve the required effect
without doing this.

If you could construct an example, preferably simplified, that shows why
you need to do this, it would be most helpful. I know you have sent me
code in the past, but I don't think it was a complete stylesheet that I
could work with.

Michael Kay




Hi,

The way I see this, it is a very simple case of recursive traversal of a 
nodeset.
I believe that the example that I sent already had everything required to 
reproduce the situation.

As for the use-cases, I tried to give you a few examples of where/how we 
use it.
To do more, I would have to show you the real code where we use it.
I would be happy to do that if I new that I wasn't throwing proprietary 
code out in the open.
Is there a way of doing this securely ?

Of course I could also rework the code, build another application so that 
it does not need to be protected but I feel that it probably is not worth 
the effort since if you cannot see the simplicity, basicness and straight 
forwardness of the case from a simple example I doubt that a more elaborate 
one would help.  And if it would, a set of real world applications would 
probably be best.  But I need to protect the IP and source for the people here.

As for getting the same results some other way, it is surely possible, I 
could even do it in Java or any other language that supports 
recursion.  Alternatively, I could also completely redesign the application 
and try to do something that is inherently simple and natural in a more 
complex way but the price to pay in redesign and performance does not 
attract me at this point (although some day I may not have any other 
choice.  At that point, I will also have to take a look at up coming 
alternatives to XSLT, like STX).

Still, I am puzzled that something so basic and fundamental does not 
register with the WG and others.
Does everybody agree that "XSLT 2.0 does not support output of multiple 
pages (files) in recursive traversal of node sets, in pull processing" ?
For me, it is a very powerful design tool, in pull processing.  Some 
problems are better resolved by push processing, but others by pull.
I like and use both ..., up to XSLT 2.0 !

Nevertheless, I will try again here with a simplified example/use-case that 
works ok in XSLT1.1 but not anymore in XSLT2.0 :

The node set being traversed contains information to be processed and 
mapped to html pages (can't output everything to just one page/file).  As 
the application traverses the information in the node set, it builds a page 
and that page links to sub-pages generated from further traversing and 
processing the node set, and so on, recursively, until the node set has 
been completely traversed and no more pages need to be generated.

So, for example, let's say we have a template called 'makepage' that 
renders one page to html, using result-document.  We are going to call it 
every time that we have gathered the data for a page, as we are traversing 
the node set.  For our example here, we will try to do invoicing, that is 
to produce outstanding invoices for many customers (let's say, at the end 
of the month, for example).  Here, we want one html page with links to each 
of the invoices (and envelopes) produced, as a table of content and one (or 
more) html page per invoice produced.  For every customer for which we are 
generating an invoice, we also need to generate another html page with the 
corresponding mailing label/envelope, also providing a link to this page on 
our TOC page.  Also, because we want to stream data as much as possible, we 
want to avoid reprocessing the nodeset multiple times. So,

we define a template called makepage to render a page data to html, 
something like :

<xsl:output name="output-format" .../>

<xsl:template name="makepage">
         <xsl:param name="content"/>
         <xsl:param name="filename"/>
         <xsl:result-document href="{concat($filename, 'html')}" 
format="output-format">
                 <html>
                         <head>
                                 <title>
                                         <xsl:value-of select="$filename"/>
                                 </title>
                         <body>
                                 <xsl:copy-of select="$content"/>
                         </body>
                 </html>
         <xsl:/result-document>
</xsl:template>

then, assuming that we have a template called 'get-client-address' that 
simply outputs the address for a given client, we define a template to 
build a mailing label like :

<xsl:template name="envelope">
         <xsl:param name="client-id"/>
         <xsl:call-template name="makepage">
                 <xsl:with-param name="filename" select="concat('mail-', 
$client-id)"/>
                 <xsl:with-param name="content">
                         <table>
                                 <tr>
                                         <td align="top">
                                                 <xsl:copy-of select="$logo"/>
                                         </td>
                                         <td align="bottom">
                                                 <xsl:call-template 
name="get-client-address">
                                                         <xsl:with-param 
name="client" select="$client-id"/>
                                                 </xsl:call-template>
                                         </td>
                                 </tr>
                         </table>
                 </xsl:with-param>
         </xsl:call-template>
</xsl:template>

then, we need a template to generate the body for an invoice, like :

<xsl:template name="invoice">
         <xsl:param name="invoice-id"/>
         ...
         <xsl:call-template name="makepage">
                 <xsl:with-param name="filename" select="$invoice-id"/>
                 <xsl:with-param name="content">
                         <table>
                                 ...
                         </table>
                 </xsl:with-param>
         </xsl:call-template>
         ...
</xsl:template>

and finally, the invoicing template that traverses the source node set, like :

<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:wiith-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>

Of course, this is a simplified use-case and example but if processed in 
XSLT2.0, an error will be generated on the result-document line of the 
'makepage' template, every time an invoice is requested and every time an 
envelope is requested.

I hope that this example is useful and that I am not alone in thinking that 
recursion, whether in push or pull processing is fundamental to node set 
traversal, and not a side-effect.

Whether the output is to a single file or multiple file should not change 
anything and is in fact imposed by standards like HTML (and by the physical 
world in which applications operate).

In our application, we have many cases for this as I have already pointed 
out, including invoicing, OR-mapping, compound document processing, etc. 
The basic issue is always the same.

Again, I hope that this helps.
Thank you for your time and consideration.
Regards,

Andre Cusson
ac@hyperbase.com
01 Communications Inc.

PS: come to think of it, simply building a table of contents as one is pull 
processing the pages of a document is a typical use of result-document from 
a temporary tree.

PSS: the same issue could come up in push processing also, especially when 
required to pass parameters in apply-templates.  It just seems natural in 
pull though.
Received on Wednesday, 26 March 2003 16:10:45 GMT

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