Пространство имен предотвращает анализ XML-файла в C # - PullRequest
1 голос
/ 23 июля 2010

У меня есть этот XML-файл размером 2,8 ГБ (дамп польской Википедии). Я должен искать этот файл для определенного заголовка и получить содержание страницы для него. Я использую LINQ to 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 ]

2 голосов
/ 23 июля 2010

Хорошо, тогда добро пожаловать в SO; -)

В XML декларация пространства имен является святой.Удаление этого файла может сделать XML непригодным для использования, поэтому я бы посоветовал против него (и это огромная задача для файла объемом 2,8 ГБ!).Каждое имя должно считаться уникальным, как в {namespace}elementname (то есть, оба), когда вы имеете дело с XML. Linq to XML принимает пространства имен , и вы должны использовать их:

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 о потоковой передаче Linq в XML .

1 голос
/ 23 июля 2010

Я верю, что вы хотите:

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");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...