public void write (OutputStream out) throws IOException public void write (Writer out) throws IOException public void write (Writer out, String encoding) throws IOException |
String name="fancy"; DocumentBuilder parser; DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); try { parser = factory.newDocumentBuilder(); Document doc = parser.parse("user.xml"); Element newlink=doc.createElement(name); doc.getDocumentElement().appendChild(newlink); ((XmlDocument)doc).write(new FileOutputStream(new File("xuser1.xml"))); } catch (Exception e) { //to log it } |
在上面的代碼中,首先創(chuàng)建了一個(gè)Document對(duì)象doc,獲取完整的DOM Tree,然后應(yīng)用Node接口的appendChild()方法,在DOM Tree的最后追加了一個(gè)新節(jié)點(diǎn)(fancy),最后調(diào)用XmlDocument類的write(OutputStream out)方法,把DOM Tree中的內(nèi)容輸出到xuser.xml中(其實(shí)也可以輸出到user.xml,更新原始的XML文檔,在這里為了便于做對(duì)比,故而輸出到xuser.xml文件中)。需要注意的是不能直接對(duì)Document對(duì)象doc直接調(diào)用write()方法,因?yàn)镴AXP的Document接口并沒有定義任何write()方法,所以必須將doc由Document對(duì)象強(qiáng)制轉(zhuǎn)換為XmlDocument對(duì)象,然后才能調(diào)用write()方法,在上面的代碼中使用的是write(OutputStream out)方法,這個(gè)方法使用缺省的UTF-8編碼輸出DOM Tree中的內(nèi)容到特定的輸出介質(zhì)中,如果DOM Tree中包含中文字符,那么輸出的結(jié)果有可能是亂碼,亦即存在所謂的"漢字問題",解決的辦法是使用write (Writer out, String encoding)方法,顯式指定輸出時(shí)的編碼,例如將第二個(gè)參數(shù)設(shè)為"GB2312",這時(shí)即不存在"漢字問題",輸出結(jié)果能夠正常顯示中文字符。
完整的例子請(qǐng)參考下列文件: AddRecord.java(見附件)、user.xml(見附件)。該例子的運(yùn)行環(huán)境為:Windows XP Professional、JDK 1.3.1。為了能夠正常編譯運(yùn)行AddRecord.java這個(gè)程序,你需要到網(wǎng)址http://xml.apache.org/dist/crimson/去下載Apache Crimson,并將所獲取的crimson.jar文件加入到環(huán)境變量CLASSPATH中。
注意:
Apache Crimson的前身是Sun Project X Parser,后來不知何故,由X Parser演變?yōu)锳pache Crimson,至今Apache Crimson的很多代碼都是從X Parser中直接移植過來的。比如上文用到的XmlDocument類,它在X Parser中是com.sun.xml.XmlDocument,到了Apache Crimson中搖身一變,就變成了org.apache.crimson.tree.XmlDocument類,其實(shí)它們的絕大部分代碼是一樣的,可能就package語句和import語句以及文件開頭的一段lience有所不同而已。早期的JAXP是和X Parser捆綁在一起的,因此一些老的程序使用了com.sun.xml包,如果你現(xiàn)在重新編譯它們,有可能不能通過,肯定就是因?yàn)檫@個(gè)原因。后來的JAXP和Apache Crimson捆綁在一起,比如JAXP 1.1,如果你使用JAXP 1.1,那么不需要額外下載Apache Crimson,也能夠正常編譯運(yùn)行上面的例子(AddRecord.java)。最新的JAXP 1.2 EA(Early Access)改弦更張,采用性能更好的Apache Xalan和Apache Xerces分別作為XSLT處理器和XML解析器,不能直接支持Apache Crimson了,所以如果你的開發(fā)環(huán)境采用了JAXP 1.2 EA或者是Java XML Pack(內(nèi)含JAXP 1.2 EA),那么將無法直接編譯運(yùn)行上面的例子(AddRecord.java),你需要額外下載并安裝Apache Crimson。
方法三:使用TransformerFactory和Transformer類
在JAXP中所提供的標(biāo)準(zhǔn)的更新原始XML文檔的方法就是調(diào)用XSLT引擎,亦即使用TransformerFactory和Transformer類。請(qǐng)看下面的Java代碼片斷:
//首先創(chuàng)建一個(gè)DOMSource對(duì)象,該構(gòu)造函數(shù)的參數(shù)可以是一個(gè)Document對(duì)象 //doc代表更改后的DOM Tree。 DOMSource doms = new DOMSource (doc); //創(chuàng)建一個(gè)File對(duì)象,代表DOM Tree所包含的數(shù)據(jù)的輸出介質(zhì),這是一個(gè)XML文件。 File f = new File ("XMLOutput.xml"); //創(chuàng)建一個(gè)StreamResult對(duì)象,該構(gòu)造函數(shù)的參數(shù)可以取為File對(duì)象。 StreamResult sr = new StreamResult (f); //下面調(diào)用JAXP中的XSLT引擎來實(shí)現(xiàn)輸出DOM Tree中的數(shù)據(jù)到XML文件中的功能。 //XSLT引擎的輸入為DOMSource對(duì)象,輸出為StreamResut對(duì)象。 try { //首先創(chuàng)建一個(gè)TransformerFactory對(duì)象,再由此創(chuàng)建Transformer對(duì)象。Transformer //類相當(dāng)于一個(gè)XSLT引擎。通常我們使用它來處理XSL文件,但是在這里我們使 //用它來輸出XML文檔。 TransformerFactory tf=TransformerFactory.newInstance(); Transformer t=tf.newTransformer (); //關(guān)鍵的一步, 調(diào)用Transformer對(duì)象 (XSLT引擎)的transform()方法,該方法的第一 //個(gè)參數(shù)是DOMSource對(duì)象,第二個(gè)參數(shù)是StreamResult對(duì)象。 t.transform(doms,sr); } catch (TransformerConfigurationException tce) { System.out.println("Transformer Configuration Exception -----"); tce.printStackTrace(); } catch (TransformerException te) { System.out.println ("Transformer Exception ---------"); te.printStackTrace (); } |
在實(shí)際的應(yīng)用中,我們可以應(yīng)用傳統(tǒng)的DOM API從XML文檔中獲取DOM Tree,然后根據(jù)實(shí)際的需求對(duì)DOM Tree執(zhí)行各種操作,得到最終的Document對(duì)象,接下來可以由此Document對(duì)象創(chuàng)建DOMSource對(duì)象,剩下的事情就是照搬上面的代碼了,程序運(yùn)行完畢后, XMLOutput.xml就是你所需要的結(jié)果(當(dāng)然了,你可以隨意更改StreamResult類構(gòu)造函數(shù)的參數(shù),指定不同的輸出介質(zhì),而不必是千篇一律的XML文檔)。
這個(gè)方法最大的好處在于可以隨心所欲的控制DOM Tree中的內(nèi)容輸出到輸出介質(zhì)中的格式,但是光靠TransformerFactory類和Transformer類并不能實(shí)現(xiàn)這個(gè)功能,還需要依賴OutputKeys類的幫助。 完整的例子請(qǐng)參考下列文件: AddRecord2.java(見附件)、user.xml(見附件)。該例子的運(yùn)行環(huán)境為:Windows XP Professional、JDK 1.3.1。為了能夠正常編譯運(yùn)行AddRecord2.java這個(gè)程序,你需要到網(wǎng)址http://java.sun.com去下載安裝JAXP 1.1或者Java XML Pack(Java XML Pack已經(jīng)內(nèi)含JAXP了)。
OutputKeys類
javax.xml.transform.OutputKeys類和java.util.Properties類配合使用,可以控制JAXP的XSLT引擎(Transformer類)輸出XML文檔的格式。請(qǐng)看下面的代碼片斷:
//首先創(chuàng)建一個(gè)TransformerFactory對(duì)象,再由此創(chuàng)建Transformer對(duì)象。 TransformerFactory tf=TransformerFactory.newInstance(); Transformer t=tf.newTransformer (); //獲取Transformser對(duì)象的輸出屬性,亦即XSLT引擎的缺省輸出屬性,這是一個(gè) //java.util.Properties對(duì)象。 Properties properties = t.getOutputProperties(); //設(shè)置新的輸出屬性:輸出字符編碼為GB2312,這樣可以支持中文字符,XSLT引擎所輸出 //的XML文檔如果包含了中文字符,可以正常顯示,不會(huì)出現(xiàn)所謂的"漢字問題"。 //請(qǐng)留意OutputKeys類的字符串常數(shù)OutputKeys.ENCODING。 properties.setProperty(OutputKeys.ENCODING,"GB2312"); /更新XSLT引擎的輸出屬性。 t.setOutputProperties(properties); //調(diào)用XSLT引擎,按照輸出屬性中的設(shè)置,輸出DOM Tree中的內(nèi)容到輸出介質(zhì)中。 t.transform(DOMSource_Object,StreamResult_Object); |
從上面的程序代碼,我們不難看出,通過設(shè)置XSLT引擎(Transformer類)的輸出屬性,可以控制DOM Tree中的內(nèi)容的輸出格式,這對(duì)于我們定制輸出內(nèi)容是很有幫助的。那么JAXP的XSLT引擎(Transformer類)有那些輸出屬性可以設(shè)置呢? javax.xml.transform.OutputKeys類定義了很多字符串常數(shù),它們都是可以自由設(shè)置的輸出屬性,常用的輸出屬性如下所示:
public static final java.lang.String METHOD |
可以設(shè)為"xml"、"html"、"text"等值。
public static final java.lang.String VERSION |
所遵循規(guī)范的版本號(hào),如果METHOD設(shè)為"xml",那么它的值應(yīng)該設(shè)為"1.0",如果METHOD設(shè)為"html",那么它的值應(yīng)該設(shè)為"4.0",如果METHOD設(shè)為"text",那么這個(gè)輸出屬性會(huì)被忽略。
public static final java.lang.String ENCODING |
設(shè)置輸出時(shí)所采用的編碼方式,比如"GB2312"、"UTF-8"等等,如果將其設(shè)置為"GB2312",可以解決所謂的"漢字問題"。
public static final java.lang.String OMIT_XML_DECLARATION |
設(shè)置輸出到XML文檔中時(shí)是否忽略XML聲明,亦即類似于:
<?xml version="1.0" standalone="yes" encoding="utf-8" ?> |
這樣的代碼。它可選的值有"yes"、"no"。
public static final java.lang.String INDENT |
IDENT設(shè)定XSLT引擎在輸出XML文檔時(shí),是否自動(dòng)添加額外的空格,它可選的值為"yes"、"no"。
public static final java.lang.String MEDIA_TYPE |
MEDIA_TYPE設(shè)定輸出文檔的MIME類型。
如果設(shè)定XSLT引擎的輸出屬性呢?下面我們來總結(jié)一下:
首先是獲取XSLT引擎(Transformer類)的缺省輸出屬性的集合,這需要使用Transformer類的getOutputProperties()方法,返回值是一個(gè)java.util.Properties對(duì)象。
Properties properties = transformer.getOutputProperties(); |
然后是設(shè)定新的輸出屬性,比如:
properties.setProperty(OutputKeys.ENCODING,"GB2312"); properties.setProperty(OutputKeys.METHOD,"html"); properties.setProperty(OutputKeys.VERSION,"4.0"); ……………………………………………………… |
最后是更新XSLT引擎(Transformer類)的缺省輸出屬性的集合,這需要使用Transformer類的setOutputProperties()方法,參數(shù)是一個(gè)java.util.Properties對(duì)象。
我們編寫了一個(gè)新的程序,其中應(yīng)用了OutputKeys類,用以控制XSLT引擎的輸出屬性,該程序的架構(gòu)和前一個(gè)程序(AddRecord3.java)大致相同,不過輸出結(jié)果略有不同。完整的代碼請(qǐng)參考下列文件: AddRecord3.java(見附件)、user.xml(見附件)。該例子的運(yùn)行環(huán)境為:Windows XP Professional、JDK 1.3.1。為了能夠正常編譯運(yùn)行AddRecord3.java這個(gè)程序,你需要到網(wǎng)址http://java.sun.com去下載安裝JAXP 1.1或者Java XML Pack(Java XML Pack內(nèi)含JAXP了)。
方法四:使用Xalan XML Serializer
方法四其實(shí)是方法三的一個(gè)變種,它需要Apache Xalan和Apache Xerces的支持才能夠運(yùn)行。例子代碼如下所示: //首先創(chuàng)建一個(gè)DOMSource對(duì)象,該構(gòu)造函數(shù)的參數(shù)可以是一個(gè)Document對(duì)象
//doc代表更改后的DOM Tree。
DOMSource domSource = new DOMSource (doc);
//創(chuàng)建一個(gè)DOMResult對(duì)象,臨時(shí)保存XSLT引擎的輸出結(jié)果。
DOMResult domResult = new DOMResult();
//下面調(diào)用JAXP中的XSLT引擎來實(shí)現(xiàn)輸出DOM Tree中的數(shù)據(jù)到XML文件中的功能。
//XSLT引擎的輸入為DOMSource對(duì)象,輸出為DOMResut對(duì)象。
try
{
//首先創(chuàng)建一個(gè)TransformerFactory對(duì)象,再由此創(chuàng)建Transformer對(duì)象。Transformer
//類相當(dāng)于一個(gè)XSLT引擎。通常我們使用它來處理XSL文件,但是在這里我們使
//用它來輸出XML文檔。
TransformerFactory tf=TransformerFactory.newInstance();
Transformer t=tf.newTransformer ();
//設(shè)置XSLT引擎的屬性(必不可少,否則會(huì)產(chǎn)生"漢字問題")。
Properties properties = t.getOutputProperties();
properties.setProperty(OutputKeys.ENCODING,"GB2312");
t.setOutputProperties(properties);
//關(guān)鍵的一步, 調(diào)用Transformer對(duì)象 (XSLT引擎)的transform()方法,該方法的第一
//個(gè)參數(shù)是DOMSource對(duì)象,第二個(gè)參數(shù)是DOMResult對(duì)象。
t.transform(domSource,domResult);
//創(chuàng)建缺省的Xalan XML Serializer,使用它將臨時(shí)存放在DOMResult對(duì)象
//(domResult)中的內(nèi)容以輸出流的形式輸出到輸出介質(zhì)中。
Serializer serializer = SerializerFactory.getSerializer
(OutputProperties.getDefaultMethodProperties("xml"));
//設(shè)置Xalan XML Serializer的輸出屬性,這一步必不可少,否則也可能產(chǎn)生
//所謂的"漢字問題"。
Properties prop=serializer.getOutputFormat();
prop.setProperty("encoding","GB2312");
serializer.setOutputFormat(prop);
//創(chuàng)建一個(gè)File對(duì)象,代表DOM Tree所包含的數(shù)據(jù)的輸出介質(zhì),這是一個(gè)XML文件。
File f = new File ("xuser3.xml");
//創(chuàng)建文件輸出流對(duì)象fos,請(qǐng)留意構(gòu)造函數(shù)的參數(shù)。
FileOutputStream fos=new FileOutputStream(f);
//設(shè)置Xalan XML Serializer的輸出流。
serializer.setOutputStream(fos);
//串行化輸出結(jié)果。
serializer.asDOMSerializer().serialize(domResult.getNode());
}
catch (Exception tce)
{
tce.printStackTrace();
}
這個(gè)方法不太常用,而且似乎有點(diǎn)畫蛇添足,所以我們就不展開討論了。完整的例子請(qǐng)參考下列文件: AddRecord4.java(見附件)、user.xml(見附件)。該例子的運(yùn)行環(huán)境為:Windows XP Professional、JDK 1.3.1。為了能夠正常編譯運(yùn)行AddRecord4.java這個(gè)程序,你需要到網(wǎng)址http://xml.apache.org/dist/去下載安裝Apache Xalan和Apache Xerces。
或者是到網(wǎng)址http://java.sun.com/xml/download.html去下載安裝Java XML Pack。因?yàn)樽钚碌腏ava XML Pack(Winter 01 版)包含了Apache Xalan和Apache Xerces技術(shù)在內(nèi)。
結(jié)論:
本文簡(jiǎn)略的討論了Java語言編程中更新XML文檔的四種方法。第一種方法是直接讀寫XML文件,這種方法十分繁瑣,而且比較容易出錯(cuò),極少使用,除非你需要開發(fā)自己的XML Parser,否則不會(huì)使用這種方法。第二種方法是使用Apache Crimson的XmlDocument類,這種方法極為簡(jiǎn)單,使用方便,如果你選用Apache Crimson作為XML解析器,那么不妨使用這種方法,不過這種方法似乎效率不高(源于效率低下的Apache Crimson),另外,高版本的JAXP或者是Java XML Pack、JWSDP不直接支持Apache Crimson,亦即這種方法不通用。第三種方法是使用JAXP的XSLT引擎(Transformer類)來輸出XML文檔,這種方法也許是標(biāo)準(zhǔn)的方法了,使用起來十分靈活,特別是可以自如控制輸出格式,我們推薦采用這種方法。第四種方法是第三種方法的變種,采用了Xalan XML Serializer,引入了串行化操作,對(duì)于大量文檔的修改/輸出有優(yōu)越性,可惜的是要重復(fù)設(shè)置XSLT引擎的屬性和XML Serializer的輸出屬性,比較麻煩,而且依賴于Apache Xalan和Apache Xerces技術(shù),通用性略顯不足。
除了上面討論的四種方法以外,實(shí)際上應(yīng)用別的API(比如JDOM、Castor、XML4J、Oracle XML Parser V2)也有很多辦法可以更新XML文檔,限于篇幅,在這里就不一一討論了。
標(biāo)簽:大興安嶺 紅河 拉薩 武威 岳陽 亳州 馬鞍山 鄭州
巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《Java編程中更新XML文檔的常用方法》,本文關(guān)鍵詞 Java,編程,中,更新,XML,文檔,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。