Today I was writing some Selenium unit tests for our PHPUnit test suite and needed to check if a certain navigational tab was active. Situation in HTML:
<span class="navbutton active"> <input type="submit" name="someId" value="Button 1"/> <input type="submit" name="someOtherId" value="Button 2"/> </span>
I needed to check if Button 1 was active. The problem was that with simple xpath constructs like //span[@class='active']/input do not work since the class may have multiple values.
The rescue was the contains function: //span[contains(@class, 'active')]/input[@id='someId'] as parameter to assertElementPresent().
This only does work for simple cases, though: A class like inactive would also match here. The following sections provide real solutions, inspired by Jakob Westhoffs blog entry:
In XPath 2.0, you can split an attribute into tokens and search through them:
//*[count(index-of(tokenize(@class, '\s+' ), '$classname')) = 1]
Many libaries (and thus PHP itself, which utilizes libxml2) only offer XPath 1.0, which means that the tokenize() is not available.
To circumvent that issue, we just search for space + classname + space, and add the spaces around the class attribute so that classes at the beginning and end are caught, too.
//*[contains(concat(' ', normalize-space(@class), ' '), ' $classname ')]