I am trying to create an XPath that will allow me to verify if a row in a table where label is "X" has the correct drop down value.
The XPath for the label is
//*[#id="mainContent"]/table/tbody/tr/td/center/table/tbody/tr/td/table/tbody/tr/td/table/tbody/tr[14]/td[1]/b
The XPath for the drop down is
//*[#id="mainContent"]/table/tbody/tr/td/center/table/tbody/tr/td/table/tbody/tr/td/table/tbody/tr[14]/td[2]/select
How can I modify these so I only need one XPath?
Assuming that the "X" label is unique:
//td[. = 'X']/following-sibling::td[1]/select
Or, you can retain some,
//*[#id="mainContent"]//td[. = 'X']/following-sibling::td[1]/select
or all,
//*[#id="mainContent"]/table/tbody/tr/td/center/table/tbody/tr/td/table/tbody/tr/td/table/tbody/tr[14]/td[1]/following-sibling::td[1]/select
of the original path as necessary to meet whatever generality/specificity is required given the data on the page.
Similar to kjhughes' answer, but I would use
//td[1][b = 'X']/../td[2]/select
[b = 'X'] more closely matches what the OP asked, since the td could have other content besides the label (including whitespace-only nodes). And using td[1]/td[2] ensures that we use the first two columns, as the OP did.
Related
I have a sample list of student and grades/subject in this file
enter image description here
https://docs.google.com/spreadsheets/d/1NeHlUaRnbvdJ2yJ38fUETGgBoYseQ8CuXmwRCwObAlM/edit#gid=0
On the range A16:A I'd like to see the list of names who has the grades of around 90-100 when I check any of the checkbox on B15:k15
the first example is when I check all of the boxes
I will only see the first name on the list because he is the only one with the 90-100 scores on all subject
2nd example when I check B15 and C15
I will only see the 1st and 2nd names on the list because he's those who only able to get a 90-100 score on those two subjects.
Is there a way to do this kind of filtering? thank you so much
Since this is your first post, I'm going to go with the approach I think you'll find easiest to understand. It's a long formula (which I've placed in a new sheet called "Erik Help" in A16), but it's just a repeat of the same element several times:
=FILTER(A2:K11, IF(B15=TRUE, B2:B11>=90, B2:B11^0), IF(C15=TRUE, C2:C11>=90, B2:B11^0), IF(D15=TRUE, D2:D11>=90, D2:D11^0), IF(E15=TRUE, E2:E11>=90, E2:E11^0), IF(F15=TRUE, F2:F11>=90, F2:F11^0), IF(G15=TRUE, G2:G11>=90, G2:G11^0), IF(H15=TRUE, H2:H11>=90, H2:H11^0), IF(I15=TRUE, I2:I11>=90, I2:I11^0), IF(J15=TRUE, J2:J11>=90, J2:J11^0), IF(K15=TRUE, K2:K11>=90, K2:K11^0))
The first argument of FILTER tells the function what to filter (in this case A2:K11).
After that, an IF statement is set up to check each checkbox. If the checkbox is checked, the FILTER will only include students who obtained a 90 or higher in that subject.
If the checkbox is NOT checked, then the student is automatically included (that's the part that says "B2:B11^0" etc., since anything to the zero-power equals 1, and 1 and TRUE are the same to Google Sheets). In other words, if no checkboxes were checked, then all students would read TRUE for all subjects, i.e., all students would be included (or, to think of it another way, no one is rules out). While the ^0 is not strictly necessary (i.e., any number other than zero is the same as TRUE), I think it's better formula practice and easier for others to understand if TRUE is represented either as TRUE or as 1.
I also set conditional formatting on A15:A, to bold the name as you had it. (The conditional formatting rule says, in English, "If anything is there, use bold.") You can see the rule by clicking anywhere in the range A15:A, then selecting Format > Conditional formatting from the menu and clicking the open the rule that appears in the window to the right of the screen.
I am having trouble using selecting from this select element.
<select name="vehicle_attrs[position_count]" class="mb1"><option>Position / Quantity</option><option>Front</option><option>Rear</option></select>
I have tried
select('Front', :from=>'mb1')
select('Front', :from=>'vehicle_attrs[position_count]')
select('Front', :from=>'vehicle_attrs[1]')
All of them result in a can not find selection box error
I've never liked how restrictive Capybara's concept of a 'locator' is (i.e. must have a name/id/label), but if you dig into the source code, those helpful methods like select, click_on, and fill_in are just wrappers for find and some native method of Element, which takes arbitrary CSS, and works in almost all situations. In this case, you could use:
find('[name="vehicle_attrs[position_count]"]').find('option', text: 'Front').select_option
Since dropdowns often have multiple similar options, where one is a substring of the other, you might consider using an exact string match, like
find('[name="vehicle_attrs[position_count]"]').find('option', text: /\AFront\z/).select_option
From the docs for select - https://www.rubydoc.info/github/teamcapybara/capybara/Capybara/Node/Actions#select-instance_method - we can see that the from option takes "The id, Capybara.test_id atrtribute, name or label of the select box".
Neither 'mb1' or 'vehicle_attrs[1]' are any of those so they would be expected to fail.
'vehicle_attrs[position_count]' is the name so assuming the box is actually visible on the page (not replaced with a JS driven select widget, etc), that should work. If it doesn't, then edit your question and add the full exact error message you get when trying to use it. Of course if there is only one select box on the page with an option of 'Front' then you don't need to specify the from option at all and can just do
select 'Front'
In SSRS I want to indent certain rows when they start with e.g. 'aa'. See this example:
What is the best practice in this case? As I don't have a parent-child situation here (to use recursive hierarchy group), do I have an option e.g. via the properties to set something like an IIf to solve this? If yes, could you please provide some information where to set this?
Every info is welcome! I'm new to SSRS.
This is simple to do...
Click on the cell that you want to indent.
In the properties panel, expand the Indent properties and then click the drop-down in the Left Indent property and choose Expression.
Then set the expressions to something like
=SWITCH (
LEFT(Fields!FieldIwantToCheck.Value, 2) = "aa", "10pt",
LEFT(Fields!FieldIwantToCheck.Value, 2) = "bb", "30pt",
True, "0pt"
)
You could do this with an IIF expression but if you need to make it more flexible than 1 or two cases then SWITCH is much easier to read/manage.
All we are doing here is checking the left 2 characteras of the FieldIwantToCheck field and setting an indent value respectivley. If none of the criteria match, the final True, Nothing acts like an ELSE and leaves the property as the default Nothing value.
I am trying to find a way to return the index of a HTML child tag based on its xpath.
For instance, on the right rail of a page, I have three elements:
//*[#id="ctl00_ctl50_g_3B684B74_3A19_4750_AA2A_FB3D56462880"]/div[1]/h4
//*[#id="ctl00_ctl50_g_3B684B74_3A19_4750_AA2A_FB3D56462880"]/div[2]/h4
//*[#id="ctl00_ctl50_g_3B684B74_3A19_4750_AA2A_FB3D56462880"]/div[3]/h4
Assume that I've found the first element, and I want to return the number inside the tag div, which is 1. How can I do it?
I referred to this previous post (How to count HTML child tag in Selenium WebDriver using Java) but still cannot figure it out.
You can get the number using regex:
var regExp = /div\[([^)]+)\]/;
var matches = regExp.exec("//[#id=\"ctl00_ctl50_g_3B684B74_3A19_4750_AA2A_FB3D56462880\"]/div[2]/h4");
console.log(matches[1]); \\ returns 2
You can select preceeding sibling in xpath to get all the reports before your current one like this:
//h4[contains(text(),'hello1')]/preceding-sibling::h4
Now you only have to count how many you found plus the current and you have your index.
Another option would be to select all the reports at once and loop over them checking for their content. They always come in the same order they are in the dom.
for java it could look like this:
List<WebElement> reports = driver.findElements(By.xpath("//*[#id='ctl00_ctl50_g_3B684B74_3A19_4750_AA2A_FB3D56462880']/div/h4")
for(WebElement element : reports){
if(element.getText().contains("report1"){
return reports.indexOf(element) + 1;
}
}
Otherwise you will have to parse the xpath by yourself to extract the value (see LG3527118's answer for this).
I have a table that consists of multiple rows that each contain 5 cells, like this:
<tr>
<td></td>
<td>123456</td>
<td>statusText</td>
<td><a>linkText</a></td>
<td>editButton</td>
</tr>
The 123456 could be any string of random letters and numbers. I want to be able to select a link based on the contents of the second cell in the table. I've been trying something like this:
//tr[contains(td, '123456')]
to get me to the cell, but it either returns every row or nothing, depending on how I tweak the xpath.
I've been trying something like this:
//tr[contains(td, '123456')]
to get me to the cell, but it either
returns every row or nothing,
depending on how I tweak the xpath
You get what you asked for. The above XPath expression selects any tr element (row) in the document that has (at least one) td child whose string value contains '123456'.
But you want:
//tr/td[text() = '123456']
this selects every td element (cell) in the document, that has a text node child, whose string value is '123456'.
There can be different variations, depending on whether a td may have more than one text nodes and on whether the white space in a text node should be normalized, but the question doesn't provide any information if any of these apply in this particular case.
I'd research something like //tr[string(td[2]) = '123456']. If this does not work, I'd look up XPath axes.