Looking in the Saxon documentation there is a "-x:className" flag on the command line for specifying a particular SAX parser for use during the application of an XSLT.
How does one achieve this programmatically? I'm using the s9api right now in my code, and I checked the Processor
, XsltCompiler
, XsltExecutable
, and XsltTransformer
objects; none of them have any way to set the SAX parser. I also instantiated a net.sf.saxon.Transform
, and that didn't have anything either.
I am most likely looking at the wrong set of objects, but I don't know how I'm supposed to know what the correct set is.
The command line documentation linked to above mentioned "Use specified SAX parser for source file and any files loaded using the document() function." I'm sure if I knew what I was doing, this mention of a "document()
" function would immediately clue me in. Unfortunately, I do not, and it does not.
Edit: Michael Kay's answer below is the correct one. (Of course it is! He's the Saxon guy!) I figured I'd add some sample code for future generations.
First, his solution using net.sf.saxon.s9api.Processor
:
Processor processor = new Processor(false);
processor.setConfigurationProperty(FeatureKeys.SOURCE_PARSER_CLASS,
"fully.qualified.package.name.of.MySAXParser");
In the above, it's important to supply it the fully-qualified name (and not just the class name) of the SAXParser as a String. If you do the following:
processor.setConfigurationProperty(FeatureKeys.SOURCE_PARSER_CLASS,
new MySAXParser());
...you will get this:
java.lang.IllegalArgumentException: SOURCE_PARSER_CLASS class must be a String
Second, his solution using net.sf.saxon.s9api.XsltTransformer
:
// ^^^ Various setup code to get to this point...
XsltTransformer transformer = xsltExecutable.load();
File file = new File("/path/to/my/file");
InputStream fileInputStream = new FileInputStream(file);
InputSource inputSource = new InputSource(fileInputStream);
Source saxSource = new SAXSource(new MySAXParser(), inputSource);
transformer.setSource(saxSource);
// vvv Set other parameters, actually invoke the transform, etc...
My only issues/caveats are:
1.) The following message is printed out in the console:
Cannot find CatalogManager.properties
This doesn't seem to affect anything, as the transform still works just fine, and I'm pretty sure it has nothing really to do with Saxon itself, but rather something I'm messing up within the implementation of my custom SAXParser.
2.) If I want to transform a non-XML document (yes, it's totally possible) I can't use solution #2, as calling XsltTransform.setSource() causes it to default to viewing the source as an XML document, and will give you the dreaded
Error on line 1 column 1
SXXP0003: Error reported by XML parser: Content is not allowed in prolog.
Thus, for transforming non-XML documents, you must use the "coarse-grained" Processor solution.