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?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
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
CompTIA Cloud+

The CompTIA Cloud+ Basic training course will teach you about cloud concepts and models, data storage, networking, and network infrastructure.

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
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
ASP.NET

From novice to tech pro — start learning today.