Michael Kay wrote:
Hi
> > > (c)
> [...]
> > I'm a little bit lost in the several optimizations,
> > rewritings, validations, preparations, compilations,
> > simplifications, etcetera.
> I'm not surprised, I get lost in them myself...
Ok, I'm feeling less stupid :-)
> I'm afraid I would need to step this through the debugger
> to see exactly what's going on. I doubt that it's a
> compile-time rewrite that's causing the problem
Yes, it was a bug. The inner ex:error-safe caught an
exception, there was no handler for it, so it rethrowed it
(encapsulated in a DynamicError). The outer ex:error-safe
caught it and handled it.
The reason there was no handler in the inner most
ex:error-safe is that it was not an XPath error, but
another Java exception, an IndexOutOfBoundException.
I added the possibility to catch Java exceptions in
addition to XPath errors:
<ex:error-safe>
<ex:try>
<xsl:value-of select="for $i in $n return $i div $d"/>
</ex:try>
<ex:catch errors="jt:java.lang.ArrayIndexOutOfBoundsException"
xmlns:jt="http://saxon.sf.net/java-type">
<bounds/>
</ex:catch>
</ex:error-safe>
The test case now "passes", but I still have to
investigate on the reason this exception is thrown. The
exception is:
(drkm)[139]> saxon --b --cp=. -it main test/error-safe-03.xsl
java.lang.ArrayIndexOutOfBoundsException: -999
at
net.sf.saxon.expr.XPathContextMinor.setLocalVariable(XPathContextMinor.java:353)
at
net.sf.saxon.expr.ForExpression$MappingAction.map(ForExpression.java:575)
at
net.sf.saxon.expr.MappingIterator.next(MappingIterator.java:55)
at
net.sf.saxon.instruct.SimpleContentConstructor.evaluateItem(SimpleContentConstructor.java:215)
at
net.sf.saxon.instruct.ValueOf.processLeavingTail(ValueOf.java:198)
at
net.sf.saxon.instruct.Instruction.process(Instruction.java:91)
at
org.fgeorges.exslt2.saxon.ErrorSafeExpression.process(ErrorSafe.java:77)
at
net.sf.saxon.instruct.UserFunction.process(UserFunction.java:209)
at
net.sf.saxon.expr.UserFunctionCall.process(UserFunctionCall.java:306)
at
org.fgeorges.exslt2.saxon.ErrorSafeExpression.process(ErrorSafe.java:77)
at
net.sf.saxon.instruct.ElementCreator.processLeavingTail(ElementCreator.java:250)
at net.sf.saxon.instruct.Template.expand(Template.java:113)
at
net.sf.saxon.Controller.transformDocument(Controller.java:1617)
at net.sf.saxon.Controller.transform(Controller.java:1426)
at net.sf.saxon.Transform.execute(Transform.java:890)
at net.sf.saxon.Transform.doTransform(Transform.java:491)
at net.sf.saxon.Transform.main(Transform.java:60)
But I doubt this can help you as is.
> [...]
> But I can't quite see how this could happen, so I might be
> wrong.
No, I was.
> > I added a fifth test case. IMHO the simpler but more
> > important one:
> > <ex:error-safe>
> > <ex:try>
> > <root>
> > <xsl:sequence select="error(...)"/>
> > </root>
> > </ex:try>
> > <ex:catch ...
> > It looks simple. But what I understand is that when
> > the error is thrown, nothing else is evaluated (for
> > example the closing root element event), until the error
> > is catched and the transformation continue with
> > evaluating the ex:catch own sequence constructor.
> > So when the serializer come to play, it is given an
> > incoherent "tree" (the sequence of events no longer
> > represents a legal tree).
> > I need to define what to do here. I'm not sure what
> > is the right way (not speaking of how to implement it in
> > Saxon).
> Yes, this is a nasty one. You're evaluating in "push" mode
> (using the process() method) which writes events to the
> current output stream, and in the event of an error this
> needs to roll-back these events. This suggests you might
> need to add a new SequenceOutputter to the output pipeline
> which stores all the events, and then release them to the
> rest of the pipeline only on successful completion.
It could be a solution. Actually, I didn't already define
what to do in the case an error is thrown from within an
element being constructed. With the solution you describe,
if I'm right, that will discard all the content of the
ex:try if it throws an error.
I wrote a little proxy receiver that counts the
startElement and endElement events, and can close all the
remaining "opened" elements at a given time. This enables
to keep as much as possible that was constructed within the
ex:try before the error was thrown:
public class ProxyErrorSafeReceiver
extends ProxyReceiver
{
public ProxyErrorSafeReceiver(Receiver next)
{
nextReceiver = next;
}
public void closeRemainingOpenElements()
throws XPathException
{
if ( myOpens > myStarts ) {
++myStarts;
nextReceiver.startContent();
}
while ( myOpens > 0 ) {
endElement();
}
}
public void startElement(
int nameCode, int typeCode,
int locationId, int properties)
throws XPathException
{
++myOpens;
nextReceiver.startElement(
nameCode, typeCode, locationId, properties);
}
public void startContent()
throws XPathException
{
++myStarts;
nextReceiver.startContent();
}
public void endElement()
throws XPathException
{
--myOpens;
--myStarts;
nextReceiver.endElement();
}
private int myOpens = 0;
private int myStarts = 0;
}
In ErrorSafeExpression:
public void process(XPathContext ctxt)
throws XPathException
{
SequenceReceiver original =
(SequenceReceiver) ctxt.getReceiver();
ProxyErrorSafeReceiver proxy =
new ProxyErrorSafeReceiver(original);
try {
ctxt.setReceiver(proxy);
myTry.process(ctxt);
}
catch ( Exception ex ) {
proxy.closeRemainingOpenElements();
< .. hanlde the error ... >
}
ctxt.setReceiver(original);
}
The following test case:
<root>
<ex:error-safe>
<ex:try>
<element>
<xsl:sequence select="error(...)"/>
</element>
</ex:try>
<ex:catch>
<handler/>
</ex:catch>
</ex:error-safe>
</root>
runs now as follows:
(drkm)[140]> saxon --b --cp=. -it main test/error-safe-05.xsl
<root>
<element/>
<handler/>
</root>
But as I said I'm still not sure what to do in this case.
Maybe both closing remaining open elements and discarding
all the ex:try sequence constructor may be interesting
choices, depending on the use case?
> Good luck... I'm thinking I will probably take this stuff
> on board once you've got it basically working; it's
> becoming clear that it needs integrating at too intimate a
> level to be a pure user-written bolt-on.
Great!
Thanks again,
--drkm
___________________________________________________________________________
Découvrez une nouvelle façon d'obtenir des réponses à toutes vos questions !
Profitez des connaissances, des opinions et des expériences des internautes sur Yahoo! Questions/Réponses
http://fr.answers.yahoo.com
|