tags:

views:

217

answers:

4

i have this html code:

<p style="padding:0px;">
<strong style="padding:0;margin:0;">hello</strong>
</p>

but it should become (for all possible html tags):

<p>
<strong>hello</strong>
</p>

this is driving me crazy, is there a regexp expert that can give me a hand? thanks!

+5  A: 

I would avoid using regex as HTML is not a regular language and instead use a html parser like Simple HTML DOM

You can get a list of attributes that the object has by using attr. For example:

$html = str_get_html('<div id="hello">World</div>');
var_dump($html->find("div", 0)->attr); /
/*
array(1) {
  ["id"]=>
  string(5) "hello"
}
*/

foreach ( $html->find("div", 0)->attr as &$value ){
    $value = null;
}

print $html
//<div>World</div>
Yacoby
i'll give it a try later ;) in the meantime gnarf's regexp solution works fine.
andufo
+1  A: 

Adapted from my answer on a similar question

$text = '<p style="padding:0px;"><strong style="padding:0;margin:0;">hello</strong></p>';

echo preg_replace("/<([a-z][a-z0-9]*)[^>]*?(\/?)>/i",'<$1$2>', $text);

// <p><strong>hello</strong></p>

The RegExp broken down:

/              # Start Pattern
 <             # Match '<' at beginning of tags
 (             # Start Capture Group $1 - Tag Name
  [a-z]         # Match 'a' through 'z'
  [a-z0-9]*     # Match 'a' through 'z' or '0' through '9' zero or more times
 )             # End Capture Group
 [^>]*?        # Match anything other than '>', Zero or More times, not-greedy (wont eat the /)
 (\/?)         # Capture Group $2 - '/' if it is there
 >             # Match '>'
/i            # End Pattern - Case Insensitive

Add some quoting, and use the replacement text <$1$2> it should strip any text after the tagname until the end of tag /> or just >.

Please Note This isn't necessarily going to work on ALL input, as the Anti-HTML + RegExp will tell you. There are a few fallbacks, most notably <p style=">"> would end up <p>"> and a few other broken issues... I would recommend looking at Zend_Filter_StripTags as a more full proof tags/attributes filter in PHP

gnarf
this worked out alright
andufo
A: 

Regex's are too fragile for HTML parsing. In your example, the following would strip out your attributes:

echo preg_replace(
    "|<(\w+)([^>]+)|",
    "<$1",
    "<p style=\"padding:0px;\">\n<strong style=\"padding:0;margin:0;\">hello</strong>\n</p>\n"
);
Greg K
It would also strip the `/>` on `<br />`
gnarf
this one has a bug, if there is only <strong>hello</strong> it returns <stron>hello</stron>
andufo
This works for the HTML supplied in the question.
Greg K
+3  A: 

Here is how to do it with native DOM:

$dom = new DOMDocument;                 // init new DOMDocument
$dom->loadHTML($html);                  // load HTML into it
$xpath = new DOMXPath($dom);            // create a new XPath
$nodes = $xpath->query('//*[@style]');  // Find elements with a style attribute
foreach($nodes as $node) {              // Iterate over found elements
    $node->removeAttribute('style');    // Remove style attribute
}
echo $dom->saveHTML();                  // output cleaned HTML
Gordon