聲明:以下的測試是用的jdk1.4.2,xalan7.0對於如下xml文檔片斷: <ML:MREML XMLns:ML="MREML">
<EnvelopEntity>
<EnvelopID>GUID2006102000002</EnvelopID>
<EnvelopVersion>1.0.1R</EnvelopVersion>
<ExchangeTime>2006-10-25 13:12:10</ExchangeTime>
<SendFrom>
<SFID>SOBEY_NEWS</SFID>
<SFDescription>SOBEY新聞系統</SFDescription>
</SendFrom>
<SendTo>
<STID>DAYANG_MAM</STID>
<STDescription>DAYANG媒資系統</STDescription>
</SendTo>
<Priority>2</Priority>
<EntityInfo>
<EntityID>REQUEST_ID_01</EntityID>
<EntityType>4</EntityType>
</EntityInfo>
<EntityInfo>
<EntityID>節目GUID</EntityID>
<EntityType>3</EntityType>
</EntityInfo>
<EntityInfo>
<EntityID>管理信息實體ID</EntityID>
<EntityType>2</EntityType>
</EntityInfo>
</EnvelopEntity>
</ML:MREML >
對於上述含有命名空間的XML文檔,如果想通過xpath查找EnvelopID的值,有兩種方式:1.通過利用xpath的函數local-name()
如上述查找內容的xpath表達式可以寫為://*[local-name()='MREML']/EnvelopEntity/EnvelopID/text()
2.通過在java程序中處理上述文檔的命名空間是定義的,如果要使xpath表達式能正確地被解析需要在Java程序中建立起prefix和uri二者的映射關系
public static Node parseXPath(String expression, Object obj, QName qname)
throws Exception {
javax.XML.xpath.XPath xpath = Javax.XML.xpath.XPathFactory.newInstance().newXPath();
xpath.setNamespaceContext(getNamespaceContext());
if (qname.equals(XPathConstants.NODE))
return (Node) xpath.evaluate(expression, obj, qname);
return null;
}
public static NamespaceContext getNamespaceContext() throws Exception {
return new NamespaceContext() {
public String getNamespaceURI(String prefix) {
/*
// 一種方式:
//這裡可以采用配置文件的方式,先將所需要使用的XMLNamespace配置好,
//采用注冊的方式供應用使用,這種方式效率應該高一些,不用每次都要從文檔中提取namespace
//不過沒有第二種方便
String uri;
if (prefix.equalsIgnoreCase("ML"))
uri = "MREML";
else if (prefix.equalsIgnoreCase("RE"))
uri = "http://herry.com.cn";
else if (prefix.equalsIgnoreCase("RID"))
uri = "ResourceID";
else if (prefix.equalsIgnoreCase("RUI"))
uri = "ResourceUniqueID";
else if (prefix.equalsIgnoreCase("RMDI"))
uri = "ResourceMetaDataInfo";
else
uri = null;
System.out.println(ParseXMLUtil.class + "::getNamespaceURI:prefix= " + prefix);
return uri;
*/
/*
// 另外一種方式: 通過PrefixResolver來提取出prefix和Namespace的對應關系
final PrefixResolver resolver =
new PrefixResolverDefault(doc.getDocumentElement());
return resolver.getNamespaceForPrefix(prefix);
*/
// Dummy implementation - not used!
public Java.util.Iterator getPrefixes(String val) {
return null;
}
// Dummy implemenation - not used!
public String getPrefix(String uri) {
return null;
}
};
}
若要查找ResourceUniqueID的值,則xpath應該書寫為://ML:MREML/ML:ResourceEntity/RMDI:ResourceMetaDataInfo/RMDI:ResourceID/RUI:ResourceUniqueID/text()
這裡的ML(prefix)和URI(MERML)等已經通過
對於含有默認命名空間地文檔如果采用NamespaceContext的方式,即將prefix和uri已經映射起來,如對於以下的文檔:
<MREML XMLns="MREML"><ResourceEntity >
<ResourceMetaDataInfo>
<ResourceID XMLns="ResourceID">
<RUI:ResourceUniqueID XMLns:RUI="ResourceUniqueID">節目GUID</RUI:ResourceUniqueID>
<UserDefID>UserDefID填寫節目代碼</UserDefID>
</ResourceID>
<Title>
<ResourceName>911新聞素材</ResourceName>
</Title>
<ResourceType>1</ResourceType>
<Subject>
<KeyWords>911 襲擊</KeyWords>
</Subject>
<Description>
<ContentDescription>美國遭遇911襲擊現場30S畫面及同期聲素材</ContentDescription>
<Column>
<ColumnName>今日世界</ColumnName>
</Column>
</Description>
<Date>
<CreateDate>2006-10-25 13:12:10</CreateDate>
</Date>
<Format>
<TotalLength>00:04:35:12</TotalLength>
<NumberofElements>2</NumberofElements>
<MarkPoint>
<StartPoint>00:00:00:05</StartPoint>
<EndPoint>00:04:35:10</EndPoint>
</MarkPoint>
</Format>
</ResourceMetaDataInfo>
</ResourceEntity>
</MREML>
若要查找ResourceUniqueID的值,則xpath應該書寫為://ML:MREML/ML:ResourceEntity/RMDI:ResourceMetaDataInfo/RMDI:ResourceID/RUI:ResourceUniqueID/text()
這裡的ML(prefix)和URI(MERML)等已經通過
if (prefix.equalsIgnoreCase("ML"))
uri = "MREML";
else if (prefix.equalsIgnoreCase("RE"))
uri = "http://herry.com.cn";
else if (prefix.equalsIgnoreCase("RID"))
uri = "ResourceID";
else if (prefix.equalsIgnoreCase("RUI"))
uri= "ResourceUniqueID";
else if (prefix.equalsIgnoreCase("RMDI"))
uri = "ResourceMetaDataInfo";
else
uri = null;
映射。
其中的ML和RMDI都是default namespace,它的作用范圍包含它的子元素,直至有新的default namespace出現為止。而namespace只對它自身起作用。如將上述文檔中:<ResourceMetaDataInfo>
<ResourceID XMLns="ResourceID">
改為:
<RMDI:ResourceMetaDataInfo XMLns:RMDI=” ResourceMetaDataInfo”>
<ResourceID>
…
…
</ RMDI:ResourceMetaDataInfo>
查找ResourceUniqueID的值,則xpath應該改為://ML:MREML/ML:ResourceEntity/RMDI:ResourceMetaDataInfo/ResourceID/RUI:ResourceUniqueID/text()
大家也可參考這篇文章:
http://blog.davber.com/2006/09/17/xpath-with-namespaces-in-Java/