1
votes

I have an application where I use Xalan as XSLT processor. I now want to use Saxon. I want to be sure that all existing transformations still work. Therefore I want to use Xalan for all existing XML files. For new XML files, I want to use Saxon. To summarize I want to use both processors alongside. Therefore I instantiate the processor like this:

TransformerFactory.newInstance("com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl", null);
or
TransformerFactory.newInstance("net.sf.saxon.TransformerFactoryImpl", null);

In all my existing unit tests I use Xalan. But some of them fail when I add Saxon to my classpath. The tests that fail all use Apache FOP to create a PDF-file. The difference is that now some tabs (indent keys) are inserted in the generated PDF (not in the visible content, I just see them when I compare the bytecode). I think this behavior is strange because I still use Xalan and expect the same result as when I don't have Saxon in my classpath. So what else does change when Saxon is in the classpath?

When I add

System.setProperty("javax.xml.transform.TransformerFactory",
            "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl");

to my tests, it again works with Saxon in the classpath. But this is no solution for my productive environment because I want to switch dynamically between the two processors.

So does anyone know what else changes when I add Saxon to my classpath? Thank you very much!

Update: I have set the jaxp.debug flag and get the following output (using Xalan with Saxon in the classpath)

    JAXP: created new instance of class org.apache.xalan.xsltc.trax.TransformerFactoryImpl using ClassLoader: null
JAXP: created new instance of class org.apache.xalan.xsltc.trax.TransformerFactoryImpl using ClassLoader: null
JAXP: created new instance of class org.apache.xalan.xsltc.trax.TransformerFactoryImpl using ClassLoader: null
Calling com.saxonica.SchemaFactoryImpl.isSchemaLanguageSupported("http://www.w3.org/2001/XMLSchema"); returning true
JAXP: created new instance of class org.apache.xalan.xsltc.trax.TransformerFactoryImpl using ClassLoader: null
JAXP: find factoryId =javax.xml.transform.TransformerFactory
JAXP: find factoryId =javax.xml.transform.TransformerFactory
JAXP: find factoryId =javax.xml.transform.TransformerFactory
JAXP: find factoryId =javax.xml.transform.TransformerFactory
JAXP: find factoryId =javax.xml.transform.TransformerFactory
JAXP: created new instance of class org.apache.xalan.xsltc.trax.TransformerFactoryImpl using ClassLoader: null

When I remove saxon from the classpath, i got the following output:

JAXP: created new instance of class org.apache.xalan.xsltc.trax.TransformerFactoryImpl using ClassLoader: null
JAXP: created new instance of class org.apache.xalan.xsltc.trax.TransformerFactoryImpl using ClassLoader: null
JAXP: created new instance of class org.apache.xalan.xsltc.trax.TransformerFactoryImpl using ClassLoader: null
JAXP: created new instance of class org.apache.xalan.xsltc.trax.TransformerFactoryImpl using ClassLoader: null
JAXP: find factoryId =javax.xml.transform.TransformerFactory
JAXP: find factoryId =javax.xml.transform.TransformerFactory
JAXP: find factoryId =javax.xml.transform.TransformerFactory
JAXP: find factoryId =javax.xml.transform.TransformerFactory
JAXP: find factoryId =javax.xml.transform.TransformerFactory
JAXP: created new instance of class org.apache.xalan.xsltc.trax.TransformerFactoryImpl using ClassLoader: null

So I really use the Xalan processor. The difference in the output is that without saxon in the classpath i dont see the line

Calling com.saxonica.SchemaFactoryImpl.isSchemaLanguageSupported("http://www.w3.org/2001/XMLSchema"); returning true

After reading this question I added the proposed lines to get information about all the factories. When I use the xalan processor (with saxon in the classpath), i got

DocumentBuilderFactory implementation: com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl loaded from: Java Runtime
    XPathFactory implementation: org.apache.xpath.jaxp.XPathFactoryImpl loaded from: file:/D:/repository/xalan/xalan/2.7.1/xalan-2.7.1.jar
    TransformerFactory implementation: com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl loaded from: Java Runtime
    SAXParserFactory implementation: com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl loaded from: Java Runtime

When i use Saxon i got

    DocumentBuilderFactory implementation: com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl loaded from: Java Runtime
XPathFactory implementation: org.apache.xpath.jaxp.XPathFactoryImpl loaded from: file:/D:/repository/xalan/xalan/2.7.1/xalan-2.7.1.jar
TransformerFactory implementation: com.saxonica.config.EnterpriseTransformerFactory loaded from: file:/D:/repository/de/soptim/contrib/net/sf/saxon/Saxon-EE/9.8.0.14/Saxon-EE-9.8.0.14.jar
SAXParserFactory implementation: com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl loaded from: Java Runtime
1

1 Answers

1
votes

I think you must have some transformations that are using TransformerFactory.newInstance() without specifying a processor. Try setting the jaxp.debug system property to get diagnostics on the loading process.

I would suggest setting the system property

System.setProperty("javax.xml.transform.TransformerFactory",
            "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl");

so that Xalan is invoked by default, and using

TransformerFactory saxon = new net.sf.saxon.TransformerFactoryImpl();

in cases where you want to invoke Saxon. If you want to make the decision dynamically, then control it using some conditional logic in your own code.