python lxml - simply get/check class of HTML element
<p>I use <code>tree.xpath</code> to iterate over all interesting HTML elements but I need to be able to tell whether the current element is part of a certain CSS class or not.</p>

<pre><code>from lxml import html

mypage = """
&lt;div class="otherclass exampleclass"&gt;some&lt;/div&gt;
&lt;div class="otherclass"&gt;things&lt;/div&gt;
&lt;div class="exampleclass"&gt;are&lt;/div&gt;
&lt;div class="otherclass"&gt;better&lt;/div&gt;
&lt;div&gt;left&lt;/div&gt;"""

tree = html.fromstring(mypage)

for item in tree.xpath( "//div" ):
  print("testing")
  #if "exampleclass" in item.getListOfClasses():
  #  print("foo")
  #else:
  #  print("bar")
</code></pre>

<p>The overall structure should remain the same.</p>

<p>What is a fast way to check whether or not the current <code>div</code> has the <code>exampleclass</code> class or not?</p>

<p>In above example, <code>item</code> is of <a href="http://lxml.de/api/lxml.html.HtmlElement-class.html" rel="nofollow"><code>lxml.html.HtmlElement</code></a> class, which has the property <a href="http://lxml.de/api/lxml.html.HtmlMixin-class.html#classes" rel="nofollow"><code>classes</code></a> but I don't understand what this means:</p>

<blockquote>
  <p><strong>classes</strong><br>
  A set-like wrapper around the 'class' attribute.</p>
  
  <p><strong>Get Method:</strong><br>
  <code>unreachable.classes(self)</code> - A set-like wrapper around the 'class' attribute.</p>
  
  <p><strong>Set Method:</strong><br>
  <code>unreachable.classes(self, classes)</code></p>
</blockquote>

<p>It returns a <a href="http://lxml.de/api/lxml.html.Classes-class.html" rel="nofollow"><code>lxml.html.Classes</code></a> object, which has a <code>__iter__</code> method and it turns out <code>iter()</code> works. So I construct this code:</p>

<pre><code>for item in tree.xpath( "//div" )
  match = False
  for classname in iter(item.classes):
    if classname == "exampleclass":
      match = True
  if match:
    print("foo")
  else:
    print("bar")
</code></pre>

<p>But I'm hoping there is a more elegant method.</p>

<p>I tried searching for similar questions but all I found were various "how do I get all elements of 'classname'", however I need all <code>div</code>s in the loop, I just want to treat some of them differently.</p>

<p>There is no need for <em>iter</em>, <code>if "exampleclass" in item.classes:</code> does the exact same thing,  only more efficiently.  </p>

<pre><code>from lxml import html

mypage = """
&lt;div class="otherclass exampleclass"&gt;some&lt;/div&gt;
&lt;div class="otherclass"&gt;things&lt;/div&gt;
&lt;div class="exampleclass"&gt;are&lt;/div&gt;
&lt;div class="otherclass"&gt;better&lt;/div&gt;
&lt;div&gt;left&lt;/div&gt;"""

tree = html.fromstring(mypage)

for item in tree.xpath("//div"):
    if "exampleclass" in item.classes:
        print("foo")
</code></pre>

<p>The difference is calling <em>iter</em> on a set makes the lookup linear so definitely not an efficient way to search a set, not much difference here but in some cases there would be a monumental diffrence:</p>

<pre><code>In [1]: st = set(range(1000000))

In [2]: timeit 100000 in st
10000000 loops, best of 3: 51.4 ns per loop

In [3]: timeit 100000 in iter(st)
100 loops, best of 3: 1.82 ms per loop
</code></pre>

<p>You can also use <a href="https://pythonhosted.org/cssselect/" rel="nofollow">css selectors</a> using lxml:</p>

<pre><code>for item in tree.cssselect("div.exampleclass"):
    print("foo")
</code></pre>

<p>Depending on the case, you may also be able to use contains:</p>

<pre><code>for item in tree.xpath("//div[contains(@class, 'exampleclass')]"):
    print("foo")
</code></pre>

python class python-3.x lxml