Canonical XML Support in the JAXB RI

The JAXB RI marshaller or JAXBRIContext can be configured to marshal canonical XML. There are two ways to do this:

  1. If you know in advance that you'll need c14n, use JAXBRIContext.newInstance(java.lang.Class[], java.util.Collection, java.util.Map, java.lang.String, boolean, com.sun.xml.bind.v2.model.annotation.RuntimeAnnotationReader) to create a new JAXBContext with c14n. In this way, every marshaller created from this JAXBRIContext will do c14n.
  2. use Marshaller.setProperty(String, Object) with JAXBRIContext.CANONICALIZATION_SUPPORT to enable c14n on a marshaller instance.

The first option runs faster, because the JAXB RI can do a better optimization, but the end result is the same.

Supported C14n Modes

Inclusive Canonicalization

The generated canonical XML documents will follow the Canonical XML spec provided that you marshal it to UTF-8 (which is the spec requirement) and don't turn on the formatting.

When using JAXB to marshal a tree canonically to be a subtree of a bigger document, you also need to use NamespacePrefixMapper with the marshaller. In particular, use NamespacePrefixMapper.getPreDeclaredNamespaceUris2() to make sure that the marshalling does not produce redundant namespace declarations at the first element it marshals. See below:


 <root xmlns="foo">
   <abc>
     ... suppose you are marshalling a subtree into here ...
   </abc>
 </root>

 [[ if you don't use NamespacePrefixMapper ]]
 <root xmlns="foo">
   <abc>
     <child xmlns="foo">
       <bar/>
     </child>
   </abc>
 </root>

 [[ use NamespacePrefixMapper and return "","foo" to get this ]]
 <root xmlns="foo">
   <abc>
     <child>
       <bar/>
     </child>
   </abc>
 </root>
 

Exclusive Canonicalization

JAXB RI doesn't support exclusive canonicalization (xc14n) in its full generality, but it can be used to performa xc14n if the application is in position to choose the list of "inclusive namespaces" (which is the most normal case.)

IOW, this support can be used when c14n is for producing a new signature.

The exclusive c14n support in JAXB can be done by making "inclusive namespaces" an union of (1) all the namespace URIs statically known to JAXB RI and (2) all in-scope namespace bindings available at ancestors. This effectively reduces xc14n to inclusive c14n.

Specifically, the calling application should do the followings:

  1. List up all the in-scope namespaces declared in ancestor elements, and add them to the inclusive namespace prefix list.
  2. Do not

Unsupported Features

When canonicalizing a subtree, the canonical XML spec requires the xml attributes (such as xml:lang, xml:base) on ancestor elements to be copied over to the root of the canonical subtree. This behavior is not implemented.

Call For Help

The reason this feature is experimental is because the JAXB team feels uncomfortable with the understanding of the c14n specs. Therefore, we'd like to be able to change the way this mechanism works as we go forward, and that's why this feature is an experimental vendor extension. Any feedback on this feature is greatly appreciated.

Internals

The c14n support in JAXBRIContext causes the marshaller to write "known" attributes in the lexicographical order (except those attributes in the attribute wildcard.)

If the object tree to be marshalled doesn't contain any attribute wildcard, the marshalling performs almost as fast as the ordinary marshalling mode. The only additional cost is:

  1. buffering of attributes
  2. bubble-sorting of namespace declarations

See Also:
JAXBRIContext.CANONICALIZATION_SUPPORT