1

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
Markus
  • 1,141
  • 1
  • 9
  • 25

1 Answers1

1

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.

Michael Kay
  • 156,231
  • 11
  • 92
  • 164
  • Thanks for your answer. I used the jaxp.debug flag and have added the output to my question. What I see is that with saxon in the classpath I got a information about a SchemaFactory from saxonica. Perhaps this makes the difference. – Markus Sep 06 '18 at 13:07
  • But when you as the developer of saxon tell me that I can set the system property to xalan and just use saxon for the transformerFactory, i will do that. I just was scared that some other things like the XPathFactory are also needed from saxon to run without any problems. – Markus Sep 06 '18 at 13:08
  • The SchemaFactory line is certainly interesting. You need to find out what part of the application is instantiating a SchemaFactory and why, and what it does with the schema factory once it's got it. I can't see how that will explain the difference in your final PDF output, but it's certainly a clue that needs to be investigated. – Michael Kay Sep 06 '18 at 13:26