Subject: Re: [xsl] XSLT 3.0 try/catch doubts From: "Mukul Gandhi gandhi.mukul@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> Date: Mon, 25 Feb 2019 09:58:42 -0000 |
Hi Mike, Thanks for a detailed explanation about my XSLT use case. I've now tried new ways of using XSLT try/catch syntax, and below are my new examples where try/catch appear to be more useful in the context of my examples. I'm using Saxon 9.9. Input XML: <?xml version="1.0" encoding="UTF-8"?> <test> <val>5</val> <val>4</val> <val>3</val> <val>0</val> <val>2</val> <val>0</val> <val>1</val> </test> Stylesheet 1: <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:err="http://www.w3.org/2005/xqt-errors" xmlns:fn="http://xslt-functions" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="err fn xs" version="3.0"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/"> <result> <xsl:for-each select="test/val"> <xsl:copy-of select="fn:div(5, ., position())"/> </xsl:for-each> </result> </xsl:template> <xsl:function name="fn:div" as="element()"> <xsl:param name="numerator" as="xs:integer"/> <xsl:param name="denominator" as="xs:integer"/> <xsl:param name="pos" as="xs:integer"/> <xsl:try> <xsl:sequence> <div num="{$numerator}" denom="{$denominator}"><xsl:value-of select="$numerator div $denominator"/></div> </xsl:sequence> <xsl:catch errors="*"> <xsl:sequence> <error val_pos="{$pos}" document="{$err:module}" code="{$err:code}" description="{$err:description}" location="line:{$err:line-number}, col:{$err:column-number}" /> </xsl:sequence> </xsl:catch> </xsl:try> </xsl:function> </xsl:stylesheet> The above stylesheet, when applied to the input XML document, produces following output, <?xml version="1.0" encoding="UTF-8"?> <result> <div num="5" denom="5">1</div> <div num="5" denom="4">1.25</div> <div num="5" denom="3">1.666666666666666667</div> <error val_pos="4" document="file:/E:/saxon/../foo.xsl" code="err:FOAR0001" description="Integer division by zero" location="line:26, col:0"/> <div num="5" denom="2">2.5</div> <error val_pos="6" document="file:/E:/saxon/../foo.xsl" code="err:FOAR0001" description="Integer division by zero" location="line:26, col:0"/> <div num="5" denom="1">5</div> </result> The above output is, what I wanted to achieve (i.e either emit the "div" tag if div operation is successful, or emit an "error" tag if div by 0 error occurs). For each iteration of loop, my numerator is fixed (its also non zero, and 5 in my example) and denominator is variable (it can be zero. that div error I want to catch via try/catch, and continue processing subsequent items in the loop). I would have been more happy, if an error message could show line numbers of the offending nodes from input XML document. For that, Saxon's extension function line-number(..) seems to do the job well. Below is another stylesheet (Stylesheet 2) processing things a little differently, and working on the same input XML document, <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:err="http://www.w3.org/2005/xqt-errors" xmlns:fn="http://xslt-functions" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="err fn xs" version="3.0"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/"> <result> <xsl:try> <xsl:for-each select="test/val"> <xsl:copy-of select="fn:div(5, .)"/> </xsl:for-each> <xsl:catch errors="*"> <error document="{$err:module}" code="{$err:code}" description="{$err:description}" location="line:{$err:line-number}, col:{$err:column-number}" /> </xsl:catch> </xsl:try> </result> </xsl:template> <xsl:function name="fn:div" as="element()"> <xsl:param name="numerator" as="xs:integer"/> <xsl:param name="denominator" as="xs:integer"/> <xsl:sequence> <div num="{$numerator}" denom="{$denominator}"><xsl:value-of select="$numerator div $denominator"/></div> </xsl:sequence> </xsl:function> </xsl:stylesheet> In the above stylesheet, I use the try/catch at a higher level (I enclose the for-each loop within a try/catch). I get following output with this XSLT transformation, <?xml version="1.0" encoding="UTF-8"?> <result> <error document="file:/E:/saxon/../foo1.xsl" code="err:FOAR0001" description="Integer division by zero" location="line:29, col:0"/> </result> This is expected. The transformation concludes after first failure, and roll backs previous successful outcomes. I'm happy with what I've learnt. On Sat, Feb 23, 2019 at 11:37 PM Michael Kay mike@xxxxxxxxxxxx < xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote: > Division by zero is a dynamic error, but if the operands are constants, > then most processors will be able to detect it statically, because > evaluating constant subexpressions is a very simple optimization. > > So what do the rules say about dynamic errors? The detailed rules are in > B'2.14 https://www.w3.org/TR/xslt-30/#errors -- which doesn't actually > mention try/catch. > > The key paragraph is > > <quote> > An implementation may signal a dynamic error before any source document is > available, but only if it can determine that the error would be signaled > for every possible source document and every possible set of parameter > values. For example, some circularity errors fall into this category: see > 9.11 Circular Definitions. > </quote> > > This isn't quite as rigorous as it might be. In your second example, there > are clearly source documents for which the error will never be raised > dynamically (those where count(/test/hello) is zero) and therefore it must > not be raised statically. In the first example, the error will always be > raised so long as the match="/" template is executed, that is, if > evaluation starts in the unnamed mode; that leaves some scope for > interpretation of exactly what the above paragraph is supposed to mean > (should it be read as saying "and for every possible initial mode"?). Also > the cited paragraph isn't really clear as to what "would be signaled" > means: if an error happens, but is not reported because it is caught by > try/catch, then is it "signaled" for the purpose of this rule? The whole > thing is a bit fuzzy round the edges. > > What's happening in Saxon, though, is quite wrong. Saxon goes to great > lengths to avoid raising the error statically; however the optimizer > somehow rewrites the logic so that the constant expression (1 div 0) is > evaluated outside the try/catch and the error therefore occurs at run-time, > but isn't caught. I'll pursue that as a bug, even though the spec is a > little fuzzy. > -- Regards, Mukul Gandhi alt address : mukulgandhi@xxxxxxx
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] XSLT 3.0 try/catch doubts, Michael Kay mike@xxx | Thread | Re: [xsl] XSLT 3.0 try/catch doubts, Mukul Gandhi gandhi. |
[xsl] DITA Community i18n Library U, Eliot Kimber ekimber | Date | [xsl] Adding entity declarations to, Michele R Combs mrro |
Month |