1

I want to get Selenium with Chromedriver to recognize and import a line of html text into a Webelement variable.

Given this HTML:

<li id="password_rules">
   <strong>Password Rules</strong>
   <p>The database password rules conform with...:</p>
   <ul>
      <li>The password can not be the same as the user id.</li>
      <li>Password length must be between 8 and 25 characters.</li>
   </ul>
</li>

I want to grab the text in the last list element ("Password length must be between 8 and 25 characters.").

This is the java code I'm attempting to use:

WebElement passwordCriteria = driver.findElement(By.xpath("//*[@id = 'password_rules']//*[contains(text(), 'Password length must be between ')]"));
String lineText = passwordCriteria.getText();

When that Java executes, it returns an error saying the element cannot be found:

Exception in thread "main" org.openqa.selenium.InvalidSelectorException: invalid selector: Unable to locate an element with the xpath expression //[contains((text(), 'Password length must be between ')] because of the following error: SyntaxError: Failed to execute 'evaluate' on 'Document': The string '//[contains((text(), 'Password length must be between ')]' is not a valid XPath expression.

Any insight is much appreciated.

1
  • what error are you getting? Commented Apr 19, 2018 at 15:29

5 Answers 5

2

If you are grabbing a WebElement by it's id, then you don't need your extra specific xPath. id is supposed to be unique by convention. If you have other html elements with the same id, consider changing them to a class.

You should be able to grab the element like this:

WebElement passwordCriteria = driver.findElement(By.id("password_rules"));

If you're committed to finding the element by the id containing some text then the way you should do it is as follows:

WebElement passwordCriteria = driver.findElement(By.xpath("//*[contains((text(),'Password length must be between')]"));

Also, sometimes Selenium will complain if elements are not visible on the page when you try and reference them. Sometimes you need to wait, other times you need to perform some other action to make the text visible before referencing it, like hovering the mouse over a dropdown, etc.

For example Suppose the html you pasted here is an error message. This error message does not start out as being 'visible', but instead it is shown after the user types their password in incorrectly. In such an instance, Selenium won't let you reference the text from an element inside this div, since it's not currently view-able. Instead, what you would have to do is use Selenium to input the incorrect password in the fields, wait for the error message to be displayed, and then finally reference the WebElement, only after it is able to be seen.

EDIT: I misread OP's intention. The element that OP is trying to reference is NOT the element with the id, but rather a child of that element. Instead of rewriting my answer, I will point out that @Grasshopper answer has both css and xPath solutions.

Sign up to request clarification or add additional context in comments.

7 Comments

Thanks for the tips! The error I'm getting is: Exception in thread "main" org.openqa.selenium.InvalidSelectorException: invalid selector: Unable to locate an element with the xpath expression //*[contains((text(), 'Password length must be between ')] because of the following error: SyntaxError: Failed to execute 'evaluate' on 'Document': The string '//*[contains((text(), 'Password length must be between ')]' is not a valid XPath expression.
After trying your second suggestion above, I still get the same error. The page seems to load quickly and without issue, so I wouldn't think that is causing it.
@elroy-jetson OP is specifically loking for an li nested within the ul with id of "password_rules"
@ElroyJetson, I find it common to combine IDs along with other selectors. Imagine a page with multiple widgets with similar content--say, a "click here for more info" button. You need to use the ID to find the right widget and then dive deeper in that node to find text. You cannot use just ID as that's not what I'm clicking on, and I cannot just use the text because there are multiple links with the same text.
@MivaScott you know what. I'm sorry you all. I was at the work while answering this question and I missed important details. You are correct. I will refactor my answer!
|
1

You can try these locators if the concerned li is always the last child.

Css - "li[id='password_rules'] > ul > li:last-child"

xpath - "//li[@id='password_rules']/ul/li[last()]"

Comments

0

As per your question as the desired text is within Password Rules you have to induce WebDriverWait with ExpectedConditions as textToBePresentInElementLocated and then retrieve the text as follows :

new WebDriverWait(driver, 20).until(ExpectedConditions.textToBePresentInElementLocated(By.xpath("//li[@id='password_rules']//ul//li"), "Password length"));
String lineText = driver.findElement(By.xpath("//li[@id='password_rules']//ul//li[contains(.,'Password length')]")).getAttribute("innerHTML");

1 Comment

Thank you for the tip. Strangely, I get the following error, even though it is clear that the page has loaded: Exception in thread "main" org.openqa.selenium.TimeoutException: Expected condition failed: waiting for text ('Password length') to be present in element found by By.xpath: //li[@id='password_rules']//ul//li (tried for 20 second(s) with 500 milliseconds interval)
0

Thank you for the help everyone. I finally got it using the following:

new WebDriverWait(driver, 20).until(ExpectedConditions.textToBePresentInElementLocated(By.xpath("//li[@id = 'password_rules']"), "Password length must be between "));

2 Comments

Your question was to to get string text from HTML, I don't think you are getting the desired string in return.
I am. And I'm only concerned with getting the element at position 7 of the string array, which I create after the code above. I've tested it extensively and everything checks out.
0
WebElement passwordCriteria = driver.findElement(By.xpath("//li[@id = 'password_rules']/ul/li[2]);
String lineText = passwordCriteria.getText();

Your original example had // which should only be used at the beginning of an xpath.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.