Что не так с этим кодом - PullRequest
1 голос
/ 25 января 2010

Почему цикл while ничего не возвращает? Я предполагаю, что это как-то связано с .NET. У меня есть .NET 2.0. Проблема заключается в том, что оператор while будет выполнен один раз, а затем завершится, как будто нет узлов с таким именем, когда они определенно есть.

Вот пример 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>

Вот код:

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

Ответы [ 3 ]

11 голосов
/ 25 января 2010

Вы уже прочитали все данные из ответа, когда звоните

resXML = readerStream.ReadToEnd();

... readerStream и readStream располагаются поверх receiveStream, поэтому, прочитав все данные через одну, вы не сможете снова прочитать через другую.

Вы действительно должны иметь using оператор для ответа - и в идеале различные вовлеченные потоки. Учитывая, что вы можете создать XmlReader из потока, а не просто StreamReader, почему бы просто не использовать что-то вроде этого:

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
       }
   }
}

Кроме того, я бы обычно рекомендовал бы создать XmlDocument или что-то подобное, а не работать с XmlReader - он не так хорошо масштабируется для больших документов, но с ним легче работать

1 голос
/ 25 января 2010

почему вы не используете Linq-to-XML? Сделал бы для более удобочитаемого / поддерживаемого кода

XElement rssFile = XElement.Load(content);
IEnumerable<XElement> channels = rssFile.Descendants("channel");
foreach(XElement channel in channels)
{
    Console.WriteLine("link: " + channel.Element("link").Value);
    Console.WriteLine("description: " + channel.Element("description").Value);
}

кроме того, что сказал Джон

0 голосов
/ 25 января 2010

Как сказал Джон, вы уже прочитали все данные, поэтому вы не можете прочитать их снова, однако вы должны иметь возможность установить позицию потока обратно в ноль и затем прочитать ее снова.

receiveStream.Position = 0;

Другой совет, который я бы сказал, - переименовать вашу переменную «readStream» в «reader» или что-то еще, потому что это StreamReader, а не Stream.

Береги себя, Том

...