How get AJAX elements which XPATH is varying dynamically - ajax

In my application one AJAX filed which is displaying some values
When I tried to find out their XPATH it is varying dynamically
for example :
First time when I tried to find out the path it is giving it as .//*[#id='ix-rt-13']. When I refresh the page it is giving it as .//*[#id='ix-rt-6'].
Actually it is displaying 2 values one with id .//*[#id='ix-rt-13'] and second one with .//*[#id='ix-rt-14']. And when I refresh the page it is giving XPath values as .//*[#id='ix-rt-6'] and .//*[#id='ix-rt-7'].
I want to retrieve the second element text. How to do that ?
<li class="ui-menu-item" role="presentation">
<a id="'ix-rt-15" class="ui-corner-all ui-state-focus" tabindex="-1">Being Powerful</a>
</li>

If I understand the question correctly, you can try this XPath :
(//*[starts-with(#id,'ix-rt-')])[2]
Above XPath will search for all elements with id attribute value starts with 'ix-rt-', then return the 2nd result.

If link text does not change, you shouldn't use xpath rather use link text:
driver.findElement(By.linkText("Being Powerful")).click();
However if you bend upon using xpath you may try following:
driver.findElement(By.xpath("//a[contains(#id,'ix-rt-')]")).click();
But this would select the 1st element containing 'ix-rt-' in its id. So it may not work as desired if there are more than 1 such elements. In that case, if you know the index of element on page, you may use following:
driver.findElement(By.xpath("(//a[contains(#id,'ix-rt-')])[2]")).click();

Related

Why does IMPORTXML with XPATH return unexpected blank row in addition to expected result?

I'm importing into Google Sheets with IMPORTXML with the following XPATH:
=IMPORTXML(A2;"//*[#id='mw-content-text']/div/table[1]/tbody/tr[4]/td[1]/ul/li")
A2 containing the URL (https://stt.wiki/wiki/20th_Century_Pistol).
From the website I want to import the list entries in the "Basic" column and "Crafted From" row of the table.
There are only two list entries in this section of the table:
"x1 Basic Security Codes" and
"x4 Basic Casing"
Therefore, I expected to get only those two list entries as rows in my sheet.
Instead, I got an additional blank row above those two entries. When I change "td[1]" to "td[3]" in the XPATH query however, there are no extra blanks.
I don't understand where the additional blank row is coming from and how I can avoid it.
Google Sheet with desired and actual result
When I saw the HTML of the URL, there are 2 li tags in the ul tag. So I think that your xpath is correct. But from your issue, I was worry that the sup tag might affect to this situation. But I'm not sure whether this is the direct reason. So I would like to propose to add the attribute of li for your xpath as follows.
Modified xpath:
When your xpath is modified, please modify as follows.
From:
//*[#id='mw-content-text']/div/table[1]/tbody/tr[4]/td[1]/ul/li
To:
//*[#id='mw-content-text']/div/table[1]/tbody/tr[4]/td[1]/ul/li[#style='white-space:nowrap']
By adding [#style='white-space:nowrap'], the value of li with style='white-space:nowrap' is retrieved.
Result:
The formula is =IMPORTXML(A1;"//*[#id='mw-content-text']/div/table[1]/tbody/tr[4]/td[1]/ul/li[#style='white-space:nowrap']"). Please put the URL to the cell "A1".
Note:
Also, you can use the xpath of //*[#id='mw-content-text']/div/table[1]/tbody/tr[4]/td[1]/ul/li[position()>1].
To complete the very neat #Tanaike's answer, another expression :
=IMPORTXML(A2;"//th[contains(.,'Crafted')]/following::td[1]//li[contains(#style,'white')]")
If a blank line is added it's because GoogleSheets parses an additional blank li element containing a #style attribute.

How to assert multiple elements values in a form using Xpath Assertion in Jmeter?

I'm trying to assert some text-fields values in a form
and I can only assert on a single one through Xpath Assertion post-processor.
How can I assert the whole form fields within a single http sampler ?
I tried to assert multiple text-fields in a single "Xpath Assertion" component, but it didn't work.
Here a couple of fields I'm trying to assert in a single Xpath Assertion component:
//*[#class='ProjectNameInput']/#value='Dummy_Project'
//*[#class='Desc2']/#value='Dummy_Desc'[enter image description here][1]
I would take a simple approach using xpath. As you are expecting all the fields in a form you can write the xpath to get the form element if it have all the required value elements.
For example in the SO question when you click on Add Comment (right below your question). That comment text area,Add Comment button and help button are part of the form. I want to verify if all those elements are present with the given text. Then I can use below xpath.
So in your case you can do something like this.
//form[.//xpath_of_first_element and .//xpath_of_2nd_element and .//xpath_of_3rd_element]
Make sure you specify the .// in the [] otherwise it will check the entire page rather under the form.
Going forward consider adding at least partial or better full page DOM to your question, the chance of getting a comprehensive answer will be much higher.
In the meantime, given you have following HTML form
<form>
<input type="text" class="ProjectNameInput" value="Dummy_Project"/>
<input type="text" class="Desc2" value="Dummy_Desc"/>
</form>
you can use the following XPath expression in order to match 2 nested <input> tags:
//form[./input[#class='ProjectNameInput']/#value='Dummy_Project' and ./input[#class='Desc2']/#value='Dummy_Desc']
Demo:
More information: Using the XPath Extractor in JMeter

Retrieve value from within a div tag in xpath

I am trying to retrieve the value in the data-appid field, I have tried using following-sibling but its not really a sibling per se. Not sure how to go about retrieving this. Any pointers will really be great.
<div class="section app" data-appid="532054761" data-updateid="10184169">
The sibling axis applies to elements, not attributes.
You can reference data-appid simply as an attribute of the div element. For example,
//div/#data-appid
will select 532054761
If you need to be more specific about the particular div element for which you want its data-appid, you can use a predicate to select a particular div element. For example:
//div[#data-updateid='10184169']/#data-appid
You need to use getAttribute() method
Try the following code
String dataAppId = driver.findElement(By.xpath("//div[#class='section app']")).getAttribute("data-appid");
System.out.println(dataAppId);

WebDriver select element that has ::before

I have 2 elements that have the same attributes but shown one at a time on the page (When one is shown, the other disappears).The only difference between the two is that the element which is displayed will have the '::before' selector. Is it possible to use an xpath or css selector to retrieve the element based on its id and whether or not it has ::before
I bet also to try with the javascript solution above.
Since ::after & ::before are a pseudo element which allows you to insert content onto a page from CSS (without it needing to be in the HTML). While the end result is not actually in the DOM, it appears on the page as if it is - you see it but can't really locate it with xpath for example (https://css-tricks.com/almanac/selectors/a/after-and-before/).
I can also suggest if possible to have different IDs or if they in different place in the DOM make more complex xpath using above/below elements and see if it is displayed.
String script = "return window.getComputedStyle(document.querySelector('.analyzer_search_inner.tooltipstered'),':after').getPropertyValue('content')";
Thread.sleep(3000);
JavascriptExecutor js = (JavascriptExecutor) driver;
String content = (String) js.executeScript(script);
System.out.println(content);

Xpath select following (number) sibling inside anchor help

Sorry in advance if I don't explain this clearly. I will try my best to clarify what I am trying to do. Without further ado...Suppose you have a series of numbers on a page (separated by only a space) where brackets indicate the current page you are on.
It looks like this on the page:
[1] 2 3
The HTML looks like this:
<tr>
<td>
[<a href='link1.php'>1</a>] <a href='link2.php'>2</a> <a href='link3.php'>3</a>
</td>
</tr>
I am simply trying to select the next page number based on the current. I imagine I need to use some form of following-sibling but all I have come up with is //tr/td/a/following-sibling::a[1], which is obviously incorrect. It selects 2 when on page 1 but not 3 when on page 2 as expected. I would have tried to use a[text()[contains(.,'[')]] to select the current-page but the brackets are outside the anchor as opposed to inside. Eek!?
It would be much appreciated if you could explain the thought process along with your solution instead of just pasting the answer. Looking forward to your help.
The next page after 2, will be found by:
//tr/td/a[.='2']/following-sibling::a[1]
First we select the current page based on its string content //tr/td/a[.='2'], and from there select the first following-sibling.
To do this without knowing the current page, we will instead select the a element following the "]".
//tr/td/text()[']'=normalize-space(.)]/following-sibling::a[1]
And in case that there is no current page, we will default to the first a element.
//tr/td/( text()[']'=normalize-space(.)]/following-sibling::a | a )[1]

Resources