2010-06-01 14 views
7

Cześć chłopaki, mam następujący scenariusz:Jak czytać z XmlReader bez ruchu przekazuje

while (reader.Read()) 
{ 
    if (reader.NodeType == XmlNodeType.Element && reader.Name == itemElementName) 
    { 
     XElement item = null; 
     try 
     { 
      item = XElement.ReadFrom(reader) as XElement; 
     } 
     catch (XmlException ex) 
     { 
      //log line number and stuff from XmlException class 
     } 
    } 
} 

W powyższej pętli mam transformującego pewien węzeł (itemElementName) w jego Xelement.

Niektóre węzły będą dobre XML i przejdą do XElement, ale niektóre nie.

W POŁOWIE chciałbym nie tylko złapać standardowe rzeczy XmlException ... Chciałbym również pobrać wyciąg z bieżącego Xml i ciąg.

Jednakże, jeśli wykonuję jakąkolwiek operację READ na węźle przed przekazaniem go do XElement, przesuwa ona czytnik do przodu.

W jaki sposób uzyskać "migawkę" zawartości OuterXml czytnika bez zakłócania jego pozycji?

Odpowiedz

10

W rzeczywistości ReadSubtree zwróci czytnik, który "opakuje" oryginalny czytnik. Czytanie tego nowego będzie również postępować naprzód. Musisz rozważyć XmlReader jako czytnik tylko do przodu, po prostu nie może wrócić. Co do scenariusza, zamiast próbować zapamiętać część XML, możesz poprosić czytelnika o pozycję w pliku wejściowym. Wystarczy rzucić go do interfejsu IXmlLineInfo, ma metody zwracania linii i pozycji. Dzięki temu można zapamiętać pewną pozycję początkową (przed danym elementem), a następnie pozycję końcową błędu. A następnie odczytaj tę część z pliku intput jako zwykły tekst.

+0

tak, doskonale, dziękuję, właśnie to się działo. Dziękuję za wyjaśnienie! – andy

+0

Ah .. Zupełnie źle zinterpretowałem punkt ReadSubTree, a potem przepraszam.Szczerze mówiąc, nie wynika to z dokumentacji w przeglądarce obiektów, ale strona MSDN czyni ją bardziej zrozumiałą. – Flynn1179

+1

Właśnie wróciłem i jeszcze raz rzuciłem okiem na kod, który mam, który go używa; faktycznie przestaje to czytać po zakończeniu pracy z poddrzewem, więc nigdy nie zauważyłem, że to on również przesunie oryginalny czytnik. – Flynn1179

3

Nie używaj żadnej operacji "Odczytuj" na czytniku - jak odkryłeś, to przyspiesza to. Użyj wywołań do właściwości, takich jak reader.HasValue i reader.Value, aby sprawdzić zawartość. Wyszukaj "XmlReader" w przeglądarce obiektów, istnieje sporo właściwości, które możesz przeczytać.

Edycja: Nie sądzę, że istnieje prosty sposób na uzyskanie kodu XML, prawdopodobnie dlatego, że bieżący węzeł może nie być prawidłowym kodem XML, takim jak XmlWhiteSpace, XmlText node, a nawet XmlAttribute.

+0

dziękuję flynn ... więc dla moich celów mam nadzieję uzyskać wyciąg z nieprawidłowego xml zanim błąd zostanie zgłoszony podczas próby utworzenia XElement. Mówisz, że to niemożliwe? – andy

+1

Prawdopodobnie nie jest to niemożliwe; Skopuję się za to, że o tym nie pamiętam, ale jeśli nazwiesz 'read.ReadSubtree()', utworzy on zupełnie nowy XmlReader, który zaczyna się gdziekolwiek jest 'reader'; możesz przeczytać, co ci się podoba bez wpływu na twój oryginalny "czytnik". Nie w 100%, jak by to wykorzystać w swojej sytuacji, ale wygląda na to, że to prawdopodobnie jest droga. – Flynn1179

0

Inny pomysł: przeczytaj zewnętrzny kod XML (który przesuwa czytnik), a następnie utwórz nowy czytnik z tego pliku XML, który umożliwia "powrót" i przetworzenie elementów bieżącego węzła.

while (r.ReadToFollowing("ParentNode")) 
{ 
    parentXml = r.ReadOuterXml(); 

    //since ReadOuterXml() advances the reader to the next parent node, create a new reader to read the remaining elements of the current parent 
    XmlReader r2 = XmlReader.Create(new StringReader(parentXml)); 
    r2.ReadToFollowing("ChildNode"); 
    childValue = r2.ReadElementContentAsString(); 
    r2.Close(); 
}     
1

Co zrobiłem było odczytać tylko element do XmlDocument i przeczytać, że zamiast. W moim przypadku musiałem przekonwertować dokument przepływu na HTML. Musiałem przeczytać wewnętrzny element, aby przypisać "styl" pierwszemu elementowi HTML.