Find Closest Element by Id

Best practices, code snippets for common functionality, examples, and guidelines.
haniball
Posts: 13
Joined: Fri Sep 18, 2015 2:27 pm

Find Closest Element by Id

Post by haniball » Tue Sep 22, 2015 11:17 am

-LIST
--Listitem
---Headline
---Status

Step1: I get all the headlines in a list via the Find<Text>('text[@automationid='headline']"') method. I now have a IList<Text> headlines.

Step2: I find the element with a specific headline via a Linq Query like myHeadlines.First(x=>x.TextValue == "Hadline1");. I now have the element Text specialHeadline.

Step3: I now want know the status of that listitem with my special headline. But how can I find the closest element with the automationid status without messy code?

I might be able to say myHeadline.Parent.Find but what if there is an extra container inbetween etc. I am looking for an equivalent to https://api.jquery.com/closest/ in Ranorex.

Vaughan.Douglas
Posts: 250
Joined: Tue Mar 24, 2015 5:05 pm
Location: Des Moines, Iowa, USA

Re: Find Closest Element by Id

Post by Vaughan.Douglas » Wed Sep 30, 2015 2:38 pm

Could you provide an example of the DOM?

The little outline you've provided seems like you've got the "Headline" object and you could just grab the status by using the "following-sibling" axis.

Code: Select all

objHeadline.findsingle("following-sibling::status")
this will get the following sibling that is a status tag.

Something like this should work for either

-LIST
--Listitem
---Headline
---Status

OR

-LIST
--Listitem
---Headline
---ExtraContainer
---Status

Let me know if this helps or if I misunderstood the situation.
Doug Vaughan

haniball
Posts: 13
Joined: Fri Sep 18, 2015 2:27 pm

Re: Find Closest Element by Id

Post by haniball » Thu Oct 15, 2015 8:52 am

Thanks following-sibling is a good hint but not the real solution. Sometimes the text is in an extra label field etc. and sibling takes only elements on the same tree-level (as far as I understood). The closest method would scan for the nearest element in the tree that matches the criteria. Is there no such thing in Ranorex?

Vaughan.Douglas
Posts: 250
Joined: Tue Mar 24, 2015 5:05 pm
Location: Des Moines, Iowa, USA

Re: Find Closest Element by Id

Post by Vaughan.Douglas » Thu Oct 15, 2015 1:15 pm

Ranorex has the concept of optional location.

Example: /form/container?/button
optional location step fitting a container adapter between form and button; identifies both, '/form/container/button' and '/form/button'
I prefer doing this using regular old Xpath:

Code: Select all

'/form/descendant-or-self::button
This is a pattern I use on a regular basis. I'll use something like this:

Code: Select all

descendant::label[@innertext~'(Last Name|Paternal Last)']/parent::td/following-sibling::td/descendant::input
to describe this:
10-15-2015 6-38-18 AM.png
10-15-2015 6-38-18 AM.png (12.08 KiB) Viewed 1328 times
10-15-2015 6-40-29 AM.png
10-15-2015 6-40-29 AM.png (4.5 KiB) Viewed 1328 times

So back to your sample DOM

-LIST
--Listitem
---Headline
---Status

or

-LIST
--Listitem
---Headline
---ExtraContainer
----Status

Could be achieved as such

Code: Select all

objHeadline.findsingle("following-sibling::*/descendant-or-self::status")
The following-sibling::* will grab ALL of the siblings that follow Headline regardless of tag.
The descendant-or-self::status will scan each of those siblings to grab the Status tag(s) that are either a direct sibling of Headline or a descendant of a direct sibling or Headline.

To my knowledge there is no method that will scan for the closest element in all directions at once. One of the various find methods are your best bet, but you still need to provide some kind of relationship between the two elements.

If the text you're looking for is sometimes in the Status element and sometimes a descendant of that Status element, I would go about getting the status element as above then search using a regular expression or something like descendant-or-self::*[@innertext~[A-Za-z]+]

or this:

Code: Select all

objHeadline.findsingle("following-sibling::*/descendant-or-self::status/descendant-or-self::*[@innertext~[A-Za-z]+]")
If using a combination of following-sibling and descendant-or-self doesn't get you what you need then I have a fundamental misunderstanding of your situation and I really would need to see the DOM to help.
Doug Vaughan