JAXB将JAVA对象转换为XML时CDATA的问题

来源:互联网 发布:爱淘宝推广 编辑:程序博客网 时间:2024/05/18 00:44


对Java对象转换为xml字符串时,如果有特殊字符如<>必须要是用<![CDATA[]]>来声明。我先尝试了使用XStream解决这个问题也有使用MOXy CDATA注解解决,最后发现,都存在一定的缺陷,甚至不能正常的实现该功能。

最终解决方案有两个,都可以解决这个问题,但是第一个方案由于引用了sun的专有API,在编译时会存在警告,使用了内部的API并不是值得推荐的。但是这里也贴出来,供大家参考。

sunAPI版:

首先继承XMLSerializer

import com.sun.org.apache.xml.internal.serialize.OutputFormat;import com.sun.org.apache.xml.internal.serialize.XMLSerializer;import org.xml.sax.SAXException;import java.io.OutputStream;import java.util.regex.Pattern;public class CDataContentHandler extends XMLSerializer {    private static final Pattern XML_CHARS = Pattern.compile("[<>&]");    public CDataContentHandler( OutputStream output, OutputFormat format ) {       super(output,format);    }    public void characters(char[] ch, int start, int length) throws SAXException {        boolean useCData = XML_CHARS.matcher(new String(ch, start, length)).find();        if (useCData) super.startCDATA();        super.characters(ch, start, length);        if (useCData) super.endCDATA();    }}

实际的转换方法:

public static String ojbectToXmlWithCDATA(Class clazz, Object obj) throws Exception {JAXBContext context = JAXBContext.newInstance(clazz);OutputFormat of = new OutputFormat();of.setOmitXMLDeclaration(true);of.setPreserveSpace(true);of.setIndenting(true);ByteArrayOutputStream op = new ByteArrayOutputStream();CDataContentHandler serializer = new CDataContentHandler(op, of);SAXResult result = new SAXResult(serializer.asContentHandler());Marshaller mar = context.createMarshaller();mar.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);mar.marshal(obj, result);return op.toString("UTF-8");}

第二个方法是目前使用的方法,参考了一个国外同行的解决方法,这个解决方案将自定实现javax.xml.stream.xmlstreamwriter,没有第三方的库依赖:

执行类决定哪些地方需要添加CDATA:

import javax.xml.stream.XMLStreamException;import javax.xml.stream.XMLStreamWriter;import java.util.regex.Pattern; /** * Implementation which is able to decide to use a CDATA section for a string. */public class CDataXMLStreamWriter extends DelegatingXMLStreamWriter{   private static final Pattern XML_CHARS = Pattern.compile( "[&<>]" );    public CDataXMLStreamWriter( XMLStreamWriter del )   {      super( del );   }    @Override   public void writeCharacters( String text ) throws XMLStreamException   {      boolean useCData = XML_CHARS.matcher( text ).find();      if( useCData )      {         super.writeCData( text );      }      else      {         super.writeCharacters( text );      }   }}

委托类:

