Can I force JAXB not to convert " into ", for example, when marshalling to XML?

后端 未结 14 1969
情深已故
情深已故 2020-11-29 09:27

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

相关标签:
14条回答
  • 2020-11-29 09:58

    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);
                }
        }
    }
    
    0 讨论(0)
  • 2020-11-29 10:00

    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.

    0 讨论(0)
提交回复
热议问题