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

Java 使用 DOM4J 與 XPath 解析 XML:命名空間處理完全指南

     編輯:Java 相關知識

XML 解析四大流派速覽

  • SAX:事件驅動流式解析,記憶體佔用低,適合大檔案。
  • DOM:將整份 XML 載入記憶體形成樹結構,操作靈活但耗記憶體。
  • JDOM:針對 Java 優化的 DOM 封裝,遵循「二八原則」,大幅減少樣板碼。
  • DOM4J:效能優異、功能強大且易用的開源 API,連 Sun JAXM 亦採用之。

XPath 簡介

XPath 是在 XML 文件中導航、查詢節點的語言,類似資料庫的 SQL 或前端的 jQuery 選擇器。DOM4J 內建支援 XPath,配合命名空間處理更顯強大。

命名空間導致 XPath 查無結果的經典案例

Excel 匯出的 XML 常帶有預設命名空間:

<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" ...>
  <Worksheet ss:Name="Sheet1">...</Worksheet>
</Workbook>

直接寫 //Workbook/Worksheet/Table/Row[1]/Cell[1]/Data[1] 會查無結果,因為節點實際屬於 urn:schemas-microsoft-com:office:spreadsheet 這個命名空間。

四種解決命名空間的 XPath 寫法

方法一:使用 local-name() 與 namespace-uri()

String xpath = "//*[local-name()='Workbook' and namespace-uri()='urn:schemas-microsoft-com:office:spreadsheet']"
             + "/*[local-name()='Worksheet']"
             + "/*[local-name()='Table']"
             + "/*[local-name()='Row'][4]"
             + "/*[local-name()='Cell'][3]"
             + "/*[local-name()='Data'][1]";
List<Element> nodes = doc.selectNodes(xpath);

優點:無需額外設定。缺點:XPath 冗長、難維護。

方法二:XPath 物件設定命名空間映射 setNamespaceURIs(Map)

Map<String, String> map = new HashMap<>();
map.put("wb", "urn:schemas-microsoft-com:office:spreadsheet");
XPath xpathObj = doc.createXPath("//wb:Row[4]/wb:Cell[3]/wb:Data[1]");
xpathObj.setNamespaceURIs(map);
List<Element> nodes = xpathObj.selectNodes(doc);

方法三:DocumentFactory 全域設定 setXPathNamespaceURIs(Map)(推薦)

SAXReader reader = new SAXReader();
reader.getDocumentFactory().setXPathNamespaceURIs(map); // 同方法二的 map
Document doc = reader.read(inputStream);
// 後續直接用簡潔 XPath
List<Element> nodes = doc.selectNodes("//wb:Row[4]/wb:Cell[3]/wb:Data[1]");

一次設定,全局生效,XPath 乾淨易讀。

方法四:調整 XPath 路徑完整度比較效能

同方法三,但 XPath 寫完整路徑 //wb:Worksheet/wb:Table/...,可測試是否影響查詢速度。

效能對比:DOM4J vs 原生 DOM + XPath

// 原生 DOM + XPath
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(false); // 注意:這裡未處理命名空間,僅示範語法
Document doc = builder.parse(inputStream);
XPath xpath = XPathFactory.newInstance().newXPath();
XPathExpression expr = xpath.compile("//Workbook/Worksheet/Table/Row[4]/Cell[3]/Data[1]");
NodeList nl = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);

實測 DOM4J 通常更快且程式碼更簡潔。

完整可執行範例

見原文件 TestDom4jXpath.java,包含 read1()~read5() 五種寫法與計時輸出,可直接複製到專案跑測試。

最佳實務建議

  1. 專案引入 dom4j-2.x.jar 及 jaxen-x.x.jar(缺少會拋 NoClassDefFoundError: org/jaxen/JaxenException)。
  2. 統一在 SAXReader 建立後、read() 前,透過 DocumentFactory 設定命名空間前綴映射。
  3. XPath 盡量使用簡短相對路徑,搭配前綴,兼顧可讀與效能。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved