I have the following html:
<html>
<body>
<table>
<tr>
<tr>
<tr>
<tr>
<tr>
<td>Color Digest </td>
<td>AgArAQICGQMVBBwTIRQHIwg0GUMURAZTBWQJcwV0AoEDAQ </td>
</tr>
<tr>
<td>Color Digest </td>
<td>2,43,2,25,21,28,0,0,0,0,0,0,0,0,0,0,0,0,0,0,33,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, </td>
</tr>
</table>
</body>
</html>
and the following xpath:
tr[td='Color Digest']/td
and I'm getting zero results.
Can someone explain why?
Inside xPath expression we can use attribute name and tag name(when it has text) as well. Here both <tr> and <td> are tag names. The valid xPath expressions be like,
//tagname[#attributeName='value']
and
//tagname[#tagname='text']
Inside td there is only text available so you need to write xPath like
//td[text()='Color Digest ']
or
//tr[td='Color Digest ']
If you need to use specific element then please use the match number like below,
(//td[text()='Color Digest '])[1]
or
(//tr[td='Color Digest '])[1]
Why it showed 0 matches for your xPath?
You haven't given space at end of Digest.
Yours:
//tr[td='Color Digest']/td
Corrected one:
//tr[td='Color Digest ']/td
There are a few issues with your XPath
tr[td='Color Digest']/td
^ 1
^ 2
^ 3
XPaths should start with a / (child) or // (descendant). Child basically means one level down where descendant means one or more levels down.
tr should be //tr in this case since there are no root TRs.
You've used td when it looks like you meant to use . or text() which indicates two variations of text within the element. . means squash the contained text of all descendant nodes and text() means the contained text of just the current node.
Either text() or . will work in this case but I would generally use text() just to be safe.
[td='Color Digest'] should be [text()='Color Digest']
If you look at the HTML you provided, the text in the first TD actually contains a space at the end, e.g. 'Color Digest ' vs 'Color Digest'. That space is required unless you use a function like contains().
[td='Color Digest'] should be [text()='Color Digest ']
For this last one, I'm not sure what you are actually looking for, /td.
For the TD that contains the "Color Digest " text, it has no child. If you meant sibling TD, that would require /following-sibling.
/td should be /following-sibling::td[1].
Putting all of this together,
//tr[text()='Color Digest ']/following-sibling::td[1]
and it would return the following elements
<td>AgArAQICGQMVBBwTIRQHIwg0GUMURAZTBWQJcwV0AoEDAQ </td>
<td>2,43,2,25,21,28,0,0,0,0,0,0,0,0,0,0,0,0,0,0,...</td>
I have a set of survey questions each of which I am arranging in a single row table. I want the first entry to serve as a prompt and have been using <th> for that cell, as in:
<table style='width:100% table-layout:fixed;border-collapse: collapse;'>
<tr>
<th style='width:40%'>
<b>How long were you on active surveillance?</b>
</th>
<td style='width:10%;'>f3_watchtime_num</td>
<td style='width:5%'></td>
<td style='width:50%;>f3_watchtime</td>
</tr>
</table>
It seems to work OK but I have some reservations and questions about mixing <th> and <td> cells in a single <tr>:
Is this HTML5 Standards compliant? (Is there a W3C document that allows or prohibits this practice?)
Are there any downsides to this practice?
Thanks,
David
1. Is this HTML5 Standards compliant? (Is there a W3C document that allows or prohibits this practice?)
W3C tr reference says it's content model can contain:
Content Model:
Zero or more td, th, and script-supporting elements
https://www.w3.org/TR/html5/tabular-data.html#the-tr-element
While your usage isn't very common, there isn't anything in W3C that forbids it.
2. Are there any downsides to this practice?
As for the use of th and td together, its accepted by W3C provided they are children of a tr element.
However, if you are displaying tabular data, (i.e. your survey results are data) using a table is fine. If you are using the table for layout purposes, you should use a CSS based layout instead.
The recommendation of W3C is avoid to use tables for layouts. It is valid only for displaying ordered data, but that's not your case. You can achieve the same with <div> and will be semantically correct.
Other thing is your question about mixing. I think if you don't write <tbody> and <thead> tags, you don't separate the content for the headers in the table, so that's correct because there aren't <td> tags inside a <thead> and there aren't <th> tags inside a <tbody>.
However, it's better practice if you don't use tables for this purpose.
I have an issue with selecting a table to be read in Selenium.
I have a table in which there is two 'tr' elements inside the 'thead', and I need to find a way to ignore the first of these.
Here is the code:
<table class="noselect">
<thead>
<tr>
<th> </th>
<th class="number IOL">Interest Rates</th>
<th class="number IO">
</tr>
<tr>
<th>Description</th>
<th class="number">Value</th>
<th class="number">Percentage</th>
</tr>
</thead>
<tbody>
<tr>
<tr class="">
<tr class="">
<tr class="">
<tr>
<tr>
</tbody>
</table>
Using Selenium I will ask it to record the value of a certain row and column . This will then look at the Table element I will give it (hopefully using an XPath I can get working in this case), look at the thead and record the headers of each column. In this case that I am struggling with, the fact there is an extra 'tr' at the top of this table gets in the way of this process.
This is how the element is currently used:
[TableAlias("Detailed table")]
protected virtual IWebElement DetailedTable()
{
return Driver.FindElement(By.XPath("//table[#class='noselect']"));
}
I have tried many different ways which I can't get to work, but the gist of what I've been going for is:
//table[#class='noselect movements']/thead/tr/th[not(text()='Interest Rates')]/../../..
Here I'm stuck on going to the 'tr' element, telling it not to use it then backing out, but that selects it back again - and even that doesn't unselect the whole 'tr' element. It doesn't seem to help (to me) that the 'tr' element I'm trying to remove is blank with no class or defining features.
Is there a way of selecting the entire table except for the first 'tr' element in 'thead' as one element?
combine two xpathes. The 1st xpath take thead without the 1st tr and the 2nd tbody
//table/thead/tr[not(position()=1)] | //table/tbody
In your function that processes the THEAD tag, get the collection of TRs and start with [1] (skipping [0]) and process the rest.