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

Java XPath 處理帶命名空間 XML 文檔

     編輯:Java 相關知識

前言

真實世界的 XML 文檔普遍包含命名空間,直接使用 XPath 查詢往往因前綴不匹配而失敗。本文介紹兩種在 Java 中處理帶命名空間 XML 的 XPath 查詢方案,並針對預設命名空間給出最佳實踐。

範例 XML 片段

<ML:MREML xmlns:ML="MREML">
  <EnvelopEntity>
    <EnvelopID>GUID2006102000002</EnvelopID>
    ...
  </EnvelopEntity>
</ML:MREML>

方案一:使用 local-name() 忽略命名空間

XPath 表達式:

//*[local-name()='MREML']/EnvelopEntity/EnvelopID/text()
  • 優點:無需註冊命名空間上下文,寫法簡單。
  • 缺點:無法區分同名不同命名空間的元素;效能稍差(需遍歷所有節點)。

方案二:註冊 NamespaceContext 映射前綴與 URI

核心工具類

import javax.xml.namespace.NamespaceContext;
import javax.xml.xpath.*;
import org.w3c.dom.Node;
import java.util.*;

public class XPathUtils {
    public static Node evaluateXPath(String expr, Object source, QName returnType) throws Exception {
        XPath xpath = XPathFactory.newInstance().newXPath();
        xpath.setNamespaceContext(new SimpleNamespaceContext());
        return (Node) xpath.evaluate(expr, source, returnType);
    }

    static class SimpleNamespaceContext implements NamespaceContext {
        private final Map map = Map.of(
            "ML", "MREML",
            "RE", "https://herry.com.cn",
            "RID", "ResourceID",
            "RUI", "ResourceUniqueID",
            "RMDI", "ResourceMetaDataInfo"
        );

        @Override public String getNamespaceURI(String prefix) { return map.getOrDefault(prefix, ""); }
        @Override public String getPrefix(String uri) { return map.entrySet().stream().filter(e -> e.getValue().equals(uri)).map(Map.Entry::getKey).findFirst().orElse(""); }
        @Override public Iterator getPrefixes(String uri) { return Collections.emptyIterator(); }
    }
}

XPath 表達式(使用已註冊前綴)

//ML:MREML/ML:EnvelopEntity/ML:EnvelopID/text()

預設命名空間(無前綴)的特殊處理

XML:<MREML xmlns="MREML">...

XPath 1.0 無法直接查詢無前綴的預設命名空間,**必須**在 NamespaceContext 中為其指定一個**自定義前綴**(如 ml):

map.put("ml", "MREML"); // 自定義前綴 → URI

查詢時使用:

//ml:MREML/ml:ResourceEntity/ml:ResourceMetaDataInfo/...

命名空間作用域變更對 XPath 的影響

若子元素重新宣告 xmlns:RMDI="ResourceMetaDataInfo",則該子樹下需使用 RMDI: 前綴;若改為預設命名空間 xmlns="ResourceMetaDataInfo",則需另行映射新前綴。

完整查詢範例

// 查詢 ResourceUniqueID
String xpath = "//ml:MREML/ml:ResourceEntity/rmdi:ResourceMetaDataInfo/rid:ResourceID/rui:ResourceUniqueID/text()";
// 對應 NamespaceContext 映射:
// ml → MREML, rmdi → ResourceMetaDataInfo, rid → ResourceID, rui → ResourceUniqueID

參考資源

總結

處理帶命名空間 XML 時,**強烈建議使用 NamespaceContext 顯式映射前綴**,避免 local-name() 的歧義與效能問題。預設命名空間務必分配自定義前綴,否則 XPath 1.0 無法匹配。

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