XPath - Select first element after some other element

Xpath

Xpath Problem Overview


I'm fairly new to XPath, been fiddling around with it for a few hours now, so i'm not entirely sure if you can even do something like the following with it.

Okay, here's the scenario: I want to find a link from a page. That link is only recognizable by it's text value, ie. the text between <a> tags (<a href="#">this link<a>). So far i've managed to get my hands on to link elements with that text, the only problem is that there's a few of those lying around.

These links are found from unordered lists which are preceded by another link tag, which would serve as a really good "anchor" point to begin the search for the final element that i want to find (ie. then i could just accept the first one that matches)

To clarify things a bit, here's an example of what's going on:

<a href="#">first dropdown menu</a>
<ul>
  <li><a href="#">some link</a></li>
  <li><a href="#">link i want to find</a></li>
</ul>

<-- *And i would actually want to find the thing from this list* --> 
<a href="#">second dropdown menu</a>
<ul>
  <li><a href="#">some link</a></li>
  <li><a href="#">link i want to find</a></li>
</ul>

And i should probably specify, that i only want to receive either one result or a set of results with the first element being the "correct" element - the element i want to find.

EDIT: The question has been answered already, but there were some comments that I should specify this a bit more, so that people could actually understand the question ;)

So the idea was to use an element to specify the location of another element that could have duplicate search results scattered all around the document.

Essentially you would run into something like this if you wanted to find a given link from a group of dropdown menus that would have elements with same names or values.

That's basically it. I know that it's still a bit difficult to get the point, but unfortunately I'm having a hard time trying to explain it better. I'm sure that somebody else could do a better job and if that happens, I'm more than happy to include that description here.

Xpath Solutions


Solution 1 - Xpath

I had to read through your question a couple of times but I think I understand it. What you are interested in is predicates. Predicates allow you to pick nodes based on conditions.

For example, you could do:

//a[text()='second dropdown menu']/following::ul[1]/li/a[text()='link i want to find']

this would select any anchor with certain text in, find the next ul, then proceed through it's children.

Also, you can specify positional index within a result set, the following XPath is a demonstration (but it won't solve your problem):

//a[text()='first dropdown menu']/ul/li[last()]/a/text()

or you could use axes to navigate across siblings/ancestors/children:

//a[ancestor::ul/preceding::a[1]/text() = 'second dropdown menu']/text()

So I'm not sure I quite understood your question but this should help you write your XPath.

Basically, I'm assuming your XPath matches the anchor in multiple lists and you want to make sure you pick the right one. At some point in your XPath you need a predicate to specify a condition that will only be true for the list your desired node is in.

Solution 2 - Xpath

just so i understand it correctly: you want the "some link" node after the "second dropdown menu"

ul[preceding::a[text()='second dropdown menu' and position()=last()]]/li/a[text()='link i want to find']

this should do the trick (I am not 100% sure that you will need to check for the position()=1, but I think that if you omit it, it will match all following ul since preceeding is "all" preceeding nodes - that depends on the rest of your xml structure)

Solution 3 - Xpath

Correct me if i'm wrong - you need select "second drop down menu" from example above, but text can be duplicated, so you need only second one. XPath:

//a[text()='second drop down menu'][2]

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJHollantiView Question on Stackoverflow
Solution 1 - XpathChris Cameron-MillsView Answer on Stackoverflow
Solution 2 - XpathNikoView Answer on Stackoverflow
Solution 3 - XpathDewfyView Answer on Stackoverflow