Reputation: 946
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.
Upvotes: 4
Views: 3408
Reputation: 163587
If you want to be sure of getting answers to Saxon questions, use the Saxon forums at dev.saxonica.com, or the saxon-help list on SourceForge.
The answer is: you can use
Processor.setConfigurationProperty(
FeatureKeys.SOURCE_PARSER_CLASS, parserClassName)
However, this may be a bit coarse-grained: it works on the command line because the Configuration is set up typically just to transform one document. For finer control, you can always supply input to a transformation in the form of a SAXSource object, which contains an XMLReader, which represents an instance of the SAX parser that you want to use.
Upvotes: 1