2010-07-23 39 views
1

我有這個尺寸爲2.8GB(波蘭語維基百科轉儲)的XML文件。我必須搜索此文件以獲取特定標題並獲取頁面內容。我使用的LINQ to XML的簡單:命名空間阻止解析C#中的XML文件

var text = from el in StreamXmlDocument(filePath) 
      where el.Element("title").Value.Contains(titleToSearch) 
      select (string)el.Element("revision").Element("text"); 

private IEnumerable<XElement> StreamXmlDocument(string uri) 
{ 
    //code made accoring to informations at MSDN website available at URL: 
    //http://msdn.microsoft.com/en-us/library/system.xml.linq.xnode.readfrom.aspx 
    using (XmlReader reader = XmlReader.Create(uri)) 
    { 

     reader.MoveToContent(); 

     while (reader.Read()) 
     { 
      switch (reader.NodeType) 
      { 
       case XmlNodeType.Element: 
        if (reader.Name == "page") 
        { 
         XElement el = XElement.ReadFrom(reader) as XElement; 
         el.DescendantsAndSelf().Attributes().Where(n => n.IsNamespaceDeclaration).Remove(); 
         if (el != null) 
         { 
          yield return el; 
         } 
        } 
        break; 
      } 
     } 
    } 

所以問題是,這個文件包含的xmlns在第一元素屬性:

<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.4/" (...) > 

,當我運行代碼上面我得到錯誤沒有參考對象在這一行:

where el.Element("title").Value.Contains(titleToSearch) 

當我手動刪除該xmlns屬性一切工作正常。我在互聯網的某處發現這樣的:

el.DescendantsAndSelf().Attributes().Where(n => n.IsNamespaceDeclaration).Remove(); 

應該從元素中刪除所有的xmlns屬性。但事實並非如此。

回答

2

好,歡迎這樣的話;-)

在XML中,命名空間聲明是聖人。刪除它可能會使XML無法使用,所以我建議不要這樣做(這對於2.8GB文件來說是一項艱鉅的任務!)。無論何時處理XML,每個名稱都應該被認爲是唯一的,如{namespace}elementname(即兩者)。 Linq to XML accepts namespaces,你應該使用它們:

XNamespace wiki = "http://www.mediawiki.org/xml/export-0.4/"; 

var text = from el in StreamXmlDocument(filePath) 
      where el.Element(wiki + "title").Value.Contains(titleToSearch) 
      select (string)el.Element(wiki + "revision").Element(wiki + "text"); 

(可能會被忽略,你已經這樣做了):
對XML的說明:Linq2XML將加載在內存中的整個事情,我相信,就像DOM ,這將需要約4.5倍的文件大小。這可能是有問題的。閱讀MSDN blog about streaming Linq to XML

+0

謝謝,是的,我知道的內存問題,這就是爲什麼我使用的XmlReader。它每次只讀取一個元素到內存:)感謝您的迴應。我現在檢查它 – Ventus 2010-07-23 16:49:32

+0

太棒了!這工作正常。再次感謝:) – Ventus 2010-07-23 16:56:49

1

我相信你想:

XNamespace ns = "http://www.mediawiki.org/xml/export-0.4/"; 

var text = from el in StreamXmlDocument(filePath) 
      where el.Element(ns+"title").Value.Contains(titleToSearch) 
      select (string)el.Element(ns+"revision").Element(ns+"text"); 
+0

我們可以如何平等;-)只是試圖挑剔:最後一個'元素',你可能想'元素(ns +「文本」)' – Abel 2010-07-23 16:47:53

+0

'哦!我正在考慮使用「維基」作爲命名空間變量...... – 2010-07-23 16:58:22