命名空间阻止解析C#中的XML文件

问题描述:

我有这个尺寸为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属性。但事实并非如此。

好,欢迎这样的话;-)

在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

我相信你想:

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