Thursday 27 September 2012

Outputting CDATA sections with JAXB

Here is a non-deprecated way to output a JAXB object model with some elements wrapped in CDATA sections.

Previously you could do this with an Apache OutputFormat as shown on the JAXB site.  This class which was non-standard, is now deprecated with a message about using the DOM Level 3 LSSerializer which is part of the Load and Save API.  I tried and tried, but I can not see a way to use that to output CDATA sections, so I have come up with a different way.

The secret is to marshal your JAXB object into a DOM and then use a null XSLT transformer.  Transformers allow you to name the elements you want wrapped in CDATA tags.

// Generating context uses resources - do it once and reuse across threads
JAXBContext jaxbContext = JAXBContext.newInstance(FWCoreContainer.class);

// Marshaller is not thread-safe
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();

// If validating using a schema
SchemaFactory factory = SchemaFactory.newInstance(
    XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = factory.newSchema(xsd.getURL());
jaxbMarshaller.setSchema(schema);

// Create an empty DOM document
// DocumentBuilderFactory is not thread-safe
DocumentBuilderFactory docBuilderFactory =
    DocumentBuilderFactory.newInstance();
Document document =
    docBuilderFactory.newDocumentBuilder().newDocument();

// Marshall the feed object into the empty document.
jaxbMarshaller.marshal(jaxbObject, document);

// Transform the DOM to the output stream
// TransformerFactory is not thread-safe
TransformerFactory transformerFactory =
    TransformerFactory.newInstance();
Transformer nullTransformer = transformerFactory.newTransformer();
nullTransformer.setOutputProperty(OutputKeys.INDENT, "yes");
nullTransformer.setOutputProperty(
    OutputKeys.CDATA_SECTION_ELEMENTS,
     "myElement myOtherElement");
nullTransformer.transform(new DOMSource(document),
     new StreamResult(writer/stream));

3 comments:

  1. Your idea is mentioned here too:

    http://stackoverflow.com/questions/3136375/how-to-generate-cdata-block-using-jaxb

    Thank you

    ReplyDelete