Home > Blockchain >  Why XPath negation not working correctly when preceding the selection?
Why XPath negation not working correctly when preceding the selection?

Time:06-12

I can select a row based on a specific value and then fetch the desired column. Example: Click the Action Button for the student of type Bachelor:

//td[text()='Bachelor']/following-sibling::td[@class='action']

Correctly selects: enter image description here

HTML
enter image description here


I want to select based on negation: Click the Action Button for all students that are NOT of type Master

//td[not(text()='Master')]/following-sibling::td[@class='action'] 

But wrongly selects both (only Student's row should be selected): enter image description here

Using chrome XPath resolver (f12) for testing for later using the XPath query in Selenium.

Couldn't find any similar example or deep explanation with the research I did.

CodePudding user response:

The reason

//td[not(text()='Master')]/following-sibling::td[@class='action']

"selects [td elements in] Master row too," as you observe, is that

//td[not(text()='Master')]

selects all td elements that do not have a text() node child with a string value of 'Master'. Significantly, that includes all of the predecessor siblings to the 'Master' td that you're trying to exclude, and the problem is that they too have following td siblings with . So, you're not really excluding the row you want to exclude.

To select only the action td elements immediately preceded by a td whose string value is not 'Master', use this XPath:

//td[@class='action'][preceding-sibling::*[1][self::td][not(.='Master')]]

Or, you can simply test the row rather than the immediate sibling:

//tr[not(td='Master')]/td[@class='action']

Note that the former XPath will be sensitive to td positioning while the latter XPath will not.

See also

CodePudding user response:

Just use:

//td[5][not(. = 'Master])]/following-sibling::td[@class = 'action']

or simply:

//tr[not(td[5] = 'Master')]/td[@class = 'action']

I think it is dangerous to use just //tr[not(td = 'Master')] because there could easily be someone with family name 'Master'

  • Related