Using Yield to extract XML nodes

I have never used Yield before but need it or something like it.

I am iterating through an entire XML document for a defined set ot tags or arrays of tags. I want to retrieve every tag in the XML document.

How do I do this with Yield? I imagined the function would iterate through them all and return one, the resume at the next node when the function's called again.

Please let me know...

Thanks.
newbiewebSr. Software EngineerAsked:
Who is Participating?
 
Bob LearnedCommented:
I would normally assume that you know what the yield keyword does, but just in case:

yield
http://msdn.microsoft.com/en-us/library/9k7k7cf0.aspx

If you have 3.5 or higher, you can use LINQ-to-XML to extract data, and then you wouldn't need an iterator, and the yield return statement.


public class PowersOf2
{
    public static System.Collections.IEnumerable Power(int number, int exponent)
    {
        int counter = 0;
        int result = 1;
        while (counter++ < exponent)
        {
            result = result * number;
            yield return result;
        }
    }

    static void Main()
    {
        // Display powers of 2 up to the exponent 8:
        foreach (int i in Power(2, 8))
        {
            Console.Write("{0} ", i);
        }
    }
}
/*
Output:
2 4 8 16 32 64 128 256 
*/

Open in new window

0
 
käµfm³d 👽Commented:
The yield keyword is used in the context of iterating over some collection or data structure. For instance, under the hood, something like the following could use yield:

foreach (XmlNode node in someNode.ChildNodes)
{

}

Open in new window


If you already have a collection or array, then there wouldn't be much call to use the yield keyword--unless you wanted to ensure the nodes were returned in some specific order.

Can you elaborate on the overall requirement and why you think you might need to use yield?
0
 
newbiewebSr. Software EngineerAuthor Commented:
LINQ to XML sound like it could be the missing link (no pun intended :)

I thought yield since that woudl allow me to write a fucntion that iterates the XmlDocument until done, returning one node at a time. That could work nicely I think. But maybe as kaufmed suggested, using the ChildNodes property in conjunction with a recursive function could also work.

I guess it really doesn't matter to me. I just want all the nodes, one by one.

List<XmlNode> could also work if you can fill it. There are child nodes, so that would be the trick, not needing to know the structure ahead of time.

The order does not matter, I just want all the nodes. And a function that returns them one at a time is okay too.

How can I code this?
0
Cloud Class® Course: Python 3 Fundamentals

This course will teach participants about installing and configuring Python, syntax, importing, statements, types, strings, booleans, files, lists, tuples, comprehensions, functions, and classes.

 
Bob LearnedCommented:
What does your XML look like?  What do you need to extract?
0
 
newbiewebSr. Software EngineerAuthor Commented:
everything. I should not need to describe it. There are messages at the root level and messages inside of widgets, which are at the root level.

I want a fucntion that's smart enough to get everything without knowing anything about the doc.

That seems like it shoud not be that hard to do...
0
 
newbiewebSr. Software EngineerAuthor Commented:
I would use recursion if I wanted to construct the search string for this kind of xPath call:

XmlNode node = xmlDoc.SelectSingleNode("/content-item/messages");

I could extract the names "content-item", "messages" and "message" from the XmlDocument and the node(s) found.
0
 
käµfm³d 👽Commented:
The thing to be mindful of when using ChildNodes is that nodes have types (e.g. Element, Text, CData, etc.). You can see the various types in the XmlNodeType enumeration. If you iterate over every node in the document, you are going to get all of these types of nodes. Even a simple node like:

<node>Hello World!</node>

Open in new window


has more than just one node--the text is considered a node as well. You may have to do some additional checking/filtering on the nodes in order to ensure you get the node types you are interested in.
0
 
newbiewebSr. Software EngineerAuthor Commented:
Sorry, I am new to XML. I only need the CDATA nodes, for every elemtn in the xDoc.
0
 
newbiewebSr. Software EngineerAuthor Commented:
yield does not work:

The body of 'ViewValidator.Validator.GetNode(System.Xml.XmlNode)' cannot be an iterator block because 'System.Xml.XmlNode' is not an iterator interface type      

0
 
newbiewebSr. Software EngineerAuthor Commented:
Here's what I have so far...

I am ading each CDATA node to the list, and doing it recursively.

What kind of test should I put in to be sure I only add CDATA nodes?


private List<XmlNode> AddUniqueNode(XmlNode node, List<XmlNode> nodeList)
        {
            if (node != null)
            {
                if (node.HasChildNodes)
                {
                    foreach (XmlNode childNode in node.ChildNodes)
                    {
                        if (!childNode.HasChildNodes)
                        {
                            nodeList.Add(childNode);
                        }

                        XmlNode result = AddUniqueNode(childNode, nodeList);                       
                    }
                }
            }

            return nodeList;
        }

Open in new window

0
 
newbiewebSr. Software EngineerAuthor Commented:
I mean what shal I add to this line?

if (!childNode.HasChildNodes)

so I only get CDATA?
0
 
newbiewebSr. Software EngineerAuthor Commented:
This should be changed to:

nodeList = AddUniqueNode(childNode, nodeList);    
0
 
newbiewebSr. Software EngineerAuthor Commented:
I found it:

if (node.NodeType == XmlNodeType.CDATA)
0
 
newbiewebSr. Software EngineerAuthor Commented:
Thanks.
0
 
Bob LearnedCommented:
Would you like to think about LINQ-to-XML?
0
 
newbiewebSr. Software EngineerAuthor Commented:
In the future. I would love to learn that, no question. When I have questions I will ask.

Where's a good place to read up on it?

Thanks.
0
 
Bob LearnedCommented:
So many resources, so little time...there really isn't one definitive source...I find that MSDN has good examples, but you need to dig to find them...

Understanding C#: Simple LINQ to XML examples (tutorial)
http://broadcast.oreilly.com/2010/10/understanding-c-simple-linq-to.html

I really love the power of LINQ-to-XML, because it lets you query your XML like it was a database.

Example:


var data = from item in doc.Descendants("person")
                 select new
                 {
                      drink = item.Element("favoriteDrink").Value,
                      moneySpent = item.Element("moneySpent").Value,
                      zipCode = item.Element("personalInfo").Element("zip").Value
                  }

Open in new window

0
 
newbiewebSr. Software EngineerAuthor Commented:
thanks.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.