[Bug 25174] New: Buffering with xsl:try wrapped around xsl:stream or xls:result-document

https://www.w3.org/Bugs/Public/show_bug.cgi?id=25174

            Bug ID: 25174
           Summary: Buffering with xsl:try wrapped around xsl:stream or
                    xls:result-document
           Product: XPath / XQuery / XSLT
           Version: Last Call drafts
          Hardware: PC
                OS: Windows NT
            Status: NEW
          Severity: normal
          Priority: P2
         Component: XSLT 3.0
          Assignee: mike@saxonica.com
          Reporter: abel.braaksma@xs4all.nl
        QA Contact: public-qt-comments@w3.org

This bug report is a result of [1] and the response from the working group in
[2]. The relevant quotes from the latter (minutes of 13 March 2014) are:

Key example (edited to be valid):
<xsl:try>
    <xsl:stream href="foo.xml">
        <xsl:apply-templates mode="streaming"/>
    </xsl:stream>
    <xsl:catch />
</xsl:try>


Key issue: 
xsl:try requires stable roll-back in case an error occurs that is caught by
xsl:catch, even if that error is right at the beginning, i.e. when trying to
read the source document.

Quotes from the minutes:
"ABr: but if you only want to catch a failure in opening the document, you've
incurred the buffering cost for no benefit. And there's nowhere else to put the
xsl:try in this case."

"MK: yes, it would be nice to recover from a failure opening the input, without
having to buffer all the output."

"MK: this would suggest solution (3), an on-error output, but not sure how we
would define the semantics. Basically, catching errors that occur before any
output is written."

Suggested solutions (mark #3)
(1) disallow non-motionless expressions in xsl:try, which forces the programmer
to do a copy prior to the xsl:try
(2) define an extra attribute on xsl:output to make rollback behavior on
xsl:try optional
(3) make errors on xsl:stream uncatchable, or catchable only by a special
attribute "on-error"
(4) disallow xsl:stream inside xsl:try


-------------------------------------------------------

The issue with xsl:try wrapped around xsl:stream effectively prevents (output)
streaming, because the whole output is required to be buffered. This is not a
problem if the result set is small, but if it is not, it will blow up
streamability. 

The same issue occurs when xsl:try is wrapped around xsl:result-document, with
one difference, the processor is not required to leave the result document in a
stable state, i.e., it is possible to start writing output to a result document
and _not_ rollback in case an error is raised. But this is not ideal either, as
the user will be left with an uncertain state.

Suggestion #3
The suggested resolution #3 above introduces a new attribute on xsl:stream,
on-error, which could take an expression. The special variables defined under
[3], like err:code and err:description are available inside this expression.
Example:

<xsl:stream href="foo.xml" on-error="my:report($err:code)">
    <xsl:apply-templates mode="streaming"/>
</xsl:stream>

There is one additional drawback here, however. The special variables in the
err: namespace are currently lexically scoped (see [3]), which means you will
have to pass each error variable. A solution to this is to (also) allow the
errors to be available as a map (as in $err:bag or $err:map), which gives
advantages in this scenario and related scenarios, or to allow the special
variables to be dynamically scoped, comparable to current-group. In the latter
case you can write:

<xsl:template match="/">
    <xsl:stream href="foo.xml" on-error="my:report-errors()">
        <xsl:apply-templates mode="streaming"/>
    </xsl:stream>
</xsl:template>

<xsl:function name="my:report-errors">
   <xsl:message select="$err:description" />
</xsl:function>

If we decide, however, to keep the current scope and variables for err:xxx, but
we adopt static AVTs from [4], there is another way out for programmers to
write this more effectively:

<xsl:variable name="errorhandler"
    select="'my:report-errors($err:code, $err:description, $err:value)'"
    static="yes" />

<xsl:template match="/">
    <xsl:stream href="foo.xml" on-error="{$errorhandler}">
        <xsl:apply-templates mode="streaming"/>
    </xsl:stream>
</xsl:template>

<xsl:function name="my:report-errors">
   <xsl:param name="errcode" />
   ....
   <xsl:message select="$errcode" />
   ....
</xsl:function>

IMO it is hard not to get enthusiastic about static AVTs, it seems to open up a
whole new level of abstraction through preprocessing macros, that can greatly
reduce many typical use-cases (but that's another subject, again, see [4]).

Semantics for on-error: it will only catch errors that occur prior to starting
reading the document, perhaps up until the root node, which is in line with
current rules (somewhere we say that buffering of DTD and opening comments etc
is required in streaming). Other errors ought to be caught the normal way,
using more fine-grained xsl:try/xsl:catch.

I propose to adopt this for xsl:stream and xsl:result-document, in the latter
only to catch errors occurring from first attempt to writing the result
document.

Recovery actions: when on-error is defined and called, we might introduce a
return value true/false that determines whether further processing should take
place or not, or add one more attribute: on-error-terminate="yes|no". We may
also decide on whether the result of on-error becomes part of the current
result tree or not.

See also: bug 25173.


[1] https://lists.w3.org/Archives/Member/w3c-xsl-wg/2014Mar/0012.html
[2] https://lists.w3.org/Archives/Member/w3c-xsl-wg/2014Mar/0014.html
[3] https://www.w3.org/TR/xslt-30/html/Overview.html#element-try
[4] https://www.w3.org/Bugs/Public/show_bug.cgi?id=24619

-- 
You are receiving this mail because:
You are the QA Contact for the bug.

Received on Thursday, 27 March 2014 13:12:24 UTC