XPath - cannot select from root node?

I’d like to be able to select from the root node, but everything I try starting with / doesn’t work.

This is an issue because, for Android, //foo[1]/bar can happen in multiple places in the hierarchy - much more commonly than in iOS’s view hierarchy.

I want to, instead, do /foo[1]/bar/ so that I’m sure I’m looking at, relative to the top, foo[1]'s bar children. (Ideas about how to solve this problem with UiSelector are very welcome!)

Ex. view hierarchy and server logs:

android.view.View  # there are many of these. I need to select a specific one.
    * android.widget.FrameLayout
    - android.view.View
      * android.widget.FrameLayout
      * android.widget.FrameLayout
  ...

Given the above hierarchy, I would expect this to work and give me 1 element:

/android.view.View[1]/android.widget.FrameLayout

Unfortunately, no elements can be found.

info: --> POST /wd/hub/session/e774c836-a34c-4f01-b8c9-5d8f7f7dc3ed/elements {"using":"xpath","value":"/android.view.View[1]/android.widget.FrameLayout"}
info: [debug] Pushing command to appium work queue: ["find",{"strategy":"xpath","selector":"/android.view.View[1]/android.widget.FrameLayout","context":"","multiple":true}]
info: [debug] [BOOTSTRAP] [debug] Got data from client: {"cmd":"action","action":"find","params":{"strategy":"xpath","selector":"/android.view.View[1]/android.widget.FrameLayout","context":"","multiple":true}}
info: [debug] [BOOTSTRAP] [debug] Got command of type ACTION
info: [debug] [BOOTSTRAP] [debug] Got command action: find
info: [debug] [BOOTSTRAP] [debug] Finding /android.view.View[1]/android.widget.FrameLayout using XPATH with the contextId:  multiple: true
info: [debug] [BOOTSTRAP] [debug] Returning result: {"value":[],"status":0}
info: [debug] Responding to client with success: {"status":0,"value":[],"sessionId":"e774c836-a34c-4f01-b8c9-5d8f7f7dc3ed"}
info: <-- POST /wd/hub/session/e774c836-a34c-4f01-b8c9-5d8f7f7dc3ed/elements 200 76.238 ms - 74 {"status":0,"value":[],"sessionId":"e774c836-a34c-4f01-b8c9-5d8f7f7dc3ed"}

Afaict, absolute paths are totally borked in the latest code (assuming that’s what you’re using). I tried getting all Children of Root (there’s a bad cyberpunk novel in there somewhere) w /* and got nada.

As a workaround, I think you’re going to have to get creative with relative paths and not. E.g., request the FrameLayout that does not have a View parent.

and //* causes the server to implode :smile:

But yeah. I was just trying to help out this guy on StackOverflow because he didn’t want to use resource-id. Meh

That’s strange. //* works for me. Are you using the equiv of getElementsByXpath (plural)?

I’m using inspector to test my xpaths. I’ll post logs at some point in a separate ticket

//* should work!

Looking at the plain /foo[1]/bar case

//* definitely works for me.

On android ApiDemos app using wd.js:
driver.elementsByXPath("//*" ,console.log);

@JessicaSachs okay, here’s what’s going on:

Calling the UiAutomator function that dumps the xml hierarchy, it plops down a ton of xml, with no root element. In order to consume it as valid xml, we add a wrapper “” around it all. But you can never actually find that element (’/hierarchy’) because it doesn’t actually exist in the UI. We filter it out, rather than having it return in a query like //*.

This xpath expression works: /hierarchy/android.widget.FrameLayout (or whichever the element is…).

So what would you suggest as a more intuitive fix? Have /* return a more explicit error?

The //* problem:

  • Only with 1.2.3 (gist of when it happened, the command just kept executing until I killed the server)
    • Only happened on a certain screen for me
  • 1.2.4 upgrade seems to fix the problem

Glad to know the //* problem was only intermittent.

Any thoughts on what to do about the shadow element?

@jonahss

So on iOS it’s a little different, right? Doesn’t Appium set UIAApplication to be root by default and then xpath calls like /UIAWindow[1] work?

I don’t know what the correct design call is, but I think the internals of Appium, how it deals with invalid xml, should be hidden and an effort made to standardize crossplatform.

I don’t want to write /hierarchy/android.widget.FrameLayout’ when I want root. I want to write /android.widget.FrameLayout.

Then, if/when UiAutomator is updated, and it actually returns valid xml, Appium can remove the /hierarchy workaround, and my client doesn’t need to care.


shadow element?

I said “shadow element” cus it’s in the xml but not in the UI.

Right, iOS is different. This is fine. What we could do is intercept xpath expressions that look like this /android.widget.FrameLayout and insert the hierarchy so it works like /hierarchy/android.widget.FrameLayout without the user having to know about <hierarchy>

1 Like

That seems extremely reasonable. We should be explicit we’re doing that in the documentation.

1 Like

There’s a root element, it just doesn’t correspond to a selectable control.

Ah, my mistake. thanks.

@jonahss

Someone needs to write a cyberpunk trilogy XPaths:
Children of Root
Shadow Element
Empty Union or maybe The Axis Operator

1 Like

Could do some decent cover art with names like that.