XML 若宣告命名空間(如 xmlns:ML="MREML"),直接寫 //EnvelopID 會查無節點,因為節點實際屬於 ML 命名空間。需透過兩種方式處理。
local-name() 忽略命名空間XPath 內建函數 local-name() 僅比對節點本地名稱,不理會前綴:
//*[local-name()='MREML']/EnvelopEntity/EnvelopID/text()
建立 NamespaceContext 實作,將前綴對應到 URI,再設定給 XPath 物件:
public static Node parseXPath(String expr, Object src, QName qname) throws Exception {
XPath xpath = XPathFactory.newInstance().newXPath();
xpath.setNamespaceContext(new NamespaceContext() {
@Override public String getNamespaceURI(String prefix) {
if ("ML".equalsIgnoreCase(prefix)) return "MREML";
if ("RMDI".equalsIgnoreCase(prefix)) return "ResourceMetaDataInfo";
// ... 其他映射
return null;
}
@Override public String getPrefix(String uri) { return null; }
@Override public Iterator getPrefixes(String uri) { return null; }
});
return (Node) xpath.evaluate(expr, src, qname);
}
之後 XPath 可直接使用前綴:
//ML:MREML/ML:EnvelopEntity/ML:EnvelopID/text()
若 XML 使用預設命名空間(xmlns="MREML" 無前綴),仍需在 NamespaceContext 給一個自訂前綴(如 ML)映射到該 URI,XPath 才能寫 //ML:EnvelopID。
local-name() 最快。NamespaceContext,確保精確與可維護性。