I have HTML structure like this:
<table>
<tr>
<td>some value 1</td>
<td>unique value 1</td>
<td>needed value 1</td>
<td>some value 1</td>
</tr>
<tr>
<td>some value 2</td>
<td>unique value 2</td>
<td>needed value 2</td>
<td>some value 2</td>
</tr>
<tr>
<td>some value 3</td>
<td>unique value 3</td>
<td>needed value 3</td>
<td>some value 3</td>
</tr>
</table>
I use Selenium and need to point to td next to unique value by searching this unique value using XPath.
I have found solution: find tr with needed unique value, then count td's preceding-sibling and use position()=count(preceding-sibling)+2
//tr[./td[text()='Unique value 2']]/td[position()=count(//tr[./td[text()='Unique value 2']]/td[text()='Unique value 2']//preceding-sibling::td)+2]
Is there any easier way?
Problem is that structure of table may change in time, but needed value will always be next to unique
Instead of using preceding-sibling, use following-sibling:
//td[text()="unique value 2"]/following-sibling::td[1]
Related
Here is an excerpt of my xml:
<table>
...
<tbody>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
I know how to find specific <tr> tag.
Is it possible to define <tr> tag index or ordinal number inside the <tbody> tag? I guess, that it's possible to loop through the table, but the table is quite large and it will take lots of time.
Is it possible to get this index/ordinal number with single XPATH statement?
I've used following XPath expression:
//tbody//td[text()='findMe']/../following-sibling::tr
These expression calculates, how many 'tr' nodes are located under the node with 'findMe' text. Actually, it useful, because quantity of 'tr' nodes could be obtained.
But, prior to given XPath, a verification should be made, because in case 'finMe' string would be absent, XPath would return 0. The following expression works as validation fine:
//tbody//td[text()='findMe']
I would like to get all table rows after a specific row identifier (an attribute on the row column) until that specific row identifier is found.
Here is the html I'm trying to parse:
<tr>
<td colspan="4">
<h3>Header 1</h3>
</td>
</tr>
<tr>
<td>Item desc - Header 1</td>
<td>more info</td>
<td>30</td>
<td>500</td>
</tr>
<tr>
<td colspan="4">
<h3>Header 2</h3>
</td>
</tr>
<tr>
<td>Item desc - header 2</td>
<td>other</td>
<td>4</td>
<td>49</td>
</tr>
<tr>
<td>Item 2 desc - header 2</td>
<td>other 2</td>
<td>65</td>
<td>87</td>
</tr>
I want to be able to grab the item under header 1 and stop when it finds header 2; then the items under header 2 and stop when it finds a header 3; etc.
Is this possible under xpath? I can't get it to only find the TR nodes until it finds a child node with a specific attribute (of colspan="4").
This is not possible under XPath 1.0. You somehow have to fixate the header tr, because you are trying to find all its following siblings whose first preceding header tr is the original one. Without the reference to the original header, everything is possible. But you probably work in some kind of a language that you can use to remember the value.
For example, in xsh:
for my $x in //tr[td/#colspan="4"] {
echo ($x/td/h3) ;
for $x/following-sibling::tr[count(td)=4
and preceding-sibling::tr[count(td)=1][1]=$x]
echo " " (td) ;
}
Output:
Header 1
Item desc - Header 1 more info 30 500
Header 2
Item desc - header 2 other 4 49
Item 2 desc - header 2 other 2 65 87
This might give you what you're looking for, not the most orthodox means though:
//*/tr/td[not(child::h3)]/ancestor::tr
This will give you all the <td> nodes within a <tr> that isn't a header block.
And you can specify the header with:
//*/tr/td[not(child::h3/text()='Header 1')]/ancestor::tr
Or a more general:
//*/tr/td[not(child::h3[contains(text(),'Header')])]/ancestor::tr
Suppose I have a table with the following rows,
...
<tr>
<th title="Library of Quintessential Memes">LQM:</th>
</tr>
<tr>
<th title="Library of Boring Books">LBB:</th>
</tr>
...
I would like to select all <tr> elements whose first <th> child's text starts with "L". How can I do this using XPath selectors?
Use the starts-with function:
//tr[starts-with(th[1],"L")]
i want to get the values of every table and the href value for every within the table given below.
Being new to xpath, i am finding it difficult to write xpath expression.
However understanding what an xpath expression does lies somewhat in an easier category.
the expected output
http://a.com/ data for a 526735 Z
http://b.com/ data for b 522273 Z
http://c.com/ data for c 513335 Z
<table class = dataTabe>
<tbody>
<tr>
<td>data for a</td>
<td class="numericalColumn">526735</td>
<td class="numericalColumn">Z</td></tr>
<tr>
<td>data for b</td>
<td class="numericalColumn">522273</td>
<td class="numericalColumn">B</td></tr>
<tr>
<td>data for c</td>
<td class="numericalColumn">513335</td>
<td class="numericalColumn">B</td></tr>
</tbody>
</table>
You'll need two things: an XPath query which locates the wanted nodes and a second which outputs the text as you want it. Since you don't give more information about the languages you're using I'm putting together some pseudocode:
foreach node in document.select("//table[class='dataTable']//tr[td/a/#HREF]")
write node.select("concat(td/a/#HREF,' ',.)")
This site has a great free tool for building XPath Expressions (XPath Builder):
http://www.bubasoft.net/
Use this XPath: //tr/td/a/#HREF | //tr//text()
I have this XPath:
//tr[contains(td, 'Europe')]
which was working when I had this:
<tr>
<td></td>
<td>Europe</td>
<td></td>
</tr>
but now I have this:
<tr>
<td></td>
<td><a>Europe</a></td>
<td></td>
</tr>
How can I get with an XPath now (based on the fact that Europe is in there).
I tried:
//tr[contains(a, "Europe")]
and
//tr[contains(text(), "Europe")]
and many other silly things without any success.
//tr[contains(td, 'Europe')]
This should work with both schema because fn:contains() cast both arguments to strings.
I do see a problem with a different schema where there can be more than one td element. For that case you should use:
//tr[td[contains(.,'Europe')]]