66

I know how to get a list of DIVs of the same css class e.g

<div class="class1">1</div>
<div class="class1">2</div>

using xpath //div[@class='class1']

But how if a div have multiple classes, e.g

<div class="class1 class2">1</div>

What will the xpath like then?

seasong
  • 763
  • 1
  • 6
  • 7

5 Answers5

140

The expression you're looking for is:

//div[contains(@class, 'class1') and contains(@class, 'class2')]

I highly suggest XPath visualizer, which can help you debug xpath expressions easily. It can be found here:

http://xpathvisualizer.codeplex.com/

Ioannis Karadimas
  • 7,746
  • 3
  • 35
  • 45
  • 5
    Minor problem with this solution is that it'll potentially break if a possible class name is a substring of another. For example, if you also have 'class11', it'll erroneously match this, as it contains 'class1'. This is very easy to avoid though, just make sure class names don't contain each other. – Flynn1179 Aug 01 '12 at 08:36
  • Agreed, but given what 's being discussed here involves scanning an attribute's string value, in XPath speak, I 'm not sure if it can be avoided. – Ioannis Karadimas Aug 01 '12 at 08:39
  • 6
    Well, if it was really necessary you could do `contains(concat(' ', @class, ' '), ' class1 ')` etc., but as I said, it's very easy to avoid the need for that. – Flynn1179 Aug 01 '12 at 10:48
  • 1
    This did it for me! Took me forever to solve this! – Sunwoo Yang Oct 19 '21 at 16:30
7

According to this answer, which explains why it is important to make sure substrings of the class name that one is looking for are not included, the correct answer should be:

//div[contains(concat(' ', normalize-space(@class), ' '), ' class1 ')
    and contains(concat(' ', normalize-space(@class), ' '), ' class2 ')]
Vic Seedoubleyew
  • 9,888
  • 6
  • 55
  • 76
2

There's a useful python package called cssselect.

from cssselect import CSSSelector CSSSelector('div.gallery').path

Generates a usable XPath:

descendant-or-self::div[@class and contains(concat(' ', normalize-space(@class), ' '), ' gallery ')]

It's very similar to Flynn1179's answer.

Let Me Tink About It
  • 15,156
  • 21
  • 98
  • 207
steveayre
  • 1,075
  • 11
  • 8
0

i think this the expression you're looking for is

//div[starts-with(@class, "class1")]/text()
0

You could also do:

//div[contains-token(@class, 'class_one') and contains-token(@class, 'class_two')]
HelpNeeder
  • 6,383
  • 24
  • 91
  • 155