编者小结:将java对象转换成xml文件很简单,但是将java对象转换成<![CDATA[文本内容]]>输出结果不转义的形式就相当不易。大家都知道在XML 元素中,"<" 和 "&" 是非法的。"<" 会产生错误,因为解析器会把该字符解释为新元素的开始。"&" 也会产生错误,因为解析器会把该字符解释为字符实体的开始。某些文本,比如 JavaScript 代码,包含大量 "<" 或"&" 字符。为了避免错误,可以将脚本代码定义为 CDATA。
CDATA:在标记CDATA下,所有的标记、实体引用都被忽略,而被XML处理程序一视同仁地当作字符数据看待,CDATA的形式如下:
<![CDATA[文本内容]]>
CDATA的文本内容中不能出现字符串“]]>”,另外,CDATA不能嵌套。
具体实现过程如下:
Java实体类:
publicclassJavaDocu {
privateintid;
private String text;
publicint getId() {
returnid;
}
publicvoid setId(int id) {
this.id = id;
}
public String getText() {
returntext;
}
publicvoid setText(String text) {
this.text = text;
}
}
MyXppDriver类:
publicclassMyXppDriver extends XppDriver {
public HierarchicalStreamWritercreateWriter(Writer out){
returnnew MyPrettyPrintWriter(out);
}
}
MyPrettyPrintWriter类:
publicclassMyPrettyPrintWriterimplementsExtendedHierarchicalStreamWriter {
privatefinal QuickWriter writer;
privatefinal FastStack elementStack = new FastStack(16);
privatefinalchar[] lineIndenter;
privatebooleantagInProgress;
privateintdepth;
privatebooleanreadyForNewLine;
privatebooleantagIsEmpty;
privatestaticfinalchar[] AMP = "&".toCharArray();
privatestaticfinalchar[] LT = "<".toCharArray();
privatestaticfinalchar[] GT = ">".toCharArray();
privatestaticfinalchar[] SLASH_R = " ".toCharArray();
privatestaticfinalchar[] QUOT = """.toCharArray();
privatestaticfinalchar[] APOS = "'".toCharArray();
privatestaticfinalchar[] CLOSE = "</".toCharArray();
publicMyPrettyPrintWriter(Writer writer, char[] lineIndenter) {
this.writer = new QuickWriter(writer);
this.lineIndenter = lineIndenter;
}
publicMyPrettyPrintWriter(Writer writer, String lineIndenter) {
this(writer,lineIndenter.toCharArray());
}
public MyPrettyPrintWriter(PrintWriterwriter) {
this(writer, newchar[] { ' ', ' ' });
}
publicMyPrettyPrintWriter(Writer writer) {
this(new PrintWriter(writer));
}
@Override
publicvoid addAttribute(Stringkey, String value) {
writer.write(' ');
writer.write(key);
writer.write('=');
writer.write('\"');
writeAttributeValue(writer, value);
writer.write('\"');
}
protectedvoidwriteAttributeValue(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);
}
}
}
@Override
publicvoid 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();
}
}
@Override
publicvoid setValue(String text) {
readyForNewLine = false;
tagIsEmpty = false;
finishTag();
writeText(writer, text);
}
protectedvoid writeText(QuickWriterwriter, String text) {
int length = text.length();
StringCDATAPrefix = "<![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);
}
}
}
@Override
publicvoid startNode(String name){
tagIsEmpty = false;
finishTag();
writer.write('<');
writer.write(name);
elementStack.push(name);
tagInProgress = true;
depth++;
readyForNewLine = true;
tagIsEmpty = true;
}
privatevoid finishTag() {
if (tagInProgress) {
writer.write('>');
}
tagInProgress = false;
if (readyForNewLine) {
endOfLine();
}
readyForNewLine = false;
tagIsEmpty = false;
}
protectedvoid endOfLine() {
writer.write('\n');
for (int i = 0; i < depth; i++) {
writer.write(lineIndenter);
}
}
publicvoid flush() {
writer.flush();
}
publicvoid close() {
writer.close();
}
@Override
publicHierarchicalStreamWriter underlyingWriter() {
returnthis;
}
@Override
publicvoid startNode(String name, @SuppressWarnings("rawtypes")Class arg1) {
// TODO Auto-generated method stub
tagIsEmpty = false;
finishTag();
writer.write('<');
writer.write(name);
elementStack.push(name);
tagInProgress = true;
depth++;
readyForNewLine = true;
tagIsEmpty = true;
}
}
Java测试类:
publicclassJavaDocuTest {
publicstaticvoid main(String[] args) throws IOException,JAXBException {
Long t1 = System.currentTimeMillis();
StringCDATAPrefix = "<![CDATA[";
StringCDATABackfix = "]]>";
JavaDocujavadocu = newJavaDocu();
JavaDocujavadocu2 = newJavaDocu();
javadocu.setText(CDATAPrefix+ "这是一个测试" + CDATABackfix);
javadocu2.setText(CDATAPrefix+ "这又是一个测试" + CDATABackfix);
List<JavaDocu>list = newArrayList<JavaDocu>();
list.add(javadocu);
list.add(javadocu2);
XStreamxstream = newXStream(newMyXppDriver());
for (int i = 0; i <list.size(); i++) {
list.get(i).setId(i);
xstream.alias("javatoxml",JavaDocu.class);
xstream.useAttributeFor(JavaDocu.class, "id");
// xstream.useAttributeFor("id",String.class);
}
System.out.println(xstream.toXML(list));
xstream.toXML(list, new PrintWriter("c:\\测试.xml", "utf-8"));
}
}
以上代码可实现将javabean转换成包含<![CDATA[文本内容]]>的xml文件。
温馨提示:此过程使用xstream.1.3.1.jar,请到http://download.youkuaiyun.com/detail/yaohucaizi/5120422下载所需jar包(免费)。
本文原创yhcz 由于总结过程实属不易如需转载请注明出处,谢谢!