11

I am currently using the following code to marshal an object into an xml string

    JAXBContext context;

    try {
        context = JAXBContext.newInstance(heartbeat.getClass());
        StringWriter writer = new StringWriter();
        Marshaller marshaller = context.createMarshaller();

        heartbeat.setHeader(header);
        heartbeat.setHeartbeatEvent(event);

        marshaller.marshal(heartbeat, writer);
        String stringXML = writer.toString();
        return stringXML;

    } catch (JAXBException e) {
        throw new RuntimeException("Problems generating XML in specified "
                + "encoding, underlying problem is " + e.getMessage(),
                e);
    }

Which produces the following header

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

My desired output is the following

<?xml version=\"1.0\"?>

By adding this to the marshaller

marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.FALSE);
marshaller.setProperty("com.sun.xml.bind.xmlHeaders", "<?xml version=\"1.0\"?>");

I receive

<?xml version="1.0" encoding="UTF-8" standalone="yes"?><?xml version="1.0"?>

and changing the JAXB_FRAGMENT property to TRUE removes the header entirely. I have been following the JAXB - Remove 'standalone="yes"' from generated XML thread attempting to solve the problem but I have had no luck so far. Can someone please give me some insight on how to get my desired header from the JAXB marshaller?

Community
  • 1
  • 1
JME
  • 2,293
  • 9
  • 36
  • 56

3 Answers3

25

When marshalling to an OutputStream using a combination of the following produces the expected output.

    marshaller.setProperty("com.sun.xml.bind.xmlHeaders", "<?xml version=\"1.0\"?>");
    marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);

The problem you are seeing occurs when you marshal to a Writer, which appears to be a bug in the JAXB reference implementation. You can raise an issue at the link below:


You could always do:

JAXBContext context;

try {
    context = JAXBContext.newInstance(heartbeat.getClass());
    StringWriter writer = new StringWriter();
    writer.append("<?xml version=\"1.0\"?>");
    Marshaller marshaller = context.createMarshaller();
    marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);

    heartbeat.setHeader(header);
    heartbeat.setHeartbeatEvent(event);

    marshaller.marshal(heartbeat, writer);
    String stringXML = writer.toString();
    return stringXML;

} catch (JAXBException e) {
    throw new RuntimeException("Problems generating XML in specified "
            + "encoding, underlying problem is " + e.getMessage(),
            e);
}

EclipseLink JAXB (MOXy) also supports the com.sun.xml.bind.xmlHeaders and it works correctly when marshalling to a Writer (I'm the MOXy lead)

Pyves
  • 6,333
  • 7
  • 41
  • 59
bdoughan
  • 147,609
  • 23
  • 300
  • 400
7

This worked for me

marshaller.setProperty("com.sun.xml.internal.bind.xmlHeaders", "<?xml version=\"1.0\" encoding=\"UTF-8\"?>");

Gopi Krishna
  • 119
  • 2
  • 3
  • 3
    "com.sun.xml.internal.bind.xmlHeaders" works when using jaxb from jdk 1.8 (at least on windows with java 1.8.0_60) – dosw Feb 03 '16 at 16:13
3

In JAXB 3.0.1 the above mentioned constants cause a PropertyException:

 jakarta.xml.bind.PropertyException: name: com.sun.xml.bind.xmlDeclaration value: false

In this case, the XML preamble can be configured with these marshaller constants:

marshaller.setProperty("org.glassfish.jaxb.xmlHeaders", "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
plejaden
  • 31
  • 4