2011-08-26 59 views
5

以下是我的XML文件XPath的結果空字符串

<xyzevent xmlns="http://www.xyz.com/common/xyzevent/v1" xmlns:xsi="http://www.w3.org2001XMLSchema-instance"> 
<header> 
---- 
</header> 
<subscription xmlns="http://www.xyz.com/common/xyzevent/source/v1"> 
    <sender></sender> 
    <receiver> 
    <clientsubscription> 
     <servicemap>nanna</servicemap> 
    </clientsubscription> 
    </receiver> 
</subscription> 
</xyzevent> 

當我budila org.w3c.dom.Document中從該XML和應用XPathExperssion與表達

/xyzevent/subscription/receiver/clientsubscription/servicemap/text() 

結果空字符串。這個表達式有什麼問題?

謝謝

回答

6

這是因爲您的XML文檔使用了命名空間。 XPath真的很討厭命名空間。要確認這一點,請從文檔中去除兩個xmlns=http://.../v1,並再次運行您的XPath表達式,即未命名空間的,無法驗證的XML文件。它會匹配。

發生了什麼是您的XPath表達式試圖選擇/xyzevent,當您的文檔包含{http://.../v1}:xyzevent時,這是不一樣的事情。

解決此問題的方法有多種。正確的方法是設置一個NamespaceContext,以便您可以在XPath表達式中使用prefix:localName表示法並將前綴解析爲正確的URI。關於這個在xerces docs和更多elsewhere on StackOverflow有一個簡短的介紹。在ibm.com有廣泛的描述。

NamespaceContext將包含兩個(或更多)的映射:然後

{ 
    event => http://www.xyz.com/common/xyzevent/v1 
    source => http://www.xyz.com/common/xyzevent/source/v1 
} 

你的XPath表達式可以成爲/event:xyzevent/source:subscription/source:receiver/.../text()

作爲討厭的解決方法,你可以重寫你的XPath表達式使用local-name()功能選擇:

/*[local-name()='xyzevent']/*[local-name()='subscription'/ ... 

在這種情況下,表達的,任何元素,它的本地名稱是xyzevent無論空間URI相匹配。

+0

刪除xmlns = http://.../v1後,我可以從這兩個地方獲得值。但是,你能否向我解釋如何在我們在文檔中同時創建名稱空間值時創建NamespaceContext ... – Pokuri

+0

@Pokuri在'NamespaceContext'中註冊兩個單獨的前綴,例如, 'event'和'source'都有適當的URI。您的XPath表達式將成爲'/ event:xyzevent/source:subscription/source:receiver/...' – Barend

+0

但NamespaceContext需要一個namespaceURI和一個或多個前綴。那麼如何將兩個NamespaceContext傳遞給XPath.setNamespaceContext(namespaceContext);方法 – Pokuri

1

xyzevent是你的根元素,所以你只需要使用"/subscription/receiver/clientsubscription/servicemap/text()"

2

您的XML具有默認名稱空間:xmlns="http://www.xyz.com/common/xyzevent/v1",因此您需要在XML/XPath引擎中定義它。

或者使用XPath的:

/*[local-name() = 'xyzevent'] 
    /*[local-name() = 'subscription'] 
     /*[local-name() = 'receiver'] 
      /*[local-name() = 'clientsubscription'] 
       /*[local-name() = 'servicemap'] 
        /text()