Search code examples
watin

Navigating a DOM hierarchy in WatiN


I have a page that includes a list of lists and I'd like to navigate it with WatiN:

<div id="NestedLists">
    <ul>
        <li>
            <ul>
                <li>Sweet</li>
                <li>Sour</li>
                <li>Salty</li>
            </ul>
        </li>
        <li>
            <ul>
                <li>Red</li>
                <li>Yellow</li>
            </ul>
        </li>
    </ul>
</div>

I don't know how to loop through just the direct decendents of an Element. I thought this would work (note use of Lists and ListItems):

var treeControl = browser.Div(Find.ById("NestedLists"));
var listOfLists = treeControl.Lists.First();

Console.WriteLine("Outer List:");
foreach (var list in listOfLists.ListItems)
{
    Console.WriteLine("\tInner List:");
    foreach(var listItem in list.ListItems)
    {
        Console.WriteLine("\t\tList Item: " + listItem.Text);
    }
}

But that gives:

Outer List:
    Inner List:
        List Item: Sweet 
        List Item: Sour 
        List Item: Salty 
    Inner List:
    Inner List:
    Inner List:
    Inner List:
        List Item: Red 
        List Item: Yellow 
    Inner List:
    Inner List:

Solution

  • Ok, this is actually a tougher question than I realized, but here's a partial solution.

    The ChildrenOfType function can get the direct child of some elements including Div, List and ListItem. I've included a sample of how this works.

    However, the problem with this sample is that when you display the text of a ListItem using .Text, not only is the immediate text displayed, but the text of the child elements as well.

    At the very least, this sample code will provide a way to surf the list heirarchy. You could only output the text if the listItem has no child elements, but I don't know how well that works for your situation.

    public static void listSurfer(Div div)
        {
            Console.WriteLine("Outer List:");
            var innerLists = div.ChildrenOfType<List>();
            var innerListItems = div.ChildrenOfType<ListItem>();
            if (innerListItems.Count > 0)
            {
                foreach (var innerlist in innerLists)
                {
                    Console.WriteLine("List Item: " + innerlist.Text);
                }
            }
            listSurfer(innerLists, 1);
        }
    
        public static void listSurfer(ElementCollection<List> lstCollect, int depth)
        {
            foreach (List lst in lstCollect)
            {
                Console.WriteLine(tabNumber(depth) + "innerlist");
                var innerLists = lst.ChildrenOfType<List>();
                var innerListItems = lst.ChildrenOfType<ListItem>();
                if (innerListItems.Count > 0)
                {
                    foreach (var innerlist in innerListItems)
                    {
                        Console.WriteLine(tabNumber(depth + 1) + "List Item: " + innerlist.Text);
                        var subLists = innerlist.ChildrenOfType<List>();
                        if (subLists.Count > 0)
                            listSurfer(subLists, depth + 1);
                    }
                }
                if (innerLists.Count > 0)
                {
                    listSurfer(innerLists, depth + 1);
                }
            }
        }
    
        public static String tabNumber(int count)
        {
            String tabs = "";
            for (int i = 0; i < count; i++)
            {
                tabs = tabs + "\t";
            }
            return tabs;
        }
        private static int Main(string[] args)
        {
            Browser browser = new IE(@"C:\test.html");
    
            var treeControl = browser.Div(Find.ById("NestedLists"));
            listSurfer(treeControl);
        }