Project

Profile

Help

Bug #6049

closed

Does XQueryEvaluator for SaxonCS lack the API to set an ErrorReporter?

Added by Martin Honnen 11 months ago. Updated 5 months ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Category:
.NET API
Sprint/Milestone:
-
Start date:
2023-05-25
Due date:
% Done:

100%

Estimated time:
Legacy ID:
Applies to branch:
12, trunk
Fix Committed on Branch:
12, trunk
Fixed in Maintenance Release:
Platforms:
.NET

Description

In https://saxonica.plan.io/boards/3/topics/9430?r=9432#message-9432 I commented on spurious console error output by SaxonCS while I thought my GUI program caught any SaxonApiExceptions. I managed to prevent lots of those console error outputs by using an ErrorReporter on XsltCompiler, XQueryCompiler and Xslt30Transformer.

However, for XQueryEvaluator in the SaxonCS API, that option seems to be missing and as a result code like

using Saxon.Api;

namespace SaxonCSXQueryEvaluatorLackOfErrorReporter
{
    internal class Program
    {
        static void Main(string[] args)
        {
            var processor = new Processor();

            var xqueryCompiler = processor.NewXQueryCompiler();

            var errorList = new List<string>();

            xqueryCompiler.ErrorReporter = error => errorList.Add($"{error.Message} {error.Location.LineNumber}:{error.Location.ColumnNumber}");

            XQueryExecutable xqueryExecutable = null;
            try
            {
                xqueryExecutable = xqueryCompiler.Compile(".");
            }
            catch (SaxonApiException e)
            {
                Console.WriteLine($"XQuery compilation failed: {e.Message}\n{string.Join('\n', errorList)}");
                return;
            }

            var xqueryEvaluator = xqueryExecutable.Load();

            try
            {
                using var resultWriter = new StringWriter();
                xqueryEvaluator.Run(processor.NewSerializer(resultWriter));
                Console.WriteLine(resultWriter.ToString());
            }
            catch (SaxonApiException e)
            {
                Console.WriteLine($"XQuery evaluation failed: {e.Message}\n{string.Join('\n', errorList)}");
            }

        }
    }
}

outputs both the Console.WriteLine($"XQuery evaluation failed: {e.Message}\n{string.Join('\n', errorList)}"); as well as SaxonCS internal Console.Err output e.g.

Error on line 1 column 2
  XPDY0002  The context item is absent
XQuery evaluation failed: The context item is absent

For a Java program along the same lines I see similar output but there XQueryEvaluator allows me to set an ErrorReporter e.g.

package org.example;

import net.sf.saxon.s9api.*;

import java.io.StringWriter;
import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        Processor processor = new Processor();

        XQueryCompiler xqueryCompiler = processor.newXQueryCompiler();

        ArrayList<String> errorList = new ArrayList<>();
        xqueryCompiler.setErrorReporter(xmlProcessingError -> errorList.add(xmlProcessingError.getMessage() + " " + xmlProcessingError.getLocation().getLineNumber() + ":" + xmlProcessingError.getLocation().getColumnNumber()));

        XQueryExecutable xqueryExecutable = null;
        try {
            xqueryExecutable = xqueryCompiler.compile(".");
        }
        catch (SaxonApiException e) {
            System.out.println("XQuery compilation failed: " + e.getMessage() + "\n" + errorList);
            return;
        }

        XQueryEvaluator xqueryEvaluator = xqueryExecutable.load();

        errorList.clear();
        xqueryEvaluator.setErrorReporter(xmlProcessingError -> errorList.add(xmlProcessingError.getMessage() + " " + xmlProcessingError.getLocation().getLineNumber() + ":" + xmlProcessingError.getLocation().getColumnNumber()));
        
        try {
            StringWriter resultWriter = new StringWriter();
            xqueryEvaluator.run(processor.newSerializer(resultWriter));
        }
        catch (SaxonApiException e) {
            System.out.println("XQuery evaluation failed: " + e.getMessage() + "\n" + errorList);
        }

    }
}

and then Saxon's internal output to System.err is prevented.

That suggests SaxonCS somehow lacks the option/API to set an ErrorReporter on XQueryEvaluator.

Or is there a different way for SaxonCS to prevent the Console.Err output and handle any errors with program code?

Actions #1

Updated by Michael Kay 11 months ago

That suggests SaxonCS somehow lacks the option/API to set an ErrorReporter on XQueryEvaluator.

First reaction, it appears to be an oversight.

But actually, I think it might have been deliberate, since the method is also absent from XsltTransformer.

Perhaps I was thinking: run-time errors are always fatal (unless caught by try/catch). They are going to result in an exception, and all the error information should be in the exception. What is achieved by notifying them to an ErrorReporter as well?

This logic doesn't work for warnings, of course.

Or is there a different way for SaxonCS to prevent the Console.Err output and handle any errors with program code?

On the reasoning above, there should be no Console.Err output unless the application writes it. That's in an ideal world, of course. It's hard to be sure it won't happen on some error conditions.

Actions #2

Updated by Michael Kay 5 months ago

Revisiting this.

Clearly if we rely entirely on dynamic errors being reported only via the final exception thrown by the query Run() (or whatever) method, then we shouldn't be outputting error messages to the console; conversely, if we do output messages, then we should provide a way to capture them in the application.

Because the underlying Java code is notifying dynamic errors to an ErrorReporter, it's easiest to change SaxonCS to allow the messages to be captured rather than providing a way for them to be suppressed. So I'm going to pursue that avenue.

Actions #3

Updated by Michael Kay 5 months ago

  • Status changed from New to Closed
  • Applies to branch trunk added
  • Fix Committed on Branch 12, trunk added
Actions #4

Updated by Michael Kay 5 months ago

  • Tracker changed from Support to Bug
  • Status changed from Closed to Resolved
Actions #5

Updated by Michael Kay 5 months ago

  • Status changed from Resolved to In Progress

Re-opening, to clarify exactly what the error reporter in the XPath case actually does.

Actions #6

Updated by Michael Kay 5 months ago

I'm going to step back from adding the ErrorReporter property to XPathSelector, because it appears to have very little effect - despite the fact that it's available in the Java API. If a fatal error occurs, the ErrorReporter isn't called, the error information is available only via the exception that is thrown from the Evaluate() method. I think the ErrorReporter is probably called to notify warnings, but run-time warnings are (rightly) very rare -- in fact, I'm having trouble locating any that can occur with free-standing XPath, other than warnings explicitly requested when a document in a collection() can't be read.

Actions #7

Updated by Michael Kay 5 months ago

  • Status changed from In Progress to Resolved
Actions #8

Updated by O'Neil Delpratt 5 months ago

  • Status changed from Resolved to Closed
  • % Done changed from 0 to 100
  • Fixed in Maintenance Release 12.4 added

Bug fix applied in the Saxon 12.4 maintenance release

Please register to edit this issue

Also available in: Atom PDF