Should the values of html elements with "display: none;" be returned by HtmlUnit - htmlunit

Given the following table, where every other row has it display value set to none:
<table>
<thead>
<tr><th>Expand</th><th>Some Id</th><th>Some Attribute</th><th>Another Attribute</th></tr>
</thead>
<tbody>
<tr><td>V</td><td>101</td><td>fast</td><td>1/1/1</td></tr>
<tr style="display: none"><td>1</td><td>0</td><td>1</td><td>A Hidden Value 1011</td></tr>
<tr><td>V</td><td>102</td><td>fast</td><td>2/2/2</td></tr>
<tr style="display: none"><td>1</td><td>0</td><td>2</td><td>A Hidden Value 1022</td></tr>
<tr><td>V</td><td>103</td><td>fast</td><td>3/3/3</td></tr>
<tr style="display: none"><td>1</td><td>0</td><td>3</td><td>A Hidden Value 1033</td></tr>
<tr><td>V</td><td>104</td><td>fast</td><td>4/4/4</td></tr>
<tr style="display: none"><td>1</td><td>0</td><td>4</td><td>A Hidden Value 1044</td></tr>
</tbody>
</table>
When I use HtmlUnit with an xPath expression to retrieve all the rows:
HtmlPage page = webClient.getPage("http://localhost:4567/Home.html");
List<HtmlTableRow> rowsByXPath = page.getByXPath("//tbody/tr");
all of the rows are retrieved, however even though the rows that have their display value set to none are retrieved, the value of their cells are not available when using asText.
As an example if I attempt to print the values for the final cell in each row using the following code:
cells.forEach(cell -> System.err.print("[" + cell.asText() + "]"));
The output is:
[1/1/1][][2/2/2][][3/3/3][][4/4/4][]
However when I use asXml:
cells.forEach(cell -> System.err.print("[" + cell.asXml() + "]"));
The following output is obtained (modified for readability):
[<td>1/1/1</td>][<td>A Hidden Value 1011</td>]
[<td>2/2/2</td>][<td>A Hidden Value 1022</td>]
[<td>3/3/3</td>][<td>A Hidden Value 1033</td>]
[<td>4/4/4</td>][<td>A Hidden Value 1044</td>]
Is this the expected behaviour?
I expected the output from using the asText on the cells to be:
[1/1/1][A Hidden Value 1011][2/2/2][A Hidden Value 1022][3/3/3][A Hidden Value 1033][4/4/4][A Hidden Value 1044]

XPath is an XML feature and works without any HTML semantics. This implies that style attributes are not hiding any element from the tree.
Or the other way around - it is correct that you find the (hidden) elements when using XPath.
On the other hand methods like DomNode.asText() are working on the DOM tree in an HTML context - asText will return an empty string if the node is not visible.

Related

Cypress - click hyperlink on row based on value of two cells

Trying to get a Cypress script to click a hyperlink based on two values - the text of the hyperlink in column 1 and the value of the cell in the second column:
<tbody>
<tr>
<td>Anything</td>
<td>Casualty</td>
</tr>
<tr>
<td>Declined Prospect</td>
<td>Casualty</td>
</tr>
<tr>
<td>Declined Prospect</td>
<td>Package</td>
</tr>
<tr>
<td>Declined Prospect</td>
<td>Casualty</td>
</tr>
<tr>
<td>Irrelevant</td>
<td>Package</td>
</tr>
</tbody>
cy.get('a').contains('Declined Prospect').click()
fails because there's more than one hyperlink with that value. The id is not useful because it's dynamic.
In the example above, I want to click Declined Prospect when the second column is Casualty (but the order of the rows may vary and values in the first and second column are repeated - but only once for the combination).
Any thoughts?
The trick is to target <td>Casualty</td> then click the preceding <td><a>.
There are quite a few ways to get to sibling elements, the simplest in this case is prev().
cy.contains('td', 'Casualty') // target the 'marker' element
.prev() // move to the previous sibling
.click()
Approach from row and move inwards
To target a row with a specific combination of text in some of it's cells, just concatenate the text and use contains().
cy.contains('tr', 'Declined Prospect Casualty') // target unique text within children
This even works when there are other cells with text that's not relevent to the search, e.g
<tr>
<td>Declined Prospect</td>
<td>Casualty</td>
<td>Irrelevent text here</td>
</tr>
Then you can walk down the HTML tree,
cy.contains('tr', 'Declined Prospect Casualty') // target unique text within children
.find('td a') // descendant of previous subject
.click()
I think this can be useful: https://github.com/cypress-io/cypress-xpath
You can create selectors in xpath instead of css and in xpath you can search tree by text. e.g:
cy.xpath("//text() = 'Declined Prospect'")
==================================Edited====================
You can merge couples of xpatch selectors: it will looks like this //tr[td='Casualty']/td/a
Playgroud

