I have an Object that is being marshalled to XML using JAXB. One element contains a String that includes quotes (\"). The resulting XML has "
where t
After trying all the above solutions, finally came to the conclusion.
your marshaling logic through the custom escape handler.
final StringWriter sw = new StringWriter();
final Class classType = fixml.getClass();
final JAXBContext jaxbContext = JAXBContext.newInstance(classType);
final Marshaller marshaller = jaxbContext.createMarshaller();
final JAXBElement<T> fixmsg = new JAXBElement<T>(new QName(namespaceURI, localPart), classType, fixml);
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(CharacterEscapeHandler.class.getName(), new JaxbCharacterEscapeHandler());
marshaller.marshal(fixmsg, sw);
return sw.toString();
And the custom escape handler is as follow:
import java.io.IOException;
import java.io.Writer;
public class JaxbCharacterEscapeHandler implements CharacterEscapeHandler {
public void escape(char[] buf, int start, int len, boolean isAttValue,
Writer out) throws IOException {
for (int i = start; i < start + len; i++) {
char ch = buf[i];
out.write(ch);
}
}
}
I've been playing with your example a bit and debugging the JAXB code. And it seems it's something specific about UTF-8 encoding used. The escapeHandler property of MarshallerImpl
seems to be set properly. However it's being used not in every context. If I searched for calls of MarshallerImpl.createEscapeHandler()
I found:
public XmlOutput createWriter( OutputStream os, String encoding ) throws JAXBException {
// UTF8XmlOutput does buffering on its own, and
// otherwise createWriter(Writer) inserts a buffering,
// so no point in doing a buffering here.
if(encoding.equals("UTF-8")) {
Encoded[] table = context.getUTF8NameTable();
final UTF8XmlOutput out;
if(isFormattedOutput())
out = new IndentingUTF8XmlOutput(os,indent,table);
else {
if(c14nSupport)
out = new C14nXmlOutput(os,table,context.c14nSupport);
else
out = new UTF8XmlOutput(os,table);
}
if(header!=null)
out.setHeader(header);
return out;
}
try {
return createWriter(
new OutputStreamWriter(os,getJavaEncoding(encoding)),
encoding );
} catch( UnsupportedEncodingException e ) {
throw new MarshalException(
Messages.UNSUPPORTED_ENCODING.format(encoding),
e );
}
}
Note that in your setup the top section (...equals("UTF-8")...)
is taken into consideration. However this one doesn't take the escapeHandler
. However if you set the encoding to any other, the bottom part of this method is called (createWriter(OutputStream, String)
) and this one uses escapeHandler
, so EH plays its role.
So, adding...
marshaller.setProperty(Marshaller.JAXB_ENCODING, "ASCII");
makes your custom CharacterEscapeHandler
be called.
Not really sure, but I would guess this is kind of bug in JAXB.