How to merge 2 xpath in one - java

Html
<li class="wdappchrome-ai" data-automation-id="searchInputAutoCompleteResult" tabindex="-2" aria-posinset="1" aria-setsize="3">
<span data-automation-id="searchInputAutoCompleteResultFullText">
<span style="font-weight:500">
<span data-automation-id="searchInputAutoCompleteResultToken" style="font-weight:400">mike</span>
<span data-automation-id="searchInputAutoCompleteResultToken" style="font-weight:400">diana</span>
</span>
</span>
</li>
I am getting user full name divided into spans so I want to build xpath which returns me combine text of both/multiple span from single list.
For now I am using 2 or more xpath based on name of user divided into span.
I use : //li[.//span[text()='mike']] //li[.//span[text()='diana']]
Then I do gettext() for above both xpath and merge using java grammatically. So I am looking for solution which give me full text of all span within particular li tag from above.

Try below XPath to match element by one of the spans:
//li[.//span='diana' or .//span='mike']
or by both spans:
//li[.//span='diana' and .//span='mike']

To get the full text of all span within particular li tag in a single line you can use the following code block :
ArrayList<String> nameList = new ArrayList<String>();
List<WebElement> firstName_lastname = driver.findElements(By.xpath("//li[#class='wdappchrome-ai']//span[#data-automation-id='searchInputAutoCompleteResultToken']"));
for (WebElement fN_lN:firstName_lastname)
nameList.add(fN_lN.getAttribute("innerHTML"));
System.out.println(nameList);

Related

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']"));

Get xpath of div having multiple occurence in page

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(), "");

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;
}

JSoup - how to grab a href (url/link) immediately preceding a <span class = *>?

Given the following :
<li class="med grey mkp2">
<span class="price bld">$28.15</span> new <span class="grey">(14 offers)</span> </li>
I need to grab the href, which sounds simple, right? However the only way I can find the correct list item to grab from is to get the <span class="price bld">, so the href I need preceeds it. It's similar to Extracting href from a class within other div/id classes with jsoup, but in reverse.
There can be many list items with the css class "med grey mkp2", but I only need content from the ones with the noted span with class="price bld".
How can I achieve this?
You can only select the target element (the <a>), not the child element (the <span>), otherwise it would only return <span> elements. In this particular case, you can use the :has() selector to check if the target element has the desired child element.
Elements elements = document.select("a:has(.price.bld)");
See also:
Jsoup selector cookbook
:has(seletor): find elements that contain elements matching the selector; e.g. div:has(p)

Categories

Resources