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
Solution my teammate found:
PrintWriter printWriter = new PrintWriter(new FileWriter(xmlFile));
DataWriter dataWriter = new DataWriter(printWriter, "UTF-8", DumbEscapeHandler.theInstance);
marshaller.marshal(request, dataWriter);
Instead of passing the xmlFile to marshal(), pass the DataWriter which knows both the encoding and an appropriate escape handler, if any.
Note: Since DataWriter and DumbEscapeHandler are both within the com.sun.xml.internal.bind.marshaller package, you must bootstrap javac.
The simplest way, when using sun's Marshaller implementation is to provide your own implementation of the CharacterEscapeEncoder which does not escape anything.
Marshaller m = jcb.createMarshaller();
m.setProperty(
"com.sun.xml.bind.marshaller.CharacterEscapeHandler",
new NullCharacterEscapeHandler());
With
public class NullCharacterEscapeHandler implements CharacterEscapeHandler {
public NullCharacterEscapeHandler() {
super();
}
public void escape(char[] ch, int start, int length, boolean isAttVal, Writer writer) throws IOException {
writer.write( ch, start, length );
}
}
I have just made my custom handler as a class like this:
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import com.sun.xml.bind.marshaller.CharacterEscapeHandler;
public class XmlCharacterHandler implements CharacterEscapeHandler {
public void escape(char[] buf, int start, int len, boolean isAttValue,
Writer out) throws IOException {
StringWriter buffer = new StringWriter();
for (int i = start; i < start + len; i++) {
buffer.write(buf[i]);
}
String st = buffer.toString();
if (!st.contains("CDATA")) {
st = buffer.toString().replace("&", "&").replace("<", "<")
.replace(">", ">").replace("'", "'")
.replace("\"", """);
}
out.write(st);
System.out.println(st);
}
}
in the marshaller method simply call:
marshaller.setProperty(CharacterEscapeHandler.class.getName(),
new XmlCharacterHandler());
it works fine.
This works for me after reading other posts:
javax.xml.bind.JAXBContext jc = javax.xml.bind.JAXBContext.newInstance(object);
marshaller = jc.createMarshaller(); marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_ENCODING, "UTF-8"); marshaller.setProperty(CharacterEscapeHandler.class.getName(), new CustomCharacterEscapeHandler());
public static class CustomCharacterEscapeHandler implements CharacterEscapeHandler {
/**
* Escape characters inside the buffer and send the output to the Writer.
* (prevent <b> to be converted <b> but still ok for a<5.)
*/
public void escape(char[] buf, int start, int len, boolean isAttValue, Writer out) throws IOException {
if (buf != null){
StringBuilder sb = new StringBuilder();
for (int i = start; i < start + len; i++) {
char ch = buf[i];
//by adding these, it prevent the problem happened when unmarshalling
if (ch == '&') {
sb.append("&");
continue;
}
if (ch == '"' && isAttValue) {
sb.append(""");
continue;
}
if (ch == '\'' && isAttValue) {
sb.append("'");
continue;
}
// otherwise print normally
sb.append(ch);
}
//Make corrections of unintended changes
String st = sb.toString();
st = st.replace("&quot;", """)
.replace("&lt;", "<")
.replace("&gt;", ">")
.replace("&apos;", "'")
.replace("&amp;", "&");
out.write(st);
}
}
}
interesting but with strings you can try out
Marshaller marshaller = jaxbContext.createMarshaller();
StringWriter sw = new StringWriter();
marshaller.marshal(data, sw);
sw.toString();
at least for me this do not escape quotes
For some reason I have no time to find out, it worked for me when setting
marshaller.setProperty(Marshaller.JAXB_ENCODING, "utf-8");
As opposed to using "UTF-8"
or "Unicode"
I suggest you try them, and as @Javatar said, check them dumping to file using:
marshaller.marshal(shipOrder, new File("<test_file_path>"));
and opening it with a a decent text editor like notepad++