How to get td text value of nested table by XPath

I have this table inside another table inside another table and so on. And then I want to get the text value of the td element with a specific class.
<tr>
<td width="5%"></td>
<td class="wintxt">The XML ....<br/><br/>Number: xyz</td>
</tr>
I need to get the text content "The XML ....Number: xyz"
I tried using:
List<?> submissionString = resultOfsubmissionPage.getByXPath("//tr[#class=\"wintxt\"]/td/text()");
...and many other variations but I always get a zero element List. Anyone has a clue?
There is mistakes with your provided xpath you are searching text() in that row means tr which has class attribute but as your provided HTML only one td has class attribute. So try as below :-
List<?> submissionString = resultOfsubmissionPage.getByXPath("//tr/td[#class='wintxt']/text()");
Hope it helps..:)

XPath of the edit button is //*[#id="edit_1088"]

My query is I need to click on the first edit link on the table. The table has 7 columns and rows will be incremented dynamically.
HTML Code for first row:
<tr role="row" class="odd">
<td>
<form method="GET" target="_blank" action>...</form>
<td> ALLOCATION CHANGE</td>
<td class="right"></td>
<td> SATTER, KRAIG</td>
<td> CAFEMANAGER1</td>
<td class="sorting_1">03/08/2016 17:00</td>
<td class="edit_icon" id="edit_1088" onclick="on EditClick(1088)">
<span class="view_icon" style="margin-left: 40%;"></span>
</td>
</tr>
Note: the ID of the edit button keep on changing as the row increments.
Mycode in cucumber -ruby -capybara
And /^I click on the Expresso image$/ do
find(:xpath, '//*[#id="l1row"]/span').click
find('tr:odd > td:edit_icon [id="edit_"] match: first').click
sleep 10
end
Error Message: invalid selector: An invalid or illegal selector was specified
Update based on the posted HTML -
Note: Your first <td> isn't closed, I'm assuming thats just an error when you were adding the HTML to the question.
So from the HTML posted you don't actually have an edit link you just have a td you need to click on - the one in the first row with an id beginning with "edit_" so
find('tr:first-child > td[id^="edit_"]').click
The attempt you posted in your question won't work because there is no such CSS selector as odd or edit_icon and find needs valid CSS selectors (or XPath if you specify XPath or set it as your default)
Previous Answer Based on the wording of the question:
If this is a table then you can do what you want with CSS and not worry about XPath.
find('tr:first-child > td:last-child [id^="edit_"]')
will find the element whose id starts with "edit_" in the last td in the first row. If your rows and columns are not actually a table you'll need to provide some example HTML of what you're talking about.

Complicated xpath for a rookie