import javax.xml.namespace.NamespaceContext;import javax.xml.stream.XMLStreamException;import javax.xml.stream.XMLStreamWriter; /** * Delegating {@link XMLStreamWriter}. */abstract class DelegatingXMLStreamWriter implements XMLStreamWriter{   private final XMLStreamWriter writer;    public DelegatingXMLStreamWriter( XMLStreamWriter writer )   {      this.writer = writer;   }    public void writeStartElement( String localName ) throws XMLStreamException   {      writer.writeStartElement( localName );   }    public void writeStartElement( String namespaceURI, String localName ) throws XMLStreamException   {      writer.writeStartElement( namespaceURI, localName );   }    public void writeStartElement( String prefix, String localName, String namespaceURI ) throws XMLStreamException   {      writer.writeStartElement( prefix, localName, namespaceURI );   }    public void writeEmptyElement( String namespaceURI, String localName ) throws XMLStreamException   {      writer.writeEmptyElement( namespaceURI, localName );   }    public void writeEmptyElement( String prefix, String localName, String namespaceURI ) throws XMLStreamException   {      writer.writeEmptyElement( prefix, localName, namespaceURI );   }    public void writeEmptyElement( String localName ) throws XMLStreamException   {      writer.writeEmptyElement( localName );   }    public void writeEndElement() throws XMLStreamException   {      writer.writeEndElement();   }    public void writeEndDocument() throws XMLStreamException   {      writer.writeEndDocument();   }    public void close() throws XMLStreamException   {      writer.close();   }    public void flush() throws XMLStreamException   {      writer.flush();   }    public void writeAttribute( String localName, String value ) throws XMLStreamException   {      writer.writeAttribute( localName, value );   }    public void writeAttribute( String prefix, String namespaceURI, String localName, String value )      throws XMLStreamException   {      writer.writeAttribute( prefix, namespaceURI, localName, value );   }    public void writeAttribute( String namespaceURI, String localName, String value ) throws XMLStreamException   {      writer.writeAttribute( namespaceURI, localName, value );   }    public void writeNamespace( String prefix, String namespaceURI ) throws XMLStreamException   {      writer.writeNamespace( prefix, namespaceURI );   }    public void writeDefaultNamespace( String namespaceURI ) throws XMLStreamException   {      writer.writeDefaultNamespace( namespaceURI );   }    public void writeComment( String data ) throws XMLStreamException   {      writer.writeComment( data );   }    public void writeProcessingInstruction( String target ) throws XMLStreamException   {      writer.writeProcessingInstruction( target );   }    public void writeProcessingInstruction( String target, String data ) throws XMLStreamException   {      writer.writeProcessingInstruction( target, data );   }    public void writeCData( String data ) throws XMLStreamException   {      writer.writeCData( data );   }    public void writeDTD( String dtd ) throws XMLStreamException   {      writer.writeDTD( dtd );   }    public void writeEntityRef( String name ) throws XMLStreamException   {      writer.writeEntityRef( name );   }    public void writeStartDocument() throws XMLStreamException   {      writer.writeStartDocument();   }    public void writeStartDocument( String version ) throws XMLStreamException   {      writer.writeStartDocument( version );   }    public void writeStartDocument( String encoding, String version ) throws XMLStreamException   {      writer.writeStartDocument( encoding, version );   }    public void writeCharacters( String text ) throws XMLStreamException   {      writer.writeCharacters( text );   }    public void writeCharacters( char[] text, int start, int len ) throws XMLStreamException   {      writer.writeCharacters( text, start, len );   }    public String getPrefix( String uri ) throws XMLStreamException   {      return writer.getPrefix( uri );   }    public void setPrefix( String prefix, String uri ) throws XMLStreamException   {      writer.setPrefix( prefix, uri );   }    public void setDefaultNamespace( String uri ) throws XMLStreamException   {      writer.setDefaultNamespace( uri );   }    public void setNamespaceContext( NamespaceContext context ) throws XMLStreamException   {      writer.setNamespaceContext( context );   }    public NamespaceContext getNamespaceContext()   {      return writer.getNamespaceContext();   }    public Object getProperty( String name ) throws IllegalArgumentException   {      return writer.getProperty( name );   }}

示例方法:


    /**使用JAXB方式解决CDATA问题     *     * @throws Exception     */    public static String ojbectToXmlWithCDATA(Class clazz, Object obj) throws Exception {        JAXBContext context = JAXBContext.newInstance(clazz);        ByteArrayOutputStream op = new ByteArrayOutputStream();        XMLOutputFactory xof = XMLOutputFactory.newInstance();        XMLStreamWriter streamWriter = xof.createXMLStreamWriter(op);        CDataXMLStreamWriter cdataStreamWriter = new CDataXMLStreamWriter(streamWriter);        Marshaller mar = context.createMarshaller();        mar.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);        mar.marshal(obj, cdataStreamWriter);      cdataStreamWriter.flush();      cdataStreamWriter.close();        return op.toString("UTF-8");    }

生成后的xml代码示例:

<?xml version='1.0' encoding='utf-8'?><businessMessages xmlns="http://aaa.xxx.com/schema/BusinessMessages">    <businessMessage>        <uuid>abcccc</uuid>        <source>tms</source>        <topic>type</topic>        <bussinessNo>123</bussinessNo>        <header></header>        <body>            <![CDATA[<pivotFlow xmlns="http://aaa.xxx.com/schema/PivotFlow"><orderId>112345</orderId><operPersonId>testOper</operPersonId><operTime>2016-02-16T16:13:40.364+08:00</operTime><status>testType</status><appendix>{"shipper":"testShip","carrierPhone":"1860132223","carrier":"testCarr"}</appendix></pivotFlow>]]></body>    </businessMessage></businessMessages>


英文原文参考:http://blog.mi-ernst.de/2012/05/04/jaxb-and-cdata-sections/

博客来源:http://blog.csdn.net/wantken/article/details/50675549


1 0
原创粉丝点击