Appium — Xpath для получения прямых дочерних элементов, не работающих на Android

#android #xpath #appium #children

#Android #xpath #appium #дочерние элементы

Вопрос:

По какой-то причине я не могу получить все прямые дочерние элементы элемента на Android. По-видимому, XPath некорректно работает при поиске подэлементов в элементе или область XPath некорректно реализована в Appium.

 parentElement.findElements(By.xpath(...))
  

Что я пробовал:

 *
./*
.//*
.//child::*
./child::*
//*
//child::*
  

Мои результаты либо равны нулю, все узлы (даже за пределами родительского элемента), либо все дочерние элементы.

Единственное, что сработало для меня, это:

 .//*[@resource-id='RESOURCE-ID-OF-PARENT']/child::*
  

Но это очень плохое решение, потому что может быть несколько элементов с одинаковым идентификатором ресурсов (К вашему сведению, я кодирую оболочку на основе Appium)

Я попытался найти все ответы здесь, но не смог найти ни одного рабочего решения.

Приветствуется любая помощь, спасибо.

Комментарии:

1. Может быть полезна некоторая дополнительная информация. Можете ли вы описать, какие типы дочерних элементов вы ищете? Недоступны ли дочерние элементы иным образом? Я понимаю, что вы, возможно, не сможете поделиться многим, но скриншот дерева иерархии экрана uiautomator может помочь, особенно если вы можете выделить свои «родительские» и потенциальные дочерние элементы, а в идеале свойства родительского и хотя бы одного дочернего элементов.

2. Конечно. Например, я хочу получить все элементы представления recycler. Ну, я не говорю о каком-либо конкретном дереве иерархии. Я хочу создать класс-оболочку, который позволяет мне находить ВСЕ (независимо от того, какого типа) дочерние элементы данного объекта Appium Element (класс WebElement и его подклассы).

Ответ №1:

Это как сказал Йори Хендриккс. Реальный узел и его дерево скрываются под поддельным узлом.

Просто попробуйте напечатать всех потомков вашего элемента; вы увидите всех потомков (очевидно), а также одного, который имеет тот же идентификатор, что и ваш элемент.

Его метод опробован, и он работает; для меня /*/* тоже работает.

Ответ №2:

Я нашел какой-то обходной путь:

1) Напишите функцию, которая сравнивает два элемента. Поскольку предоставленный метод equals не работает для собственных элементов (Android, iOS), должна быть написана собственная реализация. Я сравниваю наиболее релевантные атрибуты, такие как класс, идентификатор ресурса и описание содержимого, а также размер, местоположение и границы. Это должно сработать в 99% случаев, если только не присутствуют два одинаковых перекрывающихся элемента.

2) Запросите xpath родительского элемента ( findElementsByXpath ) с наиболее точными атрибутами — именем тега, классом, идентификатором ресурса и описанием содержимого. В большинстве случаев будет только один элемент, но если их больше, просмотрите список и используйте сравнение на основе функции равенства.

3) Отметьте индексы элементов в списке и всякий раз, когда будет найдено совпадение, запустите другой запрос в этом формате:

 (//tagName[@class=... and @resource-id= ...etc...])[index]/child::*
  

Помните, что индексация в Xpath начинается с 1. Список результатов — это фактические дочерние элементы родительского элемента.

Обходной путь не самый быстрый, но все же лучше, чем ничего.

Ответ №3:

Это чисто экспериментально, но, похоже, обработка xpath в Appium на самом деле начинается не с выбранного узла в качестве корневого (как можно было бы ожидать), а с поддельного узла, который содержит только этот текущий узел в качестве дочернего (а затем его дерево под ним)

Я попробовал следующее: .//*/child::* и это, похоже, сработало для меня.