views:

318

answers:

4

In Java 6, the entire xerces XML parser/serializer implementation is now in the Java runtime (rt.jar). The packages have been moved under the com.sun.* namespace, which places them off-limits for explicit reference within client code. This is not a problem when using the parser, which is instantiated via javax API-defined factories.

However, our code also uses xerces serialization (org.apache.xml.serialize.* ). AFAICT, there are no javax.xml API-defined factories for creating instances of Serializer and OutputFormat. This seems to imply that the only way to get one is to explicitly call the com.sun.org.apache.xml.serialize.* APIs.

I've found the serialization classes in javax.xml.stream, but they don't seem to provide any output-formatting control like the xerces OutputFormat class.

Question:

Is there a way to access the xerces serialization functionality (which is in rt.jar) via a javax standard API, without including xerces.jar and also without explicitly instantiating com.sun.* classes?

If not, is there an javax API-compliant way to achieve the same effect?

+1  A: 

As far as I know there is no official API to do this. The Java XML APIs strangely are only for parsing XML.

You could, however, use the XML Transformation API to write a DOM Document to a file. See this example.

Jesper
I'm investigating the Transformation API now. It doesn't seem to have the flexibility to specify formatting that's available via OutputFormat, unless it's using the xerces serialization under the covers and there's a way to get parameters to the serializer.
Jim Garrison
A: 

javax.xml.bind.JAXBContext? If you are trying to bind/serialize objects to XML, JAXB is the standard to go with. If you are doing raw parsing, org.xml.sax and/or org.w3c.dom should have what you're lookinf for.

UPDATED: The com.javax.transform packages should help. Take a look at the Transformer example here.

Matthew Flynn
No, I'm not binding Java objects to XML. This is just about serializing DOM, and nothing but the xerces/xalan serialization API seems to provide any control over the output formatting (indentation, whitespace, etc).
Jim Garrison
+1  A: 

If you don't want to reference sun API's, you can place Xerces in the endorsed directory. It will replace the sun copy/implementation, but then you can use the API without worries (this is the "official" way to do it).

The Java built-in implementation does not provide good control over the output, although it is possible to gain some better control over the output using Xerces and the API properties, since the API supports passing additional properties that other implementations may find useful. Haven't tried that last one myself (I'm only going by the documentation).

Edit (in response to comment): If you want to use Xerces in an enviornment where you do not control the underlying JDK to the point where you can specify your own replacement APIs for JAXP, then you will have to reference Xerces directly (or reference the sun package rewrite).

If you can put Xerces in the endorsed directory (or otherwise override the endorsed setting - which seems unlikely in an app server frankly, although I don't know Weblogic specifically) the "JDK" way of setting the properties to an underlying implementation is via TransformerFactory.setAttribute, which depending on the implementation may interact with Transformer.setParameter.

I should add that should the underlying version that sun bundles be enough, and if Weblogic uses it (or uses its own Xerces if that is enough) then you may be in luck here, and just be able to pass the properties and have it work.

Yishai
We would use the endorsed directory, but we are trying to get our product to be deployable in a WAR/EAR, in a WebSphere environment that has very strict security requirements. Where in the API do you see the possibility of passing additional properties to the underlying xerces implementation?
Jim Garrison
@Jim, I edited my answer to provide some links.
Yishai
+2  A: 

If you want to use a Xerces feature that's not exposed through an official java.* or javax.* API, then your only real solution is to include Xerces as a third-party library. Accessing the JRE-internal version of Xerces in any way would be a dangerous thing, since nothing guarantees that a valid JRE even has those classes (alternate JREs and even other versions of the same JRE might implement the JAXP APIs using a different implementation or even just move it to another package).

Joachim Sauer
This is where we started, and is the conclusion we have come to as well. If you want to use the non-Java-API parts of Xerces (specifically the serialization) then there's no way around including Xerces. We did modify our codebase to remove any explicit mention of Xerces classes in system properties, letting it use the defaults when instantiating parsers and transformers. This should prevent classloading conflicts as all the defaults are in com.sun.*
Jim Garrison