廢話很少說,寫此文檔的目的就是爲了幫助java開發者,解決利用JAXB生成XML時,XML中帶有CDATA問題。java
分三步走:框架
首先建立適配器類:CDataAdapter.javaide
package com.zhaoyx;工具
import javax.xml.bind.annotation.adapters.XmlAdapter;測試
//有時候 Java 類不能天然映射到本身所需的 XML 形式,this
//這時須要編寫本身的適配器類,經過註解綁定到javabean的成員變量上,spa
//在運行的時候jaxb框架自動會適配你所編寫的適配器類的方法,.net
//CDataAdapter.marshal(String str),將javabean的成員變量的value值xml
//轉變成你想要的形式。開發
public class CDataAdapter extends XmlAdapter<String, String> {
//從javabean到xml的適配方法
@Override
public String marshal(String str) throws Exception {
return "<![CDATA[" + str+ "]]>";
}
//從xml到javabean的適配方法
@Override
public String unmarshal(String str) throws Exception {
return str;
}
}
其次建立JAXB生成XML的工具類:JaxbToXmlUtil.java
package com.zhaoyx;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler;
//這裏用到了JAXB的核心類和方法,不懂能夠去查看下JAXB基礎應用,
//這裏只作關鍵解釋。
public class JaxbToXmlUtil {
public static String convertToXml(Object obj, String encoding) {
String result = null;
try {
JAXBContext context = JAXBContext.newInstance(obj.getClass());
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(Marshaller.JAXB_ENCODING, encoding);
//去掉生成xml的默認報文頭。
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
//轉換全部的適配字符,包括xml實體字符<和>,xml實體字符在好多處理xml
//的框架中是處理不了的,除非序列化。
marshaller.setProperty("com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler",
new CharacterEscapeHandler() {
@Override
public void escape(char[] ch, int start,int length, boolean isAttVal,
Writer writer) throws IOException {
writer.write(ch, start, length);
}
});
StringWriter writer = new StringWriter();
//添加本身想要的xml報文頭
writer.write("<?xml version=\'1.0\' encoding=\'" + encoding + "\'?>\n");
marshaller.marshal(obj, writer);
result = writer.toString();
} catch (JAXBException e) {
e.printStackTrace();
}
return result;
}
}
最後建立用於轉換成XML文件的javabean:Root.java
package com.zhaoyx;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
//綁定本身的適配器類,適配但願包含在CData數據塊中的javabean成員變量。
//這裏的空值是爲了測試,無其餘涵義。
@XmlJavaTypeAdapter(CDataAdapter.class)
private String name = "";
@XmlJavaTypeAdapter(CDataAdapter.class)
private String surname;
private String id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
上面三步就能夠解決利用JAXB生成XML時,XML中包含CDATA數據塊的問題。
下面是用於測試的類:JaxbTest.java
package com.zhaoyx;
public class JaxbTest {
public static void main(String[] arg) {
Root root = new Root();
root.setId("ddd");
root.setSurname("jiiii");
//因爲在javabean中賦值爲空,這句能夠不要,也能夠去掉javabean中的賦空值語句
root.setName("");
String str = JaxbToXmlUtil.convertToXml(root, "GBK");
System.out.println(str);
}
}
控制檯輸出結果:
<?xml version='1.0' encoding='GBK'?> <root> <name><![CDATA[]]></name> <surname><![CDATA[jiiii]]></surname> <id>ddd</id> </root>