Avatar of BSDev
BSDev
 asked on

Retrieving useful error information when compiling an xsl stylesheet in Saxon 9.

I am developing an application that uses Saxon 9 to transform XML with XSL stylesheets. I have so far been unable to extract useful stylesheet error information when an exception has been raised.

The Saxon 9 command-line utility produces very helpful error information including line numbers, diagnostics, etc, so I'm assuming that it is possible to extract the information through the java api somehow.

I've had a look at the various ErrorListener classes and related methods, but they only seem to deal with errors at transformation time. I may simply be after a nice way to run validation on the stylesheet text when I catch a javax.xml.transform.TransformerConfigurationException when compiling the stylesheet, but I've had no luck finding validation inside the Saxon classes either.

If I could get an example of extracting a stylesheet's error information during the compile phase that would be excellent.
import net.sf.saxon.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*
 
TransformerFactoryImpl fact = new TransformerFactoryImpl();
 
DOMSource source = ...;
// an XML document, already validated as XML
// to be used as the XSL stylesheet
 
try {
    fact.newTransformer(source); // 
} catch(TransformerConfigurationException error) {
    // I would like to extract xsl-related errors here
}

Open in new window

Web Languages and StandardsXMLJava

Avatar of undefined
Last Comment
abel

8/22/2022 - Mon
abel

I will forward your question to the Saxon mailing list. Often, Michael Kay himself answers on that list quite promptly. If you are interested yourself in the answers, you can subscribe to that list through the Saxon Sourceforge pages.
Mick Barry

BSDev

ASKER
objects:

"Failed to compile stylesheet. 1 error detected"

... is all I seem to be able to retrieve with getMessageAndLocation().

I've looked at most of the exception methods, and don't seem to be able to get anything useful back from them.

For reference I'm using this block of XSL text to test with:

--- begin

               
           
           
                  
                      <!-- error -->
                      
                   
                   
               
           
       
--- end
I started with Experts Exchange in 2004 and it's been a mainstay of my professional computing life since. It helped me launch a career as a programmer / Oracle data analyst
William Peck
ASKER CERTIFIED SOLUTION
abel

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.
BSDev

ASKER
abel:

The solution you provided with the ErrorListener on the TransformerFactory has allowed me to extract some useful information, but doesn't give me any line numbers.

The error string that I extract from the ListeningErrorListener is:

--- begin
:Line=-1;Column=-1: exception:Unknown XSLT element: george
root-cause:null
line: logSourceLine unavailable due to: no protocol:
error: Unknown XSLT element: george
--- end

Any idea how I can track down the line number as well?
// import java.io.*;
// import org.apache.xml.utils.ListingErrorHandler;
// import javax.xml.transform.TransformerConfigurationException;
 
StringWriter writer = new StringWriter();
PrintWriter printWriter = new PrintWriter(writer);
ListingErrorHandler errorListener = new ListingErrorHandler(PrintWriter);
 
// net.sf.saxon.TransformerFactoryImpl tFactory;
tFactory.setErrorListener(errorListener);
 
try {
    // javax.xml.transform.dom.DOMSource source;
    tFactory.newTransformer(source)
} catch(TransformerConfigurationException error) {
    // extract a useful error message
    writer.toString();
}

Open in new window

abel

weren't you a bit quick with grading (esp a B) when you still had questions on how to solve it? I'll like to look into it for you, but it is 4AM here, so it'll be a short while later ;)
abel

Getting the line number is not so trivial and depends on whether the source document has line number information already or not. Here's a post from, again, Michael Kay about the subject:

It turns out that there is in fact a class net.sf.saxon.event.LocationCopierwhich is designed to copy line number information.I think that if you do the following, any line number information present inthe source document nodeInfo should be passed across to the new document:PipelineConfiguration pipe = config.makePipelineConfiguration();Builder b = new TinyBuilder();b.setPipelineConfiguration(pipe);b.setLineNumbering(true);LocationCopier lc = new LocationCopier();lc.setUnderlyingReceiver(lc);lc.setPipelineConfiguration(pipe);nodeInfo.copy(lc, NodeInfo.ALL_NAMESPACES, true, 0);The schema document builder automatically inserts a LocationCopier into thepipeline. In fact, that's what LocationCopier was designed for - it's usedwhen processing the inline schema that can be contained in anxsl:import-schema element in a stylesheet. I tested this with the followingsimple program:    public static void main(String[] args) throws Exception {        Configuration config = new SchemaAwareConfiguration();        config.setLineNumbering(true);        NodeInfo node = config.buildDocument(new StreamSource(newFile("c:/temp/test.xsd")));        config.addSchemaSource(node);    }and confirmed that errors in the schema are reported with line numbers.But this only works, of course, if the source document already contains linenumber information.

Regards,
-- Abel --
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
BSDev

ASKER
Sorry Abel.

I'm still not very familiar with the Experts Exchange conventions :)
abel

np. The idea is, usually, the interrogate "your" expert or "experts" and to burden them with questions until you are satisfied. Of course, the questions must remain in the scope of the original question.

It is custom to give A when you are satisfied with the answer (not necessary the result: sometimes something "cannot be done" but, rightfully argumented, that should still receive an A grade).

Reserve B when you tried to get your answer but the expert just isn't capable of completely satisfying you or does not return often (i.e., waits longer than a day or so)

Reserve C (is it still available) when you are actually dissatisfied, but the answer was to some aid to you. Often, when you consider a C you should also consider deleting the question, or answering it yourself (post a Q. in the customer topic area to give yourself the credits).