Batu Lab NotesPractical developer guides

Read HTML attributes without regex matching

By Batu · English technical notes

Also published in our Blogger archive.

HTML attributes have quoting, entity-reference, and case-normalization details that are easy to mishandle with a pattern aimed at raw source text. HTMLParser.handle_starttag() supplies a parsed list of (name, value) pairs, so this example reads an image element’s attributes directly instead of applying regular expressions. Converting those pairs to a dictionary makes named lookup clear for this controlled fixture.

The input uses uppercase IMG and ALT, single quotes around src, and an entity in alt. The parser normalizes names to lowercase, removes quotation marks from values, and converts the & reference. The assertions make each expected normalized result explicit, and the output is a stable joined summary: logo.svg | Blue & white.

There are limits to the convenient dictionary step. HTML allows duplicate attribute names in source, but dict(attrs) keeps only the final value; use the original list if duplicate handling matters. An empty attribute is represented as None, which is different from an attribute written with an empty string value. This parser is also not a browser security policy or a full DOM implementation. It structures the markup callbacks; callers still decide which tags and values are acceptable.

Python documents the normalized tag and attrs arguments in the Python html.parser documentation.

AI assistance disclosure: AI helped draft this educational example; its assertions should still be run in the target environment.

from html.parser import HTMLParser


class ImageAttributes(HTMLParser):
    def __init__(self):
        super().__init__()
        self.image = None

    def handle_starttag(self, tag, attrs):
        if tag == "img":
            self.image = dict(attrs)


parser = ImageAttributes()
parser.feed("<IMG SRC='logo.svg' ALT='Blue &amp; white' loading=lazy>")
parser.close()

assert parser.image == {
    "src": "logo.svg",
    "alt": "Blue & white",
    "loading": "lazy",
}
print(f"{parser.image['src']} | {parser.image['alt']}")
logo.svg | Blue & white