Debugger very unhelpful

Here should go questions about transforming XML with XSLT and FOP.
cefn
Posts: 15
Joined: Thu Jul 12, 2007 6:20 pm
Location: Ipswich, UK

Debugger very unhelpful

Post by cefn » Thu Oct 25, 2007 7:30 pm

I've been using the Oxygen XSLT debugger based on Saxon8B for the first time and found it very unhelpful.

The error shown below was generated at line 202 of my source file - a line which doesn't invoke the root() function at all so cannot directly be responsible for the error.

Furthermore it seems impossible to get the debugger to halt the stack and retain variables or other information on a fatal error like this in order to work out what is actually causing it further up the stack invocation.

I've therefore been unable so far to debug the problem as I cannot trace the context in which it occurs.

Although I can run to a given line and inspect the in-memory information of the stack, I cannot inspect variables at the point the error takes place. Once the error has been triggered, the 'Nodes/Value Sets' and 'Variables' sections are empty, and cannot work out where the invocation of the root() function actually is which causes the problem.

Can anyone explain to me how I should use the XSLT debugger to debug these terminal errors?

Is there a mechanism to have it halt on error and retain some information I can inspect about the data it's manipulating when the failure takes place?

Here's the error...

SystemID: /Users/cefn/Documents/code/btok/ide/code/xslt/librng.xsl
Location: 202:0
Description: A sequence of more than one item is not allowed as the first argument of root() (<define/>, <define/>)
URL: http://www.w3.org/TR/xpath20/#ERRXPTY0004

...and it relates to line 202 which looks like...

<xsl:choose>

Cefn

sorin_ristache
Posts: 4144
Joined: Fri Mar 28, 2003 2:12 pm

Re: Debugger very unhelpful

Post by sorin_ristache » Fri Oct 26, 2007 3:50 pm

Hello,
cefn wrote:Can anyone explain to me how I should use the XSLT debugger to debug these terminal errors?
You should set a breakpoint on a line of the XSLT stylesheet or the XML document which is processed by the transformation before the terminal error, start the transformation which will stop automatically at the breakpoint and inspect the views XWatch, Stack, Trace, Templates, etc. to see the processing context when the terminal error is about to hit.
cefn wrote:Is there a mechanism to have it halt on error and retain some information I can inspect about the data it's manipulating when the failure takes place?
When the failure takes place the transformation was already ended unexpectedly by an exceptional condition or an error. You can look in the debugger views Stack, Trace and Templates to see where the processing was stopped and set a breakpoint on one of the last elements displayed there.
cefn wrote:Here's the error...

SystemID: /Users/cefn/Documents/code/btok/ide/code/xslt/librng.xsl
Location: 202:0
Description: A sequence of more than one item is not allowed as the first argument of root() (<define/>, <define/>)
URL: http://www.w3.org/TR/xpath20/#ERRXPTY0004

...and it relates to line 202 which looks like...

<xsl:choose>
At what line number is the root() function call?


Regards,
Sorin

cefn
Posts: 15
Joined: Thu Jul 12, 2007 6:20 pm
Location: Ipswich, UK

Post by cefn » Fri Oct 26, 2007 4:27 pm

Thanks for the reply. You suggested...
You should set a breakpoint on a line of the XSLT stylesheet or the XML document which is processed by the transformation before the terminal error
The debugger views 'Stack, Trace and Templates' are indeed populated after the terminal error so it should be possible to tell what the stack of execution was when the error was encountered and in principle monitor the key steps 'before the terminal error'.

However, the line at which the problematic 'root()' invocation takes place is unknown since the debugger, reports the error at an incorrect source location.

That source line indicated, and indeed all of its XSLT child elements do not contain any invocation of 'root()' except indirectly through several possible nested function calls or late bindings. The actual stack and context which led to the error is therefore simply unknown because the debugger does not report any useful information to support this investigation.

I guess the answer really IS that there is no mechanism to debug terminal errors. Added to this problem is the fact the minimal information which IS reported for this terminal error is incorrect making the precise source line impossible to monitor. In this program there are 31,000 visits to some functions, making manual verification of every visit essentially impossible.

What you're suggesting is that I manually explore the serial execution of the stylesheet step by step, memorising the whole stack and context every time in case the next step is the one which causes the error.

I'm afraid I interpret this to mean that monitoring and debugging error conditions is not supported. Nothing much I can do about it, I'm just surprised to discover this. Seems like it's not a debugger if it can't do this.

In this case I've been able to work around the problem by simply rewriting and fixing the stylesheet manually to ensure only single nodes are passed into this part of the stylesheet. However, I've been unable to establish what the node set was which originally caused the problem and where the invocation came from.

However, the absence of any real debugging information will remain a problem for any future more complex bugs.

sorin_ristache
Posts: 4144
Joined: Fri Mar 28, 2003 2:12 pm

Post by sorin_ristache » Fri Oct 26, 2007 5:45 pm

cefn wrote:That source line indicated, and indeed all of its XSLT child elements do not contain any invocation of 'root()' except indirectly through several possible nested function calls or late bindings. The actual stack and context which led to the error is therefore simply unknown because the debugger does not report any useful information to support this investigation.

I guess the answer really IS that there is no mechanism to debug terminal errors. Added to this problem is the fact the minimal information which IS reported for this terminal error is incorrect making the precise source line impossible to monitor.
I think there is a simple way of debugging the error. A call to the function root() is encountered before the transformation ends with the terminal error. Otherwise you would not get an error message about "the first argument of root() (<define/>, <define/>)". My suggestion is to set a breakpoint inside the root() function and one breakpoint on every call to the root() function. Start the transformation with the Run button from the debugger control toolbar and see after which breakpoint you get the terminal error. Start the investigation from the context of this breakpoint when the transformation is still running and the content of all the debugger views is available.


Regards,
Sorin

cefn
Posts: 15
Joined: Thu Jul 12, 2007 6:20 pm
Location: Ipswich, UK

Useful and clear advice

Post by cefn » Fri Oct 26, 2007 6:06 pm

Your advice is very clear, Sorin, and sounds very useful.

However, I must be missing something as I don't know how to add a breakpoint to the root() function (a core XPath function).

I can monitor the line containing the likely problem invocation of root(), but even then I seem unable to construct a breakpoint condition based on locally scoped variable (e.g. count($node) > 1) to verify that the problem condition has arisen before this breakpoint is activated.

Perhaps you have some advice how I could go about...
a) adding a breakpoint to a core XPath function.
b) adding a break condition to the breakpoint in my own code which saves me verifying the stack state 30,000 times manually.

sorin_ristache
Posts: 4144
Joined: Fri Mar 28, 2003 2:12 pm

Re: Useful and clear advice

Post by sorin_ristache » Mon Oct 29, 2007 10:51 am

cefn wrote:Perhaps you have some advice how I could go about...
a) adding a breakpoint to a core XPath function.
I am sorry, from the error message ("a sequence ... not allowed as the first argument of root() (<define/>, <define/>)") I understand that it is a user defined function as it has two arguments. If it is the core root function then you cannot set a breakpoint inside it. You have to fix the error only with breakpoints on lines where the function is called.
cefn wrote:b) adding a break condition to the breakpoint in my own code which saves me verifying the stack state 30,000 times manually.
Did you try the Break Conditions view of the oXygen XSLT Debugger? Did you try counting and displaying with xsl:message the number of successful calls of root or other variable values before the terminal error?


Regards,
Sorin

Post Reply