Chris Noe
Chris Noe

Reputation: 37181

Is there a DRYer XPath expression for union?

This works nicely for finding button-like HTML elements, (purposely simplified):

  //button[text()='Buy']
| //input[@type='submit' and @value='Buy']
| //a/img[@title='Buy']

Now I need to constrain this to a context. For example, the Buy button that appears inside a labeled box:

//legend[text()='Flubber']

And this works, (.. gets us to the containing fieldset):

  //legend[text()='Flubber']/..//button[text()='Buy']
| //legend[text()='Flubber']/..//input[@type='submit' and @value='Buy']
| //legend[text()='Flubber']/..//a/img[@title='Buy']

But is there any way to simplify this? Sadly, this sort of thing doesn't work:

//legend[text()='Flubber']/..//(
  button[text()='Buy']
| input[@type='submit' and @value='Buy']
| a/img[@title='Buy'])

(Note that this is for XPath within the browser, so XSLT solutions will not help.)

Upvotes: 5

Views: 244

Answers (2)

user357812
user357812

Reputation:

From comments:

Adjusting slightly to obtain the A rather than the IMG: self::a[img[@title='Buy']]. (Now if only 'Buy' could be reduced

Use this XPath 1.0 expression:

//legend[text() = 'Flubber']/..
   //*[
      self::button/text()
    | self::input[@type = 'submit']/@value
    | self::a/img/@title
    = 'Buy'
   ]

EDIT: I didn't see the parent accessor. Other way in one direction only:

//*[legend[text() = 'Flubber']]
   //*[
      self::button/text()
    | self::input[@type = 'submit']/@value
    | self::a/img/@title
    = 'Buy'
   ]

Upvotes: 2

Wayne
Wayne

Reputation: 60414

Combine multiple conditions in a single predicate:

//legend[text()='Flubber']/..//*[self::button[text()='Buy'] or 
                                 self::input[@type='submit' and @value='Buy'] or
                                 self::img[@title='Buy'][parent::a]]

In English:

Select all descendants of the parent (or the parent itself) for any legend element having the text "Flubber" that are any of 1) a button element having the text "Buy" or 2) an input element having an attribute type whose value is "submit" and an attribute named value whose value is "Buy" or 3) an img having an attribute named title with a value of "Buy" and whose parent is an a element.

Upvotes: 3

Related Questions