WatiN: При поиске текста, как получить ссылку на содержащий его элемент? - PullRequest
6 голосов
/ 19 января 2011

Учитывая следующую HTML-страницу:

<html>
<head>
    <title>WatiN Test</title>
</head>
<body>
<div>
    <p>Hello World!</p>
</div>
</body>
</html>

Я хотел бы иметь возможность искать некоторый текст (скажем, "World") и получать ссылку на его родительский элемент (в данном случае элемент <p>).


Если я попробую это:

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

или это:

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

Я возвращаю элемент <html>. Это согласуется с документацией WatiN для Element.Text, в которой говорится: «Получает внутренний текст этого элемента (и внутренний текст всех элементов, содержащихся в этом элементе)».

Поскольку весь текст на странице содержится в элементе <html>, я всегда получу его обратно вместо непосредственного родителя.


Есть ли способ получить только текст непосредственно под элементом (не текст внутри содержащихся в нем элементов)?

Есть ли другой способ сделать это?

Большое спасибо.

Ответы [ 3 ]

3 голосов
/ 06 июня 2012

Вы можете использовать Find.BySelector

var element = ie.Element(Find.BySelector("p:contains('World')"));
2 голосов
/ 20 января 2011

Ниже код найдет первый элемент внутри <body/> с текстом, содержащим «Мир».Элементы, которые классифицируются как контейнеры элементов и имеют дочерние элементы, будут опущены.

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;
});

Примечание : Вы можете удивиться, почему я написал ie.ElementOfType<Body>(Find.First()).Element вместо ie.Element.Это должно работать, но это не так.Я думаю, что это ошибка.Я написал сообщение об этом в списке рассылки WatiN и обновлю этот ответ, когда получу ответ.

1 голос
/ 19 января 2011

Я придумала что-то, что работает, но это немного глупо и очень неэффективно.

Это по существу работает на основе того, что самый глубокий содержащий элемент будет иметь самый короткий InnerHtml. То есть все остальные элементы, которые содержат непосредственного родителя, будут также включать его HTML, и, следовательно, будут длиннее!

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;
}
...