Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1231
  • Last Modified:

Regex to match certain HTML attributes

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
GlennGilbert
Asked:
GlennGilbert
  • 3
  • 3
2 Solutions
 
xaniusCommented:
search:

(perl style regex):

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

replace: nothing

Xanius
0
 
GlennGilbertAuthor Commented:
Cheers!

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

0
 
GlennGilbertAuthor Commented:
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
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
ozoCommented:
$_=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
 
GlennGilbertAuthor Commented:
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
 
xaniusCommented:
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
 
xaniusCommented:
(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

NEW Veeam Backup for Microsoft Office 365 1.5

With Office 365, it’s your data and your responsibility to protect it. NEW Veeam Backup for Microsoft Office 365 eliminates the risk of losing access to your Office 365 data.

  • 3
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now