Michalowic
Michalowic

Reputation: 23

Remove all attributes in HTML tag except specified with regex

I'm trying to make regex which remove all attributes from HTML tags except specified ones.

I have this HTML code:

<p class="someClass" id="someId" style="border: 1px solid black" name="someName" foo="bar"></p>

And I want to remove all attributes except class, id and name, code should look like:

<p class="someClass" id="someId" name="someName">Text</p>

I have this regex:

<([a-z][a-z0-9]*)(?:[^>]*(\sid=['"][^'"]*['"]))?[^>]*?(\/?)>

and use pattern

<$1$2>

It only works for attribute id. How to do it for all specified attributes?

Upvotes: 2

Views: 2596

Answers (1)

Scott Weaver
Scott Weaver

Reputation: 7351

You can achieve this with a negative lookahead, which will tell your expression to either 1. eat one character, or 2. match the special sequence, then rinse and repeat:

<(\w+)\s*(?:(?:(?:(?!class=|id=|name=)[^>]))*((?:class|id|name)=['"][^'"]*['"]\s*)?)+>

Explanation:

  1. <(\w+)\s* (match open of tag and tagname)

  2. (?: (begin enclosure of main construct (note that it doesn't remember matches))

  3. (?:(?:(?!class=|id=|name=)[^>]))* (look ahead for no special token, then eat one character, repeat as many times possible, don't bother to remember anything)

  4. ((?:class|id|name)=['"][^'"]*['"])\s*? (lookahead failed, so special token ahead, let's eat it! note the regular, 'remembering' parens)

  5. )+ (end enclosure of main construct; repeat it, it'll match once for each special token)

  6. > (end of tag)

At this point you might have the matches you need, if your regex flavor supports multiple matches per group. In .NET for example, you'd have something similar to this: $1 = 'a', $2[0]='class="someClass"', $2[1]='id="someId"', etc.

But if you find that only the last match is remembered, you may have to simply repeat the main construct for each token you want to match, like so: (matches will be $1-$4)

<(\w+)\s*(?:(?:(?:(?!class=|id=|name=)[^>]))*((?:class|id|name)=['"][^'"]*['"]\s*)?)(?:(?:(?:(?!class=|id=|name=)[^>]))*((?:class|id|name)=['"][^'"]*['"]\s*)?)(?:(?:(?:(?!class=|id=|name=)[^>]))*((?:class|id|name)=['"][^'"]*['"]\s*)?)[^>]*>

(see it in action here).

Upvotes: 1

Related Questions