首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java DOM/XPath 操作 XML 完整實戰:增刪改查與命名空間處理

     編輯:Java 相關知識

場景

配置文件、數據交換、報表生成等場景需程序化操作 XML。DOM 樹模型適合中小文檔 (≤50MB),XPath 提供強大查詢能力。

核心依賴 (JDK 內置)

import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.*;
import org.w3c.dom.*;
import org.xml.sax.SAXException;

工具類 XMLUtil 完整實現

public class XMLUtil {
    /** 解析文件獲取 Document */
    public static Document parse(String filePath) throws Exception {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true); // 關鍵:支持命名空間
        factory.setIgnoringElementContentWhitespace(true); // 忽略格式化空白
        DocumentBuilder builder = factory.newDocumentBuilder();
        return builder.parse(new File(filePath));
    }

    /** XPath 查詢單節點 */
    public static Node selectSingleNode(String xpathExpr, Object source) {
        try {
            XPath xpath = XPathFactory.newInstance().newXPath();
            return (Node) xpath.evaluate(xpathExpr, source, XPathConstants.NODE);
        } catch (XPathExpressionException e) {
            throw new RuntimeException("XPath 查詢失敗: " + xpathExpr, e);
        }
    }

    /** XPath 查詢節點列表 */
    public static NodeList selectNodes(String xpathExpr, Object source) {
        try {
            XPath xpath = XPathFactory.newInstance().newXPath();
            return (NodeList) xpath.evaluate(xpathExpr, source, XPathConstants.NODESET);
        } catch (XPathExpressionException e) {
            throw new RuntimeException("XPath 查詢失敗: " + xpathExpr, e);
        }
    }

    /** 節點輸出為字符串 (控制台/調試) */
    public static String nodeToString(Node node) {
        try {
            Transformer tf = TransformerFactory.newInstance().newTransformer();
            tf.setOutputProperty(OutputKeys.INDENT, "yes");
            tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
            StringWriter sw = new StringWriter();
            tf.transform(new DOMSource(node), new StreamResult(sw));
            return sw.toString();
        } catch (TransformerException e) {
            throw new RuntimeException("節點序列化失敗", e);
        }
    }

    /** Document 保存到文件 */
    public static void save(Document doc, String filePath) {
        try {
            Transformer tf = TransformerFactory.newInstance().newTransformer();
            tf.setOutputProperty(OutputKeys.INDENT, "yes");
            tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
            tf.transform(new DOMSource(doc), new StreamResult(new File(filePath)));
        } catch (TransformerException e) {
            throw new RuntimeException("XML 保存失敗", e);
        }
    }
}

實戰演示:書籍管理 (books.xml)

<?xml version="1.0" encoding="UTF-8"?>
<books>
  <book id="B01">
    <name>Harry Potter</name>
    <price>10</price>
    <memo>Magic</memo>
  </book>
  <book id="B02">
    <name>Three Kingdoms</name>
    <price>10</price>
    <memo>Classic</memo>
  </book>
  <book id="B03">
    <name>Water Margin</name>
    <price>6</price>
    <memo>Classic</memo>
  </book>
</books>

1. 查詢:找《Harry Potter》價格

Document doc = XMLUtil.parse("books.xml");
Element root = doc.getDocumentElement();
Node book = XMLUtil.selectSingleNode("/books/book[name='Harry Potter']", root);
String price = XMLUtil.selectSingleNode("price/text()", book).getNodeValue();
System.out.println("價格: " + price); // 10

2. 新增:添加一本書

Element newBook = doc.createElement("book");
newBook.setAttribute("id", "B04");
appendChild(doc, newBook, "name", "New Book");
appendChild(doc, newBook, "price", "20");
appendChild(doc, newBook, "memo", "Brand new");
root.appendChild(newBook);

3. 修改:更新價格 + 添加屬性

Node priceNode = XMLUtil.selectSingleNode("/books/book[name='Harry Potter']/price", root);
priceNode.setTextContent("15");
Element bookElem = (Element) XMLUtil.selectSingleNode("/books/book[name='Harry Potter']", root);
bookElem.setAttribute("edition", "2nd");

4. 刪除:按屬性刪除 + 條件批量刪除

// 刪除 id=B02
Node toDel = XMLUtil.selectSingleNode("/books/book[@id='B02']", root);
toDel.getParentNode().removeChild(toDel);

// 批量刪除 price < 10
NodeList cheapBooks = XMLUtil.selectNodes("/books/book[price < 10]", root);
for (int i = 0; i < cheapBooks.getLength(); i++) {
    cheapBooks.item(i).getParentNode().removeChild(cheapBooks.item(i));
}

5. 保存

XMLUtil.save(doc, "books_updated.xml");

命名空間處理 (必備技能)

// XML: ...
XPath xpath = XPathFactory.newInstance().newXPath();
xpath.setNamespaceContext(new NamespaceContext() {
    public String getNamespaceURI(String prefix) {
        return "ns".equals(prefix) ? "https://example.com" : XMLConstants.NULL_NS_URI;
    }
    public String getPrefix(String uri) { return "ns"; }
    public Iterator getPrefixes(String uri) { return null; }
});
Node item = (Node) xpath.evaluate("/ns:root/ns:item", doc, XPathConstants.NODE);

總結

DOM + XPath 是 Java 處理 XML 的標準組合:**命名空間感知、XPath 查詢、DOM 修改、Transformer 輸出** 四步走。大文件 (>100MB) 請改用 StAX (流式) 或 SAX (事件驅動) 避免 OOM。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved