Search code examples
c#.netxmlreader

What’s wrong with this code


Why doesn't the while loop return anything? I assume this has something to do with .NET. I have .NET 2.0. The problem is that the while statement will execute one time then exit, as though there are no nodes with that name, when there definately are.

Here is an example of the XML:

<rss version="2.0">
    <channel>
        <title>...</title>
        <link>...</link>
        <description>...</description>
        <lastBuildDate>...</lastBuildDate>
        <item>
            <title>User greeting</title>
            <guid>...</guid>
            <link>http://...</link>

            <description>Voicebox number: 1</description>
            <author>Free Conference Call</author>
        </item>
        <item>
            <title>User greeting</title>
            <guid>...</guid>
            <link>http://...</link>

            <description>Voicebox number: 1</description>
            <author>Free Conference Call</author>
        </item>
    </channel>
</rss>

Here is the code:

HttpWebRequest webreq = (HttpWebRequest)WebRequest.Create (reqURL);
// Set some reasonable limits on resources used by this request
webreq.MaximumAutomaticRedirections = 4;
webreq.MaximumResponseHeadersLength = 4;
//====================
// Set credentials to use for this request.
webreq.Credentials = CredentialCache.DefaultCredentials;
HttpWebResponse response = (HttpWebResponse)webreq.GetResponse ();
//====================
// Get the stream associated with the response.
receiveStream = response.GetResponseStream ();
//====================
// Pipes the stream to a higher level stream reader with the required encoding format. 
readStream = new StreamReader(receiveStream, Encoding.UTF8);
resXML = readStream.ReadToEnd();
readStream = new StreamReader(receiveStream, Encoding.UTF8);
//====================
Console.WriteLine(resXML);
Stream XMLStream = receiveStream;
readStream = new StreamReader(XMLStream, Encoding.UTF8);

XmlReaderSettings settings = new XmlReaderSettings();
settings.ConformanceLevel = ConformanceLevel.Fragment;
settings.IgnoreWhitespace = true;
settings.IgnoreComments = true;
XmlReader reader = System.Xml.XmlReader.Create(readStream, settings);

while(reader.EOF == false)
{
    reader.ReadToFollowing("link");
    Console.WriteLine("link: " + reader.Value);
    //=======================================
    reader.ReadToFollowing("description");
    Console.WriteLine("descrip: " + reader.Value);
}

Solution

  • You've already read all the data from the response when you call

    resXML = readerStream.ReadToEnd();
    

    ... readerStream and readStream are both layered on top of receiveStream, so once you've read all the data through one, you can't read it again through the other.

    You should really have a using statement for the response - and ideally the various streams involved. Given that you can create an XmlReader from a stream, not just a StreamReader, why not just use something like this:

    XmlReaderSettings settings = new XmlReaderSettings();
    settings.ConformanceLevel = ConformanceLevel.Fragment;
    settings.IgnoreWhitespace = true;
    settings.IgnoreComments = true;
    
    using (HttpWebResponse response = (HttpWebResponse)webreq.GetResponse())
    {
       using (Stream stream = response.GetResponseStream())
       {
           using(XmlReader reader = XmlReader.Create(stream, settings))
           {
               // Do stuff here
           }
       }
    }
    

    Additionally, I'd generally recommend creating an XmlDocument or something similar rather than working with XmlReader - it doesn't scale as well for large documents, but it's easier to work with.