2011-03-08 118 views
62

我有以下XML:Xml命名空間打破我的xpath!

<List xmlns="http://schemas.microsoft.com/sharepoint/soap/"> 
<Fields> 
    <Field> 
    </Field> 
</Fields> 
</List> 

這正從一個SharePoint Web服務返回的XML的一個簡化版本。我也有以下XPath:

/List/Fields/Field 

當我從XML刪除xmlns中的XPath工作正常。當它在我的xPath中找不到任何東西。有什麼我應該做的與我的xPath不同?修改XML不是一種選擇。

+2

許多重複之一:http://stackoverflow.com/questions/11345/xpaths-and-default-namespaces – 2011-03-09 19:45:28

+2

沒有,這不是重複。這個問題特別指出了C#,而這是嚴格的xpath/xml。而且,他的命名空間不是空白的,而我的是。 – 2011-03-21 14:37:51

+0

您需要某種程度的抽象......您在問如何使用XPath表達式在默認名稱空間下選擇元素。 **這是最常見的**。 – 2011-03-21 16:09:36

回答

71

我也有以下XPath:

/List/Fields/Field 

當我從XML 刪除的xmlns中的XPath工作正常。當它在 有我的XPath覺得沒有什麼

如果不能註冊,命名空間綁定,不能使用(假設註冊前綴爲「X」):

/x:List/x:Fields/x:Fiels 

則有另一種方式

/*[name()='List']/*[name()='Fields']/*[name()='Field'] 
14

您很可能必須在您的xpath庫中註冊該命名空間uri。根據庫的不同,您可能可以使用「默認」前綴,或者您可能需要爲其指定一個名稱前綴,並在xpath查詢中使用它。

例如,在PHP(因爲你沒有指定語言)使用DOMXPath你可以做這樣的事情:

$xpath = new DOMXPath($document); 
$xpath->registerNamespace('x', 'http://schemas.microsoft.com/sharepoint/soap/'); 
$xpath->query('/x:List/x:Fields/x:Field'); 
+0

是啊,我是一個.NET人,通常我的解決方案就是.NET的等價物。不幸的是,我們正在使用第三方的「快速」開發環境,它不會使我們有能力做到這一點...... – 2011-03-09 00:03:00

+1

另外,如果沒有前綴,他們爲什麼還要包含一個名稱空間? (xPath的'x:'部分) – 2011-03-09 00:03:44

+1

有一個名稱空間。它只是在這個特定的文件中使用'默認'前綴。該文件將是相同的語義是吧'' – Anomie 2011-03-09 00:10:13

35

列表元素已經定義了默認的命名空間,這是由採用裏面的所有元素。

你因此需要忽略,像這樣的元素命名空間:

/*[local-name()='List']/*[local-name()='Fields]/*[local-name()='Field] 

但這意味着與XPath將拿起任何其他元素與列表 - 田 - 現場

你可以做一個命名空間檢查以及像這樣的本地名稱檢查:

/*[local-name()='List' and namespace-uri()='http://schemas.microsoft.com/sharepoint/soap/']/*[local-name()='Fields' and namespace-uri()='http://schemas.microsoft.com/sharepoint/soap/']/*[local-name()='Field' and namespace-uri()='http://schemas.microsoft.com/sharepoint/soap/'] 

或者您可以向庫註冊命名空間,然後明確指定該命名空間和廣告的前綴將其轉換爲xpath表達式,其方法依賴於您正在使用的庫。

+1

這個答案正在工作,而接受的答案不工作....謝謝@ zode64這個幫助。我瘋狂地讓我的xpath表達式爲包含xml的名稱空間工作。現在,我不需要擔心名稱空間了。萬分感謝.. – 2016-02-09 13:43:45

1

我剛剛一直有這個問題,而使用的Xalan-C

我最初不太明白的一點是,XPath或XSLT命名空間別名/前綴可能與文檔不同 - 取決於您的命名空間解析器。

看起來,如果文檔上有一個命名空間,那麼它將無法匹配路徑元素,除非使用了命名空間。 (標準但並不總是遵循?)

的XalanDocumentPrefixResolver將XPath或XSLT命名空間映射到URI和嘗試,並通過獲取前綴給它們編號 - 這裏沒有前綴它使用它變成的xmlns

/xmlns:List/xmlns:Fields/xmlns:Field

或者你的名字可以創建自己的解析器,但它仍然需要在XPath :(

這裏使用的最小的命名空間是一個我砍死在一起,同時測試,無記憶保證

// don't care what prefix given, there can only be the one 
struct NoPrefixResolver : public xalanc::PrefixResolver { 

    NoPrefixResolver(const xalanc::XalanDOMString& theURI) : m_uri(theURI){} 

    virtual const xalanc::XalanDOMString* 
     getNamespaceForPrefix(const xalanc::XalanDOMString&  prefix) const { 
     return &m_uri; 
    } 

    virtual const xalanc::XalanDOMString& getURI() const { 
     return m_uri; 
    } 

    const xalanc::XalanDOMString m_uri; 
}; 

/x:List/x:Fields/x:Field 
/a:List/b:Fields/c:Field 
-1

如果你可以跳過文檔元素,下面的XPath還可以幫助:

//Fields/Field 

這個工作,只要你沒有「字段」下的任何其他節點和大的子節點有沒有名字空間。