Solved

Regex to match certain HTML attributes

Posted on 2006-11-27
7
1,200 Views
Last Modified: 2013-11-19
Hi,

Regexes are sometimes quite challenging. I've been banging my head on this table for hours now and want to stop.  Please help me get rid of this headache!

I need to remove all style and class attributes in an HTML file whilst leaving all other attributes untouched.  I just need the regex for this - I've written a generic filter that uses the Regex,  but I just can't seem to get this one to work (I'm failing to get the regex to ignore other attributes between the tag and the style=...).

Given the following HTML (which came from pasting from the trully awful MS Werd - I really couldn't invent this rubbish if I tried!):

<H1 style="MARGIN: 0cm 0cm 0pt"><FONT color=#000000>blah blah<SPAN style="mso-spacerun: yes">&nbsp; </SPAN></font></H1>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: justify"><?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" /><st1:PlaceName w:st="on"><SPAN style="FONT-SIZE: 10pt; COLOR: #ff9900; FONT-FAMILY: 'Century Gothic'">blah blah</SPAN></st1:PlaceName><SPAN style="FONT-SIZE: 10pt; COLOR: #ff9900; FONT-FAMILY: 'Century Gothic'">

I need just the Regex and the Replacement strings.  It should:
 - remove (match) style and class attributes
 - work with and without quotes - note that 'Century Gothic' is wrapped with single quotes
 - assume the attribute quotes are "double" (or missing)
 - the attributes must be allowed to be in *any* order in the tag
 - all other attributes and tags must be left in situ

I've other regexes that clean the rest of the vomit - at least ten of them!

For a bonus,  if anyone has the name of the idiot who created the Werd HTML engine.....  I'd just love to write to his/her mother and tell her how her child is messing with people's heads:-)

Cheers,
0
Comment
Question by:GlennGilbert
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 3
7 Comments
 
LVL 10

Assisted Solution

by:xanius
xanius earned 100 total points
ID: 18027043
search:

(perl style regex):

\b(class|style)=("[^"]+?"|\S+)\s*

replace: nothing

Xanius
0
 
LVL 3

Author Comment

by:GlennGilbert
ID: 18027052
Cheers!

Could you add the angle brackets to make it specific for an HTML tag please.

0
 
LVL 3

Author Comment

by:GlennGilbert
ID: 18027079
I always seem to mess up when adding the more specific characters:

Yours:
  \b(class|style)=("[^"]+?"|\S+)\s*


Mine:
  <.*\b(class|style)=("[^"]+?"|\S+)\s*.*>
  Which,  needless to say,  doesn't work as it matches everything.
0
Is Your DevOps Pipeline Leaking?

Is your CI/CD pipeline a hodge-podge of randomly connected tools? You’ve likely got a tool to fix one problem & then a different tool to fix another, resulting in a cluster of tools with overlapping functionality. Learn how to optimize your pipeline with Gartner's recommendations

 
LVL 84

Accepted Solution

by:
ozo earned 400 total points
ID: 18027153
$_=q<
<H1 style="MARGIN: 0cm 0cm 0pt"><FONT color=#000000>blah blah<SPAN style="mso-spacerun: yes">&nbsp; </SPAN></font></H1>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: justify"><?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" /><st1:PlaceName w:st="on"><SPAN style="FONT-SIZE: 10pt; COLOR: #ff9900; FONT-FAMILY: 'Century Gothic'">blah blah</SPAN></st1:PlaceName><SPAN style="FONT-SIZE: 10pt; COLOR: #ff9900; FONT-FAMILY: 'Century Gothic'">
>;

s/(<[^<>]*?)\b((class|style)=("[^"]+?"|\S+)\s*)+([^<>]*>)/$1$5/g;

print;
0
 
LVL 3

Author Comment

by:GlennGilbert
ID: 18027624
Fantastic - thank you!

My learning point... search for all characters that aren't a start < or end > tag - and do this using as few matches as possible - *?

I made a small change to capture the leadng space(s) before the span/class so it looks like this (the syntax is my underlying filter which this will be poked into):
<Filter>
(<[^<>]*?)\s*\b((class|style)=("[^"]+?"|\S+))+([^<>]*>)
</Filter>
<Replacement>
$1$5
</Replacement>


Input:
<H1 style="MARGIN: 0cm 0cm 0pt"><FONT color=#000000>blah blah<SPAN style="mso-spacerun: yes">&nbsp; </SPAN></font></H1>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: justify"><?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" /><st1:PlaceName w:st="on"><SPAN style="FONT-SIZE: 10pt; COLOR: #ff9900; FONT-FAMILY: 'Century Gothic'">blah blah</SPAN></st1:PlaceName><SPAN style="FONT-SIZE: 10pt; COLOR: #ff9900; FONT-FAMILY: 'Century Gothic'">


Output:
<H1><FONT color=#000000>blah blah<SPAN>&nbsp; </SPAN></font></H1>
<P style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: justify"><?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" /><st1:PlaceName w:st="on"><SPAN>blah blah</SPAN></st1:PlaceName><SPAN>


And I'll just get on with clearing out the rest of the vomit - like the xml prologue, smart tag stuff, font tags, empty styles... the list seems to go on forever.

Cheers,
Glenn
0
 
LVL 10

Expert Comment

by:xanius
ID: 18027665
Glenn,

> Which,  needless to say,  doesn't work as it matches everything.

when such things happen, you generally have a too greedy regex. As in the examples above, as a thumbs of rule, put in a '?' after the '*' and '?'s.

0
 
LVL 10

Expert Comment

by:xanius
ID: 18027733
(Sorrry, I was crossposting)

<Filter>
(<[^<>]*?)\s*\b((class|style)=("[^"]+?"|\S+))+([^<>]*>)
</Filter>
<Replacement>
$1$5
</Replacement>

works perfectly as long as there are no other attribtes between 'class' and 'style'. If this is true youre ok. If not, you should rather try to use two regexes, the first to idetnify the tag and the secodn to work on it

Regex1:
<Filter>
(<[^<>]*?(?:class|style)=[^<>]*?>)
</Filter>
 Put "$1" into som variable, then apply the following regex in it with the global switch

Regex2:
<Filter>
\b(class|style)=("[^"]+?"|\S+)\s*
</Filter>
<Replacement>
</Replacement>

Cheers
Xanius
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Preface This article introduces an authentication and authorization system for a website.  It is understood by the author and the project contributors that there is no such thing as a "one size fits all" system.  That being said, there is a certa…
This article covers the basics of the Sass, which is a CSS extension language. You will learn about variables, mixins, and nesting.
HTML5 has deprecated a few of the older ways of showing media as well as offering up a new way to create games and animations. Audio, video, and canvas are just a few of the adjustments made between XHTML and HTML5. As we learned in our last micr…
Video by: Mark
This lesson goes over how to construct ordered and unordered lists and how to create hyperlinks.

728 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question