Add XML comments into marshaled file
Asked Answered
J

4

19

I'm marshaling objects into an XML file. How can I add comments into that XML file?

Jordanna answered 28/8, 2009 at 14:56 Comment(1)
Just in case someone managing JAXB is listening - i second the need to add comments (and newlines for pretty printing), i.e. the need to insert nodes into the DOM tree during marshalling.Vestal
A
7

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.

Arrowworm answered 28/8, 2009 at 20:48 Comment(0)
I
12

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);
Interfile answered 1/2, 2012 at 12:33 Comment(2)
Does not work with jaxb-impl-2.2.6-b35, the setProperty("com.sun.xml.internal.bind.xmlHeaders", ...) fails with PropertyExceptionOverbuild
@MartinVysny consider com.sun.xml.internal.bind.xmlHeadersLakia
A
7

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.

Arrowworm answered 28/8, 2009 at 20:48 Comment(0)
D
6

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.

Deadwood answered 13/11, 2015 at 8:36 Comment(0)
R
0

JAXBContext Marshaller in last java versions migrates some properties to org.glassfish.jaxb You can use this Java code in order to add comments to your file:

JAXBContext context = JAXBContext.newInstance(Player.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
m.setProperty("org.glassfish.jaxb.xmlHeaders", "\n<!-- Test Comment -->");
m.marshal(player, System.out);

Look at the setProperty(String name, Object value) in MarshallerImpl.java

Racecourse answered 18/8, 2023 at 8:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.