Get xpath of div having multiple occurence in page - java

I am having a weird requirement. I am having a div class named "expandThisSection". And I have
<div id=​"requiredAccessoriesContentPlaceHolder" class=​"expandThisSection">​No required accessories are available for this product.​</div>​
<div id=​"requiredAccessoriesContentPlaceHolderMeasurement" class=​"expandThisSection">​ ​</div>​
<div id=​"optionalAccessoriesContentPlaceHolder" class=​"expandThisSection">​No optional accessories are available for this product.​</div>​
<div id=​"optionalAccessoriesContentPlaceHolderMeasurement" class=​"expandThisSection">​ ​</div>​
<div class=​"expandThisSection">​
<div style=​"width:​95%">​mytext</div>​
​<ul class=​"movePos">​…​</ul>​
<div><b>test</b>​</div>
​<div>​<b>abc</b> Get this text</div>
​<div id=​"vendLogo">​…​</div>
</div>
<div class="expandThisSection">
<table>...</table>
</div>
I want the content of the div that has style of 95% width.That is value I want is "mytext". But I am not able to find out xpath for the same.
Also I want xpath for finding the div content just above div with id=​"vendLogo". That is I want "Get this text".
NOTE: ITS ASSURED THAT THIS Bold tag WILL CONTAIN "abc"
How to do it? I am using selenium with Java
Got the first one. Not able to get second one.
Code:
List<WebElement> currentSkuDescription = driver.findElements(By.xpath("//div[#class='expandThisSection']/div"));
for(WebElement currentItem: currentSkuDescription) {
WebElement descriptionBlock = currentItem.findElement(By.xpath("//div[contains(#style, 'width:95%')]"));
description= descriptionBlock.getText();
}

Try dropping the #class='expandThisSection' because the div you want does not have that class attribute (it's parent does). Also, an exact match may be possible.
By.xpath("//div[#style='width:95%']
By.xpath("//div[contains(#style, 'width:95%')]
Either of those should work. If you want to make sure you are grabbing the right one, relative to the parent, use XPath axes...
//div[contains(#class, 'expandThisSection')]/child::div[contains(#style, 'width:95%')]

If you to search for the div by a specific text (in this case 'mytext') this you can use this xpath:
"//div[text()[contains(.,'mytext')]]/ancestor::div[#class='expandThisSection']"
Or if you want by the styling, the you can use this xpath:
"//div[#style='width:95%']/ancestor::div[#class='expandThisSection']"
Note that the second xpath will only work where the inline styling is done on the tag.
For the second query, try this xpath:
"//div[#id='vendLogo']/preceding-sibling::div[1]"
To get the specific text you require, you can do the following:
String text = driver.findElement(By.xpath("//div[#id='vendLogo']/preceding-sibling::div[1]")).getText();
text.replace(div.findElement(By.tagName("b")).getText(), "");

Related

Is it possible to find an element according to "p" tag but click "a" tag those are inside "div"?

I'd like to select some schemas on the screen for testing. But there are 8 different types schemas. And I couldn't select any schema without click on the schema's image. The element is displayed like this;
I created web element list and filtered it on value that i wanted to select schema name with java 8 stream than i can replace filtered element with (up div[class=' up template-list-board row']>div>P to div[class='template-list-board row']>div>a) , but it was not a good idea, i've experienced.
So , is there any way to click that "a" tag?
The html is displayed like this;
<div class="template-list-board row">
<div class="template-item-list">
<a class="item-image-click" ....> </a>
<p class="item-name">Meeting Agenda</p>
</div>
<div class="template-item-list">
...
</div>
I am not sure if I am understanding you correctly, but my solution would be something like this (with XPATH not css):
1) create a string for the locator:
String locator = "//div[class='template-list-board row']//p[text()='" + hereYourNameVariableAsString + "']/preceding-sibling::a";
2) Then create your element :
WebElement element = driver.findELement(by.xpath(locator));
Here the important thing is that you locator is dynamic you will have to provide you menu name or whatever that name represent such as "Meeting Agenda". Then it will find that menu and the previous sbling a for clicking. I hope I understand the problem correctly and this helps.

How to select md-autocomplete option with Selenium or Selenide?

