user1884155
user1884155

Reputation: 3736

XML namespace is different with different implementations of DocumentBuilder/Transformer

I have 2 machines with identical java code on them. The code is about building an xml document using a document builder, and about converting that document to a string using a transformer. Both are instantiated using factory.newInstance():

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();

TransformerFactory tff = TransformerFactory.newInstance();
Transformer tf = tff.newTransformer();

However, I noticed they behaved differently. One 1 machine, inserting nodes in the document correctly turns empty namespaces into namespace with name equal to the empty string. On the other machine this doe not happen, and no namespace is inserted, and the element uses the parent's namespace instead.

So I compared the actual classes/classloaders for the factory's and the builder/transformer and they are indeed different. Here's the logfile for the correct output:

DocumentBuilderFactory class name:      com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl
DocumentBuilderFactory class loader:        null
DocumentBuilderFactory class package:       package com.sun.org.apache.xerces.internal.jaxp, Java Platform API Specification, version 1.7

DocumentBuilder class name:             com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl
DocumentBuilder class loader:           null
DocumentBuilder class package:      package com.sun.org.apache.xerces.internal.jaxp, Java Platform API Specification, version 1.7

TransformerFactory class name:      com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl
TransformerFactory class loader:        null
transformerFactory class package:       package com.sun.org.apache.xalan.internal.xsltc.trax, Java Platform API Specification, version 1.7

Transformer class name:             com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl
Transformer class loader:           null
Transformer class package:          package com.sun.org.apache.xerces.internal.jaxp, Java Platform API Specification, version 1.7

And here's the log for the WRONG output:

DocumentBuilderFactory class name:      org.apache.xerces.jaxp.DocumentBuilderFactoryImpl
DocumentBuilderFactory class loader:        sun.misc.Launcher$AppClassLoader@2ff40e1f
DocumentBuilderFactory class package:       package org.apache.xerces.jaxp

DocumentBuilder class name:             org.apache.xerces.jaxp.DocumentBuilderImpl
DocumentBuilder class loader:           sun.misc.Launcher$AppClassLoader@2ff40e1f
DocumentBuilder class package:      package org.apache.xerces.jaxp

TransformerFactory class name:      org.apache.xalan.processor.TransformerFactoryImpl
TransformerFactory class loader:        sun.misc.Launcher$AppClassLoader@2ff40e1f
transformerFactory class package:       package org.apache.xalan.processor

Transformer class name:             org.apache.xalan.transformer.TransformerIdentityImpl
Transformer class loader:           sun.misc.Launcher$AppClassLoader@2ff40e1f
Transformer class package:          package org.apache.xerces.jaxp

I would like to tell the second machine to behave like the first one, but I'm not familiar with how cloassloaders work. Can anybody give me detailed info about:

1) Why is there a difference, what does classloading mean in this context? 2) How can I alter the default behaviour of machine #2 to use the same stuff as machine #1?

Upvotes: 0

Views: 827

Answers (1)

Michael Kay
Michael Kay

Reputation: 163262

That's probably the wrong way to go. The versions of Xerces and Xalan from Apache are generally more reliable, robust, and standards conformant than the versions in the JDK. I would try to move everything to the Apache versions, and work out why your code is giving the wrong result in those cases, and fix it. We would need to see the details of exactly what code you think is giving the wrong result to tell you which product is actually behaving according to spec and which isn't. Choosing the product that is correct according to the spec is a much better approach than choosing the one that happens to do what you want.

You can control which versions JAXP loads in a number of ways: by changing what's on the classpath, by setting Java system properties, or by explicitly loading a chosen version. If you look at the Javadoc for classes like DocumentBuilderFactory and TransformerFactory it gives you a very detailed explanation.

Upvotes: 1

Related Questions