I have this piece of html:
<tr>
<td class="has-checkbox">
<input id="abc" class=... value=...>
</td>
<td class="has-label">
<label for="abc">Name1234</label>
</td>
<tr>
I need to make an xpath that gets me the input element, based on whats in the label, in this case Name1234.
In other words, for this case, I need an xpath to the input element, and the path must contain Name1234, as its variable.
Anyone who can help me out here?
//input[#id = //label[. = 'Name1234']/#for] selects input element(s) with an id attribute value equal to the for attribute value of label elements where the contents is Name1234.
You can use /.. , this syntax use to move back to parent node. In your case:
//label[.='Name1234']/../../td/input
You must move back 2 times because input tag is the child of another td tag.
Here are others introduction and example about you should read.
Here is a solution using the Axes parent and preceding-sibling:
//label[.='Name1234']/parent::td/preceding-sibling::td/input
It's not so complicated as you think:
xpath=//tr[//label[.="Name1234"]]//input
in other words, you are looking for the 'tr' which contains 'label' with text "Name1234". If the condition is true, you are getting the 'input' element

How do I get the value inside a <td> tag with xpath/htmlwebunit

I am trying to create a Java Application that retrieves information from a webpage. This is part of the code I am trying to access the value in the 1st td tag in the 2nd tr tag:
<TABLE CLASS="datadisplaytable" width = "100%">
<TR>
<TD CLASS="dddead"> </TD>
<TH CLASS="ddheader" scope="col" ><SPAN class="fieldlabeltext">Capacity</SPAN></TH>
<TH CLASS="ddheader" scope="col" ><SPAN class="fieldlabeltext">Actual</SPAN></TH>
<TH CLASS="ddheader" scope="col" ><SPAN class="fieldlabeltext">Remaining</SPAN></TH>
</TR>
<TR>
<TH CLASS="ddlabel" scope="row" ><SPAN class="fieldlabeltext">Seats</SPAN></TH>
**<TD CLASS="dddefault">46</TD>**
<TD CLASS="dddefault">46</TD>
<TD CLASS="dddefault">0</TD>
</TR>
This is what i have right now but this only returns the class of the td tag and not the value inside it:
List<?> table = page.getByXPath("//table[#class='datadisplaytable'][1]//tr[2]/td");
How would I go about getting the value of the td tag and not its properties?
edit: The code above returns this:
HtmlTableDataCell[<td class="dddefault">]
I am trying to create a Java Application that retrieves information from a webpage. This is part of the code I am trying to access the value in the 1st td tag in the 2nd tr tag:
Assuming that the document is as shown in the question (TABLE is the top element),
Use:
/TABLE/TR[2]/TD[1]/text()
This selects any text-node child of the first TD child of the second TR child of the top element TABLE.
In case the table is buried in the XML document, but can be uniquely identified by its CLASS attribute, use:
//TABLE[#CLASS='datadisplaytable']/TR[2]/TD[1]/text()
This selects any text-node child of the first TD child of the second TR child of any (we know thre is only one such) element TABLE in the XML document, such that the string value of its CLASS attribute is the string 'datadisplaytable'.
Finally, if even worse, there could be many TABLE elements whose CLASS attribute's value is 'datadisplaytable', and we want to select in the first such table, use:
(//TABLE[#CLASS='datadisplaytable'])[1]/TR[2]/TD[1]/text()
for getting the text content from an element there is an xpath function called "text()" which you can use.
Element containing text 't' exactly //*[.='t']
Element <E> containing text 't' //*[.='t']
<a> containing text 't' //a[contains(text(),'t')]
<a> with target link 'url' //a[#href='url']
Link URL labeled with text 't' exactly //a[.='t']/#href
If you are also using JwebUnit, there is a method "getElementTextByXPath" which can also be used to get the text.
net.sourceforge.jwebunit.junit.WebTestCase
getElementTextByXPath
public String getElementTextByXPath(String xpath)
Deprecated.
Get text of the given element.
Parameters:
xpath - xpath of the element.
for (int i = 1; i != 6; i++) {
String result = getElementTextByXPath("//td["+i+"][text()]");
System.out.println("The Content of TD is " +result);
}

Resources