I\'m marshaling objects into an XML file. How can I add comments into that XML file?
If anyone comes to this now, like I just did, it is worth pointing out that the property to do this is now com.sun.xml.bind.xmlHeaders
(no longer internal it seems), so you can solve the problem like this (I have only tried it with EclipseLink MOXY):
JAXBContext context = JAXBContext.newInstance(Player.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
m.setProperty("com.sun.xml.bind.xmlHeaders", "\n<!-- Test Comment -->");
m.marshal(player, System.out);
The following information originally comes from Marshaller Properties in the JAXB RI Extensions documentation on jaxb.java.net:
XML Preamble Control
This property allows you to specify an XML preamble ( declaration) and any additional PIs, comments, DOCTYPE declaration that follows it. This property takes effect only when you are marshalling to OutputStream, Writer, or StreamResult. Note that this property interacts with the Marshaller.JAXB_FRAGMENT property. If that property is untouched or set to false, then JAXB would always write its XML preamble, so this property can be only used to write PIs, comments, DOCTYPE, etc. On the other hand, if it is set to true, then JAXB will not write its own XML preamble, so this property may contain custom XML preamble.
I do not see a way to do it with JAXB alone. However, I think you can leverage DOM to get the desired effect:
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
final DocumentBuilder builder = factory.newDocumentBuilder();
final Document doc = builder.getDOMImplementation().createDocument(null, null, null);
final Binder<Node> binder = jaxbContext.createBinder();
binder.marshal(jaxbObject, doc);
final Comment comment = doc.createComment("This is a comment");
doc.appendChild(comment);
final DOMSource domSource = new DOMSource(doc);
// use System.out for testing
final StreamResult streamResult = new StreamResult(System.out);
final TransformerFactory tf = TransformerFactory.newInstance();
final Transformer serializer = tf.newTransformer();
serializer.transform(domSource, streamResult);
Where jaxbContext is the JAXBContext object you are working with and jaxbObject is the object to be marshalled. This sample just appends the comment to the end of the document. For a different location, you would have to traverse the DOM through the doc object or use XPath to find the exact element you want the comment added to and use appendChild on it.
You can add comments right after the preamble with the proprietary Marshaller property com.sun.xml.bind.xmlHeaders (see XML Preamble Control)
In the included JAXB-implementation jdk1.6.0_29 the property is called "com.sun.xml.internal.bind.xmlHeaders"
See also question: How to add DOCTYPE and xml processing instructions when marshalling with JAXB?
So to get this XML with the test-comment after the preamble:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- Test Comment -->
<player>
<name>Daniel</name>
<birthday>1982-06-09T00:00:00+02:00</birthday>
</player>
You can use this Java-Code:
JAXBContext context = JAXBContext.newInstance(Player.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
m.setProperty("com.sun.xml.internal.bind.xmlHeaders", "\n<!-- Test Comment -->");
m.marshal(player, System.out);