XStream 转化XML时候不能支持CDATA标签

XStream 转化XML时候不能支持CDATA标签导致部分字符被转义。


import java.io.IOException;
import java.io.Writer;

import org.apache.commons.lang.StringUtils;

import com.thoughtworks.xstream.core.util.FastStack;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;

public class MyPrettyPrintWriter implements ExtendedHierarchicalStreamWriter {

    private final QuickWriter writer;
    private final FastStack elementStack = new FastStack(16);
    private final char[] lineIndenter;

    private boolean tagInProgress;
    private int depth;
    private boolean readyForNewLine;
    private boolean tagIsEmpty;
    private boolean breakLine = false; // 是否换行

    private static final char[] AMP = "&".toCharArray();
    private static final char[] LT = "<".toCharArray();
    private static final char[] GT = ">".toCharArray();
    private static final char[] SLASH_R = " ".toCharArray();
    private static final char[] QUOT = "&quot;".toCharArray();
    private static final char[] APOS = "&apos;".toCharArray();
    private static final char[] CLOSE = "</".toCharArray();

    public TpaicPrettyPrintWriter(Writer writer, char[] lineIndenter, boolean breakLine, boolean needXMLHead, String encoding) throws IOException {
        this.writer = new QuickWriter(writer);
        this.lineIndenter = lineIndenter;
        this.breakLine = breakLine;

        // 增加XML头
        String xmlHeader = "<?xml version=\"1.0\" encoding=\"" + (StringUtils.isNotBlank(encoding) ? encoding : "GBK") + "\"?>";
        if (needXMLHead && breakLine) {
            writer.write(xmlHeader + "\n");
        }

        if (needXMLHead && !breakLine) {
            writer.write(xmlHeader);
        }
    }

    public TpaicPrettyPrintWriter(Writer writer, boolean breakLne, boolean needXMLHead, String encoding) throws IOException {
        // this(writer, new char[] { ' ', ' ' }); // 节点之间以空格分隔
        this(writer, breakLne ? new char[] { ' ', ' ' } : new char[] {}, breakLne, needXMLHead, encoding);
    }

    public TpaicPrettyPrintWriter(Writer writer, boolean breakLne) throws IOException {
        // this(writer, new char[] { ' ', ' ' }); // 节点之间以空格分隔
        this(writer, breakLne ? new char[] { ' ', ' ' } : new char[] {}, breakLne, true, "GBK");
    }

    public void startNode(String name) {
        tagIsEmpty = false;
        finishTag();
        writer.write('<');
        writer.write(name);
        elementStack.push(name);
        tagInProgress = true;
        depth++;
        readyForNewLine = true;
        tagIsEmpty = true;
    }

    @SuppressWarnings("unchecked")
    public void startNode(String name, Class clazz) {
        startNode(name);
    }

    public void setValue(String text) {
        readyForNewLine = false;
        tagIsEmpty = false;
        finishTag();

        writeText(writer, text);
    }

    public void addAttribute(String key, String value) {
        writer.write(' ');
        writer.write(key);
        writer.write('=');
        writer.write('"');
        writeAttributue(writer, value);
        writer.write('"');
    }

    protected void writeAttributue(QuickWriter writer, String text) {
        int length = text.length();
        for (int i = 0; i < length; i++) {
            char c = text.charAt(i);
            switch (c) {
                case '&':
                    this.writer.write(AMP);
                    break;
                case '<':
                    this.writer.write(LT);
                    break;
                case '>':
                    this.writer.write(GT);
                    break;
                case '"':
                    this.writer.write(QUOT);
                    break;
                case '\'':
                    this.writer.write(APOS);
                    break;
                case '\r':
                    this.writer.write(SLASH_R);
                    break;
                default:
                    this.writer.write(c);
            }
        }
    }

    protected void writeText(QuickWriter writer, String text) {
        int length = text.length();
        String CDATAPrefix = "<![CDATA[";

        if (!text.startsWith(CDATAPrefix)) {
            for (int i = 0; i < length; i++) {
                char c = text.charAt(i);
                switch (c) {
                    case '&':
                        this.writer.write(AMP);
                        break;
                    case '<':
                        this.writer.write(LT);
                        break;
                    case '>':
                        this.writer.write(GT);
                        break;
                    case '"':
                        this.writer.write(QUOT);
                        break;
                    case '\'':
                        this.writer.write(APOS);
                        break;
                    case '\r':
                        this.writer.write(SLASH_R);
                        break;
                    default:
                        this.writer.write(c);
                }
            }
        }

        else {
            for (int i = 0; i < length; i++) {
                char c = text.charAt(i);
                this.writer.write(c);
            }
        }
    }

    public void endNode() {
        depth--;
        if (tagIsEmpty) {
            writer.write('/');
            readyForNewLine = false;
            finishTag();
            elementStack.popSilently();
        } else {
            finishTag();
            writer.write(CLOSE);
            writer.write((String) elementStack.pop());
            writer.write('>');
        }
        readyForNewLine = true;
        if (depth == 0) {
            writer.flush();
        }
    }

    private void finishTag() {
        if (tagInProgress) {
            writer.write('>');
        }
        tagInProgress = false;
        if (readyForNewLine) {
            endOfLine();
        }
        readyForNewLine = false;
        tagIsEmpty = false;
    }

    protected void endOfLine() {
        if (breakLine) {// 节点是否换行,不换所有节点一行显示
            writer.write('\n');
        }
        for (int i = 0; i < depth; i++) {
            writer.write(lineIndenter);
        }
    }

    public void flush() {
        writer.flush();
    }

    public void close() {
        writer.close();
    }

    public HierarchicalStreamWriter underlyingWriter() {
        return this;
    }

}








import java.io.IOException;
import java.io.Writer;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;

public class MyXppDriver extends XppDriver {
    public static final Log logger = LogFactory.getLog(TpaicXppDriver.class);

    private boolean breakLine = false; // 是否换行

    private boolean needXmlHeader = true;

    private String encoding = "GBK"; // xml头编码方式

    public TpaicXppDriver(boolean breakLine, boolean needXmlHeader, String encoding) {
        this.breakLine = breakLine;
        this.needXmlHeader = needXmlHeader;
        this.encoding = encoding;
    }

    public TpaicXppDriver() {
        this(false, true, "GBK");
    }

    @Override
    public HierarchicalStreamWriter createWriter(Writer out) {
        HierarchicalStreamWriter writer = null;
        try {
            writer = new MyPrettyPrintWriter(out, breakLine, needXmlHeader, encoding);
        } catch (IOException e) {
            logger.error(e);
        }
        return writer;
    }
}





    public static String objectToXmlSupportCDATA(Object object, boolean format, boolean needXmlHead, String encoding) {
        XStream xstream = new XStream(new MyXppDriver(format, needXmlHead, encoding));
        xstream.autodetectAnnotations(true);
        return xstream.toXML(object);
    }

你可能感兴趣的:(xstream)