編者小結:將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.csdn.net/detail/yaohucaizi/5120422下載所需jar包(免費)。
本文原創yhcz 由於總結過程實屬不易如需轉載請註明出處,謝謝。