2008-10-08 97 views
19

我有一個項目,我正在採取一些特別醜陋的「活」HTML,並將其強制爲一個正式的XML DOM與HTML敏捷包。然後,我希望能夠做的就是使用Linq將其查詢到XML中,這樣我就可以刪除需要的位。我使用的方法描述here解析HtmlDocument到XDocument,但是當試圖查詢這個我不知道如何處理命名空間。在一個特定的文件上原有的HTML實際上是格式不XHTML具有以下標籤:如何在查詢Linq到XML時處理任意命名空間?

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> 

當試圖從該文件似乎命名空間屬性阻止我做類似查詢:

var x = xDoc.Descendants("div"); 
// returns null 

顯然,對於那些「div」標籤,只有LocalName是「div」,但正確的標籤名稱是命名空間加「div」。我試圖做一些研究XML命名空間的問題,看來我可以通過查詢此方式繞過命名空間:

var x = 
    (from x in xDoc.Descendants() 
    where x.Name.LocalName == "div" 
    select x); 
// works 

然而,這似乎是一個相當哈克的解決方案,並且不妥善處理命名空間問題。據我瞭解,一個合適的XML文檔可以包含多個名稱空間,因此處理它的正確方法應該是解析出我正在查詢的名稱空間。有沒有其他人必須這樣做?我只是想讓事情變得複雜嗎?我知道我可以通過堅持HtmlDocument和XPath查詢來避免所有這些,但是如果可能的話,我寧願堅持我所知道的(Linq),我也想知道我沒有爲更多的命名空間設置自己 - 相關問題在路上。

在這種情況下處理命名空間的正確方法是什麼?

回答

17

使用LocalName應該沒問題。我不認爲這是一個黑客在所有如果你不在乎它是在什麼命名空間

如果你知道你想要的命名空間,並要指定它,您可以:

var ns = "{http://www.w3.org/1999/xhtml}"; 
var x = xDoc.Root.Descendants(ns + "div"); 

MSDN reference

您也可以在文檔中使用的所有命名空間的列表:

var namespaces = (from x in xDoc.Root.DescendantsAndSelf() 
        select x.Name.Namespace).Distinct(); 

我想你可以用它來做到這一點,但它不是真正的任何減少一個黑客:

var x = namespaces.SelectMany(ns=>xDoc.Root.Descendants(ns+"div")); 
+9

這是關於XLINQ API :(最惱人的事情:有一種方法可以告訴它忽略名稱空間,或者至少指定一個默認值。 – MichaelGG 2008-10-13 23:58:58

2

如果您知道的命名空間是要通過XML的根元素聲明,如最通常情況下,你可以這樣做:

var ns = xDoc.Root.Name.Namespace; 
var x = xDoc.Descendants(ns + "div");