lfreedoml
lfreedoml

Reputation: 55

What does */ mean in XPath?

Why did my XPath,

//android.view.ViewGroup[*/android.widget.TextView[@androidXtext='Microwaves']]

select this node,

<android.view.ViewGroup androidXclickable="true" androidXcontentDescription="ucl.flex-row" androidXenabled="true" androidXfocusable="true" androidXid="@ucl.flex-row" androidXlayout_height="147px" androidXlayout_width="1059px" androidXlayout_x="11px" androidXlayout_y="913px">` 

and not any other above or below?

Full fragment:

<android.view.ViewGroup androidXenabled="true" androidXlayout_height="147px" androidXlayout_width="1059px" androidXlayout_x="11px" androidXlayout_y="913px">
  <android.view.ViewGroup androidXclickable="true" androidXcontentDescription="ucl.flex-row" androidXenabled="true" androidXfocusable="true" androidXid="@ucl.flex-row" androidXlayout_height="147px" androidXlayout_width="1059px" androidXlayout_x="11px" androidXlayout_y="913px">
    <android.view.ViewGroup androidXenabled="true" androidXlayout_height="147px" androidXlayout_width="1059px" androidXlayout_x="11px" androidXlayout_y="913px">
      <android.view.ViewGroup androidXcontentDescription="ucl.flex-row.left-action.svg" androidXenabled="true" androidXid="@ucl.flex-row.left-action.svg" androidXlayout_height="63px" androidXlayout_width="63px" androidXlayout_x="53px" androidXlayout_y="955px">
        <android.view.ViewGroup androidXenabled="true" androidXlayout_height="63px" androidXlayout_width="63px" androidXlayout_x="53px" androidXlayout_y="955px">
          <android.view.ViewGroup androidXenabled="true" androidXlayout_height="0px" androidXlayout_width="0px" androidXlayout_x="53px" androidXlayout_y="955px">
            <android.view.ViewGroup androidXenabled="true" androidXlayout_height="0px" androidXlayout_width="0px" androidXlayout_x="53px" androidXlayout_y="955px"/>
          </android.view.ViewGroup>
        </android.view.ViewGroup>
      </android.view.ViewGroup>
      <android.widget.TextView androidXcontentDescription="ucl.flex-row.main.text" androidXenabled="true" androidXid="@ucl.flex-row.main.text" androidXlayout_height="53px" androidXlayout_width="891px" androidXlayout_x="137px" androidXlayout_y="960px" androidXtext="Microwaves"/>
    </android.view.ViewGroup>
  </android.view.ViewGroup>
</android.view.ViewGroup>

Upvotes: 1

Views: 1895

Answers (2)

kjhughes
kjhughes

Reputation: 111621

Two concepts in play here, node tests and axes:

  1. * is equivalent to element(), selecting elements without regard to name.

  2. The default axis is child::, so your predicate effectively starts with child::element().

Therefore,

//android.view.ViewGroup[*/android.widget.TextView[@androidXtext='Microwaves']]

means to select all android.view.ViewGroup elements with a grandchild android.widget.TextView element that has a androidXtext attribute value equal to 'Microwaves'.

When you ask specifically,

and not any other above or below

aside from your sample XML having no other elements that meet the above criteria, note that if you were interpreting */ to be a wildcard that selected to all descendents, it does not. As explained above, it only skips past children elements. To select and test all descendent android.widget.TextView elements in the predicate, instead of */android.widget.TextView use descendent::android.widget.TextView or descendent-or-self::android.widget.TextView (abbreviated form: .//android.widget.TextView).

See also

Upvotes: 2

nwellnhof
nwellnhof

Reputation: 33638

The XPath default axis is child, so your predicate

[*/android.widget.TextView[@androidXtext='Microwaves']]

is equivalent to

[child::*/child::android.widget.TextView[@androidXtext='Microwaves']]

This predicate will select nodes with a android.widget.TextView grandchild and the specified attribute.

Upvotes: 2

Related Questions