19

Question

How do I remove class attributes from html using python and lxml?

Example

I have:

<p class="DumbClass">Lorem ipsum dolor sit amet, consectetur adipisicing elit</p>

I want:

<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit</p>

What I've tried so far

I've checked out lxml.html.clean.Cleaner however, it does not have a method to strip out class attributes. You can set safe_attrs_only=True however, this does not remove the class attribute.

Significant searching has turned up nothing workable. I think the fact that class is used in both html and python further muddies search results. Many of the results also seem to deal strictly with xml as well.

I'm open to other python modules that offer humane interfaces as well.

Thanks much.


Solution

Thanks to @Dan Roberts answer below, I came up with the following solution. Presented for folks arriving here in the future trying to solve the same problem.

import lxml.html

# Our html string we want to remove the class attribute from
html_string = '<p class="DumbClass">Lorem ipsum dolor sit amet, consectetur adipisicing elit</p>'

# Parse the html
html = lxml.html.fromstring(html_string)

# Print out our "Before"
print lxml.html.tostring(html)

# .xpath below gives us a list of all elements that have a class attribute
# xpath syntax explained:
# // = select all tags that match our expression regardless of location in doc
# * = match any tag
# [@class] = match all class attributes
for tag in html.xpath('//*[@class]'):
    # For each element with a class attribute, remove that class attribute
    tag.attrib.pop('class')

# Print out our "After"
print lxml.html.tostring(html)
2
  • 2
    Thanks. I figure if folks are nice enough to help me, I gotta pay it forward and make it easy for them and others in the future :) Commented Apr 6, 2012 at 16:09
  • 2
    clean=re.sub('class=".*?"','', html) - couldn't resist Commented Apr 3, 2016 at 6:23

3 Answers 3

18

I can't test this at the moment but this appears to be the general idea

for tag in node.xpath('//*[@class]'):
    tag.attrib.pop('class')
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks Dan. Your code worked. I added my solution based on your suggestion here as an addendum to my question for others.
3

lxml.html.clean.Cleaner does work, but needs proper configuration.

import lxml.html
from lxml.html import clean

html_string = '<p id="test" class="DumbClass">Lorem ipsum dolor sit amet, consectetur adipisicing elit</p>'
tree = html.fromstring(html_string)

cleaner = html.clean.Cleaner()
cleaner.safe_attrs_only = True
cleaner.safe_attrs=frozenset(['id'])
cleaned = cleaner.clean_html(tree)
print(html.tostring(cleaned))

Result in :

b'<p id="test">Lorem ipsum dolor sit amet, consectetur adipisicing elit</p>'

Comments

0

For lxml elment, the .attrib object contains the dict of attributes, you can just del it as you like.

Below is just a simple example to show how to replace an attribute name in html.

Given html:

<div><img src="http://www.example.com/logo.png"></div>

Code:

from lxml.html import fromstring
from lxml.html import _transform_result

html = "<div><img src=\"http://www.example.com/logo.png\"></div>"
doc = fromstring(html)
for el in doc.iter('img'):
    if "src" in el.attrib:
        el.set('data-src', el.get('src'))
        del el.attrib["src"]
print _transform_result(type(html), doc)

Result:

<div><img data-src="http://www.example.com/logo.png"></div>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.