2010-02-19 5 views
19

Widzę dziwne zachowanie, gdy próbuję parsować XML za pomocą klasy LINQ XmlReader. Przypadek testowy poniżej: wygląda na to, że używam metody (XElement)XNode.ReadFrom(xmlReader) lub jednej z metod Read() w XmlReader, brakuje w nim drugich elementów bar w wejściowym kodzie XML. Jeśli zostanie dodany dowolny odstęp między </bar> i <bar>, to zostanie poprawnie przeanalizowany drugi element bar.Dlaczego XmlReader pomija każdy inny element, jeśli nie ma separatora białych znaków?

Czy ktoś ma pomysł, dlaczego strumień wejściowy jest pomieszany i jak obejść ten problem?

[Test] 
    [Explicit] 
    public void ShouldParseCorrectNumberOfElements() 
    { 
     var xml = @"<foo><bar>wtf</bar><bar>wtf2</bar></foo>"; 
     XmlReader xmlReader = XmlReader.Create(new MemoryStream(Encoding.UTF8.GetBytes(xml))); 

     int count = 0; 
     xmlReader.MoveToContent(); 
     while (xmlReader.Read()) 
     { 
      if (xmlReader.NodeType == XmlNodeType.Element && xmlReader.Name == "bar") 
      { 
       var element = xmlReader.ReadOuterXml(); 
       Console.WriteLine("just got an " + element); 
       count++; 
      } 
     } 
     Assert.AreEqual(2, count); 
    } 
+0

Pętla może być znacznie zoptymalizowany przy użyciu 'ReadToFollowing ("bar")' zamiast 'read()' (współpracuje z odpowiedzią Jona zbyt). –

+0

Mam podobny przypadek i używam 'ReadToFollowing' z' While' i 'ReadOuterXml' wewnątrz pętli while. Jeśli dokument jest sformatowany za pomocą znaków nowej linii, działa poprawnie. Kiedy mam dokument z pojedynczą linią, pomijam wszystkie następujące węzły. –

Odpowiedz

30

Dzwonisz pod numer ReadOuterXml, który zajmie element i umieści kursor tuż przed następnym elementem. Następnie ponownie wywołujesz Read, który przesuwa kursor na (np. Do węzła tekstowego w elemencie).

Oto alternatywa do pętli:

while (!xmlReader.EOF) 
{ 
    Console.WriteLine(xmlReader.NodeType); 
    if (xmlReader.NodeType == XmlNodeType.Element && xmlReader.Name == "bar") 
    { 
     var element = xmlReader.ReadOuterXml(); 
     Console.WriteLine("just got an " + element); 
     count++;     
    } 
    else 
    { 
     xmlReader.Read(); 
    } 
} 
+0

Och, to uczucie "od jednego do drugiego" ... Jeszcze raz dziękuję! –

6

Czy może omijając linię poprzez wywołanie funkcji read() w warunku pętli while i wtedy funkcja ReadOuterXml() w samej pętli?