Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Foreach loop XmlNodeList

Currently I have the following code:

XmlDocument xDoc = new XmlDocument();
xDoc.Load("http://api.twitter.com/1/statuses/user_timeline.xml?screen_name=twitter");

XmlNodeList tweets = xDoc.GetElementsByTagName("text");
foreach (int i in tweets)
{
    if (tweets[i].InnerText.Length > 0)
    {
         MessageBox.Show(tweets[i].InnerText);
    }
}

Which doesn't work, it gives me System.InvalidCastException on the foreach line.

The following code works perfectly (no foreach, the i is replaced with a zero):

XmlDocument xDoc = new XmlDocument();
xDoc.Load("http://api.twitter.com/1/statuses/user_timeline.xml?screen_name=twitter");

XmlNodeList tweets = xDoc.GetElementsByTagName("text");

if (tweets[0].InnerText.Length > 0)
{
     MessageBox.Show(tweets[0].InnerText);
}
like image 541
Devator Avatar asked Aug 07 '12 14:08

Devator


6 Answers

I know that there is already a marked answer, but you can do it like you did in your first try, you just need to replace the int with XmlNode

XmlDocument xDoc = new XmlDocument();
xDoc.Load("http://api.twitter.com/1/statuses/user_timeline.xml?screen_name=twitter");

XmlNodeList tweets = xDoc.GetElementsByTagName("text");
foreach (XmlNode i in tweets)
{
    if (i.InnerText.Length > 0)
    {
         MessageBox.Show(i.InnerText);
    }
}
like image 140
YAYAYAYA Avatar answered Oct 16 '22 15:10

YAYAYAYA


tweets is a node list. I think that what you're trying to do is this:

XmlDocument xDoc = new XmlDocument();
xDoc.Load("http://api.twitter.com/1/statuses/user_timeline.xml?screen_name=twitter");

XmlNodeList tweets = xDoc.GetElementsByTagName("text");
for (int i = 0; i < tweets.Count; i++)
{
    if (tweets[i].InnerText.Length > 0)
    {
        MessageBox.Show(tweets[i].InnerText);
    }
}
like image 36
eburgos Avatar answered Oct 16 '22 16:10

eburgos


It is not of Int type, That is the reason you are getting a casting exception. You can either replace int with the appropriate type or simply make use of type inference (implicitly typed variables) to handle this. Here i am using typeinference.by saying type as var, The compiler will understand it is of type of the iterator variable in tweets collection

foreach (var i in tweets)
{
    if (i!=null)
    {
      string tweet= (((System.Xml.XmlElement)(i))).InnerText;
      MessageBox.Show(tweet);
     }
}

EDIT : With the Wonderful LINQtoXML, Your code can be rewritten like this.

string url = "http://api.twitter.com/1/statuses/user_timeline.xml?screen_name=twitter";
XElement elm = XElement.Load(url);
if (elm != null)
{              
    foreach (var status in elm.Elements("status"))
    {
        string tweet = status.Element("text").Value;
        MessageBox.Show(ss);
    }
}
like image 23
Shyju Avatar answered Oct 16 '22 15:10

Shyju


All the answers seem to be a bit outdated Imperative examples so I will add a declarative one. This is not doing what the OP wanted but I'm sure you'll get the point.

    public static List<System.Xml.XmlNode> toList(System.Xml.XmlNodeList nodelist){
        List<System.Xml.XmlNode> nodes =  new List<System.Xml.XmlNode>();
        foreach (System.Xml.XmlNode node in nodelist)
        {
            nodes.Add(node);
        }
        return nodes;
    }
    public static ReadMeObject setXml(ReadMeObject readmeObject){
        readmeObject.xmlDocument = new System.Xml.XmlDocument();
        readmeObject.xmlDocument.LoadXml("<body>"+readmeObject.htmlStringContent+"</body>");
        System.Xml.XmlNodeList images =  readmeObject.xmlDocument.SelectNodes("//img");
        Array.ForEach(
            Functions.toList( images )
                .Where((image) => image.Attributes != null)
                .Where((image) => image.Attributes["src"] != null)
                .Where((image) => image.Attributes["src"].Value != "")
                .ToArray()                
            , (image) => {
                Console.WriteLine(image.Attributes["src"].Value);
            }
        );
        return readmeObject;
    }
like image 37
HMR Avatar answered Oct 16 '22 17:10

HMR


foreach (XmlNode node in tweets)
{
    if (tweets[i].InnerText.Length > 0)
    {
         MessageBox.Show(tweets[node].InnerText);
    }
}

I've changed the 'I', which you cannot use, to XmlNode, which selects a single line of your list.

like image 29
Joseph Avatar answered Oct 16 '22 16:10

Joseph


You can loop through the Collection with .GetEnumerator()

this code is taken Microsoft Documentation :

 XmlNodeList elemList = root.GetElementsByTagName("title");
 IEnumerator ienum = elemList.GetEnumerator();          
 while (ienum.MoveNext()) {   
   XmlNode title = (XmlNode) ienum.Current;
   Console.WriteLine(title.InnerText);
 }
like image 27
Jean-Pascal Lavigne Avatar answered Oct 16 '22 16:10

Jean-Pascal Lavigne