Skocz do zawartości
mystery

[C#] Problem z namespace podczas przetwarzania XML

Rekomendowane odpowiedzi

Witam.

 

Mam plik XML, który waży 2,8GB (jest to aktualny dump polskiej Wikipedii). W tym pliku mam wyszukać dany, konkretny tytuł i zwrócić zawartość strony. W tym celu używam LINQ to XML, aby kod był przejrzysty. Wygląda to mniej więcej tak:

 

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

private IEnumerable<XElement> StreamXmlDocument(string uri)        {            //cheking XmlReader class with LINQ!            //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(); //nie działa                                if (el != null)                                {                                    yield return el;                                }                            }                            break;                    }                }            }        }

Jak widać kod jest łatwy i przejrzysty. Dzięki wykorzystaniu klasy XmlReader z System.XML nie wczytuję całego pliku do pamięci, poza tym kod powinien wykonywać się szybko. Problem w tym, że ów plik XML rozpoczyna się w ten sposób (zawiera atrybut namespace):

<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.4/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.4/ http://www.mediawiki.org/xml/export-0.4.xsd" version="0.4" xml:lang="pl">

Najdziwniejsze w tym wszystkim jest to, że jeżeli wywalę xmlns="http://www.mediawiki.org/xml/export-0.4/" to wszystko działa pięknie. Jednak z nim program wywala się na linii "where..." tak, jakby nie było elementu <title> w el, bądź el był null, ale tak nie jest. Dokładnie rzecz ujmując zwracany jest taki błąd:

Odwołanie do obiektu nie zostało ustawione na wystąpienie obiektu.

Dodatkowo gdzieś w Internecie znalazłem artykuł, w którym ktoś napisał, że to:

el.DescendantsAndSelf().Attributes().Where(n => n.IsNamespaceDeclaration).Remove();
Powinno usunąć wszystkie deklaracje xmlns z elementu. Niestety w moim przypadku to nie działa.

 

Próbowałem wykorzystać klasę XmlTextReader, która jest rozszerzeniem XmlReader i zawiera pole Namespaces. Niby po ustawieniu tego pola na null powinno być OK, ale program wywalał się w innym miejscu (element text posiada atrybut xml:space="preserve" i wywala na ":"). Niestety nie działa również.

 

Jeżeli macie jakiś pomysł to proszę o pomoc. Chodzi o to, żeby nie modyfikować pliku XML w żaden sposób. Wynika to z tego, że dump może być aktualizowany, mogą być ściągane wikipedie w różnych językach, itp.

Dodam, że pracuję w środowisku .NET 3.5 (Visual Studio 2008), język C# 3.0.

Jako, że nie mogę załączyć całego pliku dumpa to uczynię to z jego małym fragmentem. Cały plik można ściągnąć z plwiki dump progress on 20100629 (aktualna wersja polskiej wiki), nazwa pliku to pages-articles.xml.bz2

 

pozdrawiam

m

 

Edit:

Znalazłem rozwiązanie:

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");

test-dump-small.zip

Edytowane przez mystery

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Dołącz do dyskusji

Możesz dodać zawartość już teraz a zarejestrować się później. Jeśli posiadasz już konto, zaloguj się aby dodać zawartość za jego pomocą.

Gość
Dodaj odpowiedź do tematu...

×   Wklejono zawartość z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Odnośnik został automatycznie osadzony.   Przywróć wyświetlanie jako odnośnik

×   Przywrócono poprzednią zawartość.   Wyczyść edytor

×   Nie możesz bezpośrednio wkleić grafiki. Dodaj lub załącz grafiki z adresu URL.

Ładowanie


×
×
  • Dodaj nową pozycję...