开发者

WatiN: When finding text, how do I get a reference to its containing element?

开发者 https://www.devze.com 2023-02-05 06:36 出处:网络
Given the following HTML page: <html> <head> <title>WatiN Test</title> </head>

Given the following HTML page:

<html>
<head>
    <title>WatiN Test</title>
</head>
<body>
<div>
    <p>Hello World!<开发者_C百科;/p>
</div>
</body>
</html>

I would like to be able to search for some text (lets say "World"), and get a reference to its parent element (in this case the <p> element).


If I try this:

var element = ie.Element(Find.ByText(t => t.Contains("World")))

or this:

var element = ie.Element(e => e.Text != null && e.Text.Contains("World"));

I get back the <html> element. This is consistent with the WatiN documentation for Element.Text which states: "Gets the innertext of this element (and the innertext of all the elements contained in this element)".

Since all text within the page is contained within the <html> element, I'll always get this back instead of the immediate parent.


Is there a way to get just the text immediately beneath an element (not the text within the elements contained by it)?

Is there another way of doing this?

Many thanks.


You could use Find.BySelector

var element = ie.Element(Find.BySelector("p:contains('World')"));


Bellow code will find first element inside the <body/> with text containing "World". Elements which are classified as element containers and has child elements will be omitted.

var element = ie.ElementOfType<Body>(Find.First()).Element(e =>
{
    if (e.Text != null && e.Text.Contains("World"))
    {
        var container = e as IElementContainer;
        if (container == null || container.Elements.Count == 0)
            return true;
    }
    return false;
});

Note: You may wonder why I wrote ie.ElementOfType<Body>(Find.First()).Element instead of just ie.Element. This should work, but it doesn't. I think it's a bug. I wrote a post about it on WatiN mailing list and will update this answer when I receive the answer.


I've come up with something that works, but it's a bit hacky and very inefficient.

This essentially works on the basis that the deepest containing element will have the shortest InnerHtml. That is, all other elements which contain the immediate parent will include it's HTML as well, and therefore be longer!

public static Element FindElementContaining(IElementsContainer ie, string text)
{
    Element matchingElement = null;

    foreach (Element element in ie.Elements)
    {
        if (element.Text == null) continue;

        if (!element.Text.ToLower().Contains(text.ToLower())) continue;

        // If the element found has more inner html than the one we've already matched, it can't be the immediate parent!
        if (matchingElement != null && element.InnerHtml.Length > matchingElement.InnerHtml.Length) continue;

        matchingElement = element;
    }

    return matchingElement;
}
0

精彩评论

暂无评论...
验证码 换一张
取 消