JAXP (Java API for XML Processing) 是 Java 處理 XML 的標準 API,支援 DOM、SAX、XSLT,並通過可插拔層解耦具體解析器。初學者常遇到一個問題:DOM Tree 修改後,原始 XML 文件未同步更新。本文詳解四種同步更新方案並分析優劣。
遍歷 DOM Tree(遞歸或 TreeWalker),將節點逐個寫回文件。極繁瑣、易出錯,僅在開發自定義解析器時考慮。
XmlDocument (org.apache.crimson.tree.XmlDocument) 提供 write() 方法直接輸出 DOM 內容:
DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = parser.parse("user.xml");
Element newLink = doc.createElement("fancy");
doc.getDocumentElement().appendChild(newLink);
((XmlDocument)doc).write(new FileOutputStream("xuser1.xml"));
優點:極簡單。缺點:依賴 Crimson,高版本 JAXP/Java XML Pack 不支援,通用性差;效率較低;需強制轉型;編碼處理需額外指定(如 GB2312 解決中文亂碼)。
利用 XSLT 引擎輸出 DOM,靈活控制輸出格式:
DOMSource doms = new DOMSource(doc);
StreamResult sr = new StreamResult(new File("XMLOutput.xml"));
TransformerFactory tf = TransformerFactory.newInstance();
Transformer t = tf.newTransformer();
t.transform(doms, sr);
配合 OutputKeys 控制輸出屬性:
Properties props = t.getOutputProperties();
props.setProperty(OutputKeys.ENCODING, "GB2312"); // 解決中文問題
props.setProperty(OutputKeys.INDENT, "yes"); // 自動縮進
props.setProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
t.setOutputProperties(props);
優點:標準 API、通用性強、靈活控制格式(編碼、縮進、聲明、MIME 類型等)。
引入序列化操作,適合大量文檔輸出,但需重複設置 Transformer 和 Serializer 屬性,依賴 Xalan/Xerces,通用性稍弱:
Transformer t = tf.newTransformer();
t.transform(domSource, domResult);
Serializer serializer = SerializerFactory.getSerializer(OutputProperties.getDefaultMethodProperties("xml"));
Properties prop = serializer.getOutputFormat();
prop.setProperty("encoding", "GB2312");
serializer.setOutputFormat(prop);
serializer.setOutputStream(new FileOutputStream("xuser3.xml"));
serializer.asDOMSerializer().serialize(domResult.getNode());
| 方法 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
| 直接讀寫 | 無依賴 | 繁瑣、易錯、極少用 | 自研解析器 |
| XmlDocument | 簡單易用 | 依賴 Crimson、非標準、效率低 | 舊項目維護 |
| Transformer | 標準、靈活、通用 | 略顯繁瑣 | 推薦首選 |
| Xalan Serializer | 大量輸出性能優 | 配置重複、依賴特定庫 | 高吞吐批量處理 |
此外,JDOM、Castor、XML4J、Oracle XML Parser 等亦提供多種方案,不一一展開。