java生成xml文件的時候如何控制xml的縮進(jìn)格式
使用java自帶的xml api生成的xml文件,其格式都是沒有縮進(jìn)的,每個element都是頂?shù)阶钋懊?今天終于找到了比較好的處理方法,趕緊記下來.
使用Java標(biāo)準(zhǔn)的JAXP來輸出可以使用:
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.transform(new DOMSource(document), new StreamResult(outputFile));
中間的紅色代碼是用于設(shè)置縮進(jìn)的,比較遺憾的是JAXP只抽象出是否設(shè)置縮進(jìn)(indent: yes|no),但并沒有抽象出設(shè)置縮進(jìn)量長度的常量(indent-number),所以默認(rèn)的縮進(jìn)量長度為0。如果有下面這樣一個xml文檔:<root><a><b>c</b></a></root>會被格式化為:
<root>
<a>
<b>c</b>
</a>
</root>
由于JAXP只是一個Java一個處理XML的框架,根據(jù)實現(xiàn)的不一樣,可以傳入實現(xiàn)特定的某個Key來設(shè)置縮進(jìn)量。比如在Java 1.4下面,可以通過下面語句將縮進(jìn)量設(shè)為2:
ransformer.setOutputProperty(
"{http://xml.apache.org/xslt}indent-amount", "2");
或
transformer.setOutputProperty(
"{http://xml.apache.org/xalan}indent-amount", "2");
上面兩句不同之處僅在于命名空間。
而在Java 1.5下面,情況就有些復(fù)雜了。Java 1.5集成了JXAP 1.3(Java 1.4集成的是JXAP 1.1,不同之處參見http://java.sun.com/j2se/1.5.0/docs/guide/xml/jaxp/JAXP-Compatibility_150.html),實現(xiàn)基于Xerces類庫。由于內(nèi)部實現(xiàn)上的Bug,導(dǎo)致了設(shè)置縮進(jìn)的不同:
TransformerFactory tf = TransformerFactory.newInstance();
tf.setAttribute("indent-number", new Integer(2));
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.transform(new DOMSource(document), new StreamResult(new?BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputFile)))));
注意紅色代碼的不同之處。第一句設(shè)置TransformerFactory的indent-number屬性,在Java 1.4下面運行會拋出異常,因為其不支持該屬性,而在Java 1.5中卻只能通過該屬性來設(shè)置縮進(jìn)。后面標(biāo)為紅色的代碼則是由于Sun實現(xiàn)上的Bug,只有通過StreamResult(Writer)構(gòu)造函數(shù)生成才能正確設(shè)置縮進(jìn)(通過OutputStream或者File生成的StreamResult是無法設(shè)置縮進(jìn)的,其實現(xiàn)上會忽略任何非正式的屬性,而僅僅采用rt.jar下面com\sun\org\apache\xml\internal\serializer\output_xml.properties中的配置。詳細(xì)可以在com.sun.org.apache.xml.internal.serializer.ToStream類的setOutputStream方法中加斷點進(jìn)行分析)
?
如果忽略掉可移植性,確認(rèn)綁定在Sun的JRE實現(xiàn)上面,則可以通過如下代碼來更好的實現(xiàn):
OutputFormat format = new OutputFormat(document);
format.setIndenting(true);
format.setIndent(2);
Writer output = new BufferedWriter( new FileWriter(outputFile) );
XMLSerializer serializer = new XMLSerializer(output, format);
serializer.serialize(document);
但是OutputFormat類和XMLSerializer類都是位于com.sun.org.apache.xml.internal.serialize包下。
如果應(yīng)用對增加一個300K左右的jar包不敏感的話,我還是強烈推薦用dom4j來處理xml,其API設(shè)計的非常易用,寫出來的代碼比用JXAP寫出來的代碼漂亮多了,也容易維護(hù),也不會出現(xiàn)上面那種兩個Java版本不兼容的問題。