I'm trying to locate a specific button on a complex web page where a single attribute isn't unique enough. For example, there are multiple buttons with the same class name, but I only want the one that also contains specific text and has a certain "data-type" attribute. Is it possible to combine multiple and or or operators within a single XPath expression in Python? Also, should I be worried about the performance or readability of these long, multi-condition XPaths?
3 answers
Combining multiple conditions in XPath is one of the most powerful ways to create "bulletproof" locators in Selenium. You can use the and and or operators directly inside the square brackets. For your specific case, the syntax would look like this: driver.find_element(By.XPATH, "//button[@class='btn-primary' and text()='Submit' and @data-type='save-progress']").
This ensures that the element must satisfy all three criteria to be selected. If you want to find an element that could have one of two different classes, you would use or: //input[@type='submit' or @type='button']. Using multiple conditions is generally better than using "Absolute XPath" because it makes your scripts more resilient to layout changes, provided the attributes themselves remain stable.
What if one of the attributes is dynamic, like a class name that changes from btn-active to btn-inactive? Can I still use multiple conditions if I only know part of the string?
For readability, if your XPath gets too long, I recommend breaking it up or using variables in Python to build the string. It makes debugging much easier when a locator fails.
I agree with Brenda. Another tip is to use the normalize-space() function if you are matching text that might have extra whitespace or tabs, which is common in nested HTML. Combining normalize-space(text()) with other attribute checks makes your multi-condition XPath even more robust.
David, absolutely! You can combine the contains() function with multiple conditions. For example: //div[contains(@class, 'btn-') and @id='unique-id']. This is incredibly useful for modern front-end frameworks where class names are often generated dynamically or appended with state-specific suffixes. Just be careful not to make the conditions too broad, or you might accidentally pick up multiple elements.