-1
<span class="cname">
    <em class="multiple">2017</em> Ford 
</span>
<span class="cname">
     Toyota
</span>

I want to get only "FORD" and TOYOTA in span.

test.find_element_by_class_name('cname').text

return "2017 FORD" and "TOYOTA". So how can i get particular text of span?

3 Answers3

3

Pure XPath solution:

//span[@class='cname']//text()[not(parent::em[@class='multiple'])]

And if you alse want to filter white-space-only text-nodes():

//span[@class='cname']//text()[not(parent::em[@class='multiple']) and not(normalize-space()='')]

Both return text-nodes not an element. So Selenium will probably fail. Take a look here: https://sqa.stackexchange.com/a/33097 on how to get a text-node(). Otherwise use this answer: https://stackoverflow.com/a/67518169/3710053

EDIT:

Another way to go is this XPath:

//span[@class='cname']

And then use this code python-example to get only direct text()-nodes.

EDIT 2

all_text = driver.find_element_by_xpath("//span[@class='cname']").text
child_text = driver.find_element_by_xpath("//span[@class='cname']/em[@class='multiple']").text

parent_text = all_text.replace(child_text, '')
Siebe Jongebloed
  • 3,906
  • 2
  • 14
  • 19
1

You can get the parent element text without the child element text as following:

total_text = driver.find_element_by_xpath(parent_div_element_xpath).text
child_text = driver.find_element_by_xpath(child_div_element_xpath).text

parent_only_text = total_text.replace(child_text, '')

So in your specific case try the following:

total_text = driver.find_element_by_xpath("//span[@class='cname']").text
child_text = driver.find_element_by_xpath(//*[@class='multiple']).text

parent_only_text = total_text.replace(child_text, '')

Or to be more precise

father = driver.find_element_by_xpath("//span[@class='cname']")
total_text  = father.text
child_text = father.find_element_by_xpath(".//*[@class='multiple']").text
parent_only_text = total_text.replace(child_text, '')

In a general case you can define and use the following method:

def get_text_excluding_children(driver, element):
    return driver.execute_script("""
    return jQuery(arguments[0]).contents().filter(function() {
        return this.nodeType == Node.TEXT_NODE;
    }).text();
    """, element)

The element argument passed here is the webelement returned by driver.find_element In your particular case you can find the element with:

element = driver.find_element_by_xpath("//span[@class='cname']")

and then pass it to get_text_excluding_children and it will return you the required text

Prophet
  • 32,350
  • 22
  • 54
  • 79
  • when there is a span without "multiple" class, code can not find child text and give error. how can i deal with it ? – Furkan DURMUŞ May 13 '21 at 11:31
  • Depends what that span has. In case it contains known text you can use "//span[contains(text(),'The known span text')]". xpath can be built exactly based on what information you have about the element(s), their parents and children – Prophet May 13 '21 at 11:38
  • i changed my code in question can you check it? – Furkan DURMUŞ May 13 '21 at 11:47
  • I updated the answer with universal method that retrieves the text from the parent element only using JavaScript – Prophet May 13 '21 at 12:10
1

If can have a check for integer, if it is a integer then don't print or do something else otherwise print them for //span[@class='cname'

Code :

cname_list = driver.find_elements(By.XPATH, "//span[@class='cname']")
for cname in cname_list:
    if cname.text.isdigit() == True:
        print("It is an integer")
    else:
        print(cname.text)

or

cname_list = driver.find_elements(By.XPATH, "//span[@class='cname']")
for cname in cname_list:
    if type(cname.text) is int:
        print("We don't like int for this use case") # if you don't want you can simply remove this line
    else:
        print(cname.text)
cruisepandey
  • 28,520
  • 6
  • 20
  • 38