Here is my Java attempt, but what should I fix?
SelenideElement product = $(By.id("product"));
Assertions.assertEquals("Search product", product.attr("md-floating-label"));
product.find(By.tagName("input")).val("test");
SelenideElement span = product.find(By.tagName("span")); //this one and last lines does not work as expected
product.sendKeys(Keys.ARROW_DOWN);
product.pressEnter();
And HTML code
<md-autocomplete id="product" flex="85" md-selected-item="ctrl.orderItem.product" md-search-text="ctrl.productQuery" md-items="item in ctrl.findProduct(ctrl.productQuery)" md-item-text="item.name" md-delay="300" md-floating-label="Search product">
<div layout="row" class="item" layout-align="start center">
<span md-highlight-text="ctrl.productQuery">{{item.name}}</span>
</div>
</md-autocomplete>
Instead of doing product.find(By.tagName("span")); I would try replacing it with an XPath as such:
SelenideElement span = product.find(By.xpath("//*[#id='product']/div/span"));
The issue was that span is not a direct child element of product (which is a md-autocomplete element), so you need a slightly more complex locator to find the span.
Maybe you dont need to do this thing Assertions.assertEquals("Search product", product.attr("md-floating-label"));
Just try find your span element like this SelenideElement span = $(By.xpath("//md-autocomplete[#id='product' and #md-floating-label= 'Search product"]//span'));
span.sendKeys(Keys.ARROW_DOWN);
span.pressEnter();
If element with label 'Search product' is not exist, you get a SoSuchElementException

How to get text inside depth div tag with Selenium

I am trying to get the text content of the items inside the following 2 div elements. It work using absolute path:
element = driver.findElement(By.xpath(".//*[#id='page-wrapper']/section/section/div/div[2]/section/div/div/div/div[45]"));
data = element.getText();
System.out.println(data);
The text that I am trying to get is:
45
Se
Selenium
I am trying to get text using relative XPath, but it always fails.
I am trying use this combination:
element = driver.findElement(By.xpath("//div[contains(#class,'elemBox noclaim noclaim-tt') and contains(text(),'45')]"));
or
element = driver.findElement(By.xpath("//div[contains(#class,'elemBox noclaim noclaim-tt')]/div[contains(text(),'45')]"));
but still failed.
I have HTML code like this:
<div class="elemBox noclaim noclaim-tt text-right m-t-lg animated-add pulse-add animated pulse animated-add-active pulse-add-active" >
<div class="" ng-show="(filterTool(elementName.name)) || (name === '')">
<div class="text-right ng-binding">45</div>
<div class="text-left ng-binding">
<span class="elemSym ng-binding">Se</span>
<br/>
Selenium
</div>
</div>
What should I do?
By using contains(text(),'45'), only the first direct-child text node will be evaluated. This is the reason you attempted XPath failed to find the div; because the text '45' is nested 2 levels from the outer div :
//div[contains(#class,'elemBox noclaim noclaim-tt') and contains(div/div/text(),'45')]
Or you might want to try using . instead of text to evaluate the entire texts within the outer div as opposed to evaluating only first direct-child text node :
//div[contains(#class,'elemBox noclaim noclaim-tt') and contains(.,'45')]
I think, you don't need to use contains word inside xpath.
textRightElement = driver.findElement(By.xpath("//div[#class='elemBox noclaim noclaim-tt']/div[#class='text-right']"));
or if class text-right is unique, just use
textRightElement = driver.findElement(By.xpath("//div[#class='text-right']"));
.... if you really need to find the element with it's value,
textRightElement = driver.findElement(By.xpath("//div[text()='45']"));

Select a non significant div tag using jsoup

I'm using jsoup for webscraping and have run into another issue. The div I need information from has no class, id or any special indication. It's buried in the page. Here it is:
<div class="column">
<div class="form-label">Rate: </div>
<div>11.082/11.167</div>
<div class="form-label padding-top">High/Low: </div>
<div>1005.0/0.0004</div>
</div>
I need to get the 1st set of numbers but I'm not sure how I can tell jsoup I want them specifically; does anyone have any advice?
Assuming doc is your Document object...
doc.select('.column > div:eq(1)');
should do the job, you basically select the parent div by class, then get all child div's, but filter the child div's so that the element at index 1 is returned (this is a zero based index, so index 1 is the 2nd element)
Personally, i'd switch to jQuery as it uses a far better selector engine, but each to their own...
Select all divs with class="column"
Loop through your list of selected elements. Select the first div inside your element that has the text Rate:
your Text is inside the 2. div
Sorry Code formatting isnt working o.0
public String getRage(Document document) {
for(Element e : document.getElementsByClass("column")) {
if(e.getElementsByTagName("div").get(0).ownText().equals("Rate: ")) {
return e.getElementsByTagName("div").get(1).ownText();
}
}
return null;
}

Parsing HTML with xpath or cssSelector?

How do I parse for just the text portions of these blocks of code? I am using Selenium client drivers in java.
<li id="NOT_PUT_PREF_STORE" style="">
<span id="STORE_AVAIL" class="BodyLBoldGrey StockStat">Out of stock</span> <span id="InYourLocal">in your local</span> <span id="storeRollover_2"><span id="STORE_CITY" class="BodyLBoldLtgry VIBSStore1">West Hills</span></span> store<span id="notSelectOptionSOI">.</span>
</li>
or
<li id="NOT_PUT_PREF_STORE" style="">
<span id="STORE_AVAIL" class="BodyLLtgry StockStat">Not carried</span> <span class="BodyLLtgry" id="InYourLocal">in your local</span> <span id="storeRollover_2"><span id="STORE_CITY" class="BodyLBoldLtgry VIBSStore1">West Hills</span></span> store<span id="notSelectOptionSOI">.</span>
</li>
or
<li id="NOT_PUT_PREF_STORE" style="">
<span id="STORE_AVAIL" class="BodyMBold StockStatGreen">In stock</span> <span id="InYourLocal">in your local</span> <span id="storeRollover_2"><span id="STORE_CITY" class="BodyLBoldLtgry VIBSStore1">West Hills</span></span> store<span id="notSelectOptionSOI">.</span>
</li>
I am trying to parse for the text portion in each of these variations in the webelement (ie: Not carried, In stock, Out of stock). I am a very new user to selenium and html parsing so this is really hard for me to get functional.
I was thinking that it would be something like
WebElement driver = new FirefoxDriver(profile);
driver.get(Url);
System.out.println(driver.getElement(By.id("STORE_AVAIL").getText());
Not sure how I would do it with cssSelector but people tell me that is faster.
Would this work?
driver.getElement(By.xpath("//li[#id='NOT_PUT_PREF_STORE']./span[#id='STORE_AVAIL']").getText()
When I try to find elements on the page I always build my locators by:
id = driver.getElement(By.id("STORE_AVAIL").getText());
css selector = driver.getElement(By.css("span#STORE_AVAIL").getText());
xpath = driver.getElement(By.xpath("//span[#id='STORE_AVAIL']").getText());
The id seems to be the fastest and easiest, both for webdriver and for me. id should be unique on the page.
CSS take a little more investigative work on my part, but webdriver handles it just fine.
Lastly, xpath is sometimes unavoidable (unless you buy the devs a beer and ask nicely to change to application so you can locate it faster - after all, you are testing for them anyway). Locating by xpath with IE is terribly slow and writing complex xpaths is a drag.
Xpath is also fragile, one small change to the dom can render your xpath unusable. Then you get to debug/rewrite your xpath (it is as fun as it sounds).
My suggestion is to use Firebug and FirePath addons for Firefox to help you craft your locators.
When you 'View Page Source' it will only show the original HTML source. It will not show changes made by AJAX calls, which looks like how the Walmart page is updating that section/element. This question provides a better explanation.
Assuming you are using Firefox (based on the driver you are using), you can go to the page and click Ctrl+Shift+I to bring up the Inspector tool. Select the element you are interested in. Then click the [HTML] button (in the Inspector menu) to view the current source.
Note that when you are getting the element using selenium webdriver, it will be getting the current value rather than the original value seen in the page source. So you do not have to worry about what you see in the page source.
I am tried with the following html code snipet
<li id="NOT_PUT_PREF_STORE" style="">
<span id="STORE_AVAIL" class="BodyLBoldGrey StockStat">Out of stock</span> <span id="InYourLocal">in your local</span> <span id="storeRollover_2"><span id="STORE_CITY" class="BodyLBoldLtgry VIBSStore1">West Hills</span></span> store<span id="notSelectOptionSOI">.</span>
</li>
I am using the following code to solve it. I get the tree of span elements using XPath and parse through each of it to get the text of the elements.
driver.navigate().to("file:///C:/Users/abc/Desktop/test.html");
List<WebElement> spanEle = driver.findElements(By.xpath("//li/span"));
for (int i = 0; i < spanEle.size(); i++) {
System.out.println(spanEle.get(i).getText());

Categories

Resources