dazhall Posted February 23, 2007 Share Posted February 23, 2007 Hi Guys, I'm trying to do a function that will look at my styles and then go through the rest of the html document and add those styles inline to the particular tag. Eg: The styles: <style type="text/css"> h1 { font-family: Verdana, Arial, Helvetica, sans-serif; } p.myclass { color: #CC0000; } p.myclass a { text-decoration: none; color: #FFCC00; } </style> The html: <h1>Lorem ipsum dolor sit amet</h1> <p class="myclass">consectetuer adipiscing <a href="#">elit</a>. Sed vel velit eu lorem dignissim iaculis.</p> The result: <h1 style="font-family: Verdana, Arial, Helvetica, sans-serif;">Lorem ipsum dolor sit amet</h1> <p style="color: #CC0000;">consectetuer adipiscing <a style="text-decoration: none; color: #FFCC00;" href="#">elit</a>. Sed vel velit eu lorem dignissim iaculis.</p> Impossible? I think not, well not entirely! I'm just drowning in regex expressions! If anyone has seen anything like it before then shout up, or if anyone can offer any help I'd be extremely appreciative! Oh, why am I wanting to do this I hear you cry?! I'm doing a script that send out html emails, and I need to attach the style dynamically based up the template. Thanks! Quote Link to comment Share on other sites More sharing options...
Cep Posted February 23, 2007 Share Posted February 23, 2007 Its not impossible but why add a style attribute to each tag? Why not just use a CSS stylesheet which is easier to control and easier to edit later on? Quote Link to comment Share on other sites More sharing options...
dazhall Posted February 23, 2007 Author Share Posted February 23, 2007 Because Google Mail (and other email clients) don't like styles sheets! and unfortunately the only way to get around it is to add inline styles to every tag. Now beacuse the content is dynamic there could be <p> or <ul> all over the place and the user wont be able to add inline styles to each tag, nor should they have to. So, the code will look thorugh the template we create and add those inline styles automatically. Quote Link to comment Share on other sites More sharing options...
effigy Posted February 23, 2007 Share Posted February 23, 2007 Are you working with a fixed set of styles? This could be very challenging when you consider mimicing the "cascading" part of CSS. If you have the option to use Perl, they have a few CSS modules that may be helpful. Quote Link to comment Share on other sites More sharing options...
dazhall Posted February 23, 2007 Author Share Posted February 23, 2007 I've decided to limit myself to one style, so no classes or cascading styles - it's difficult enough as it is. I'm thinking it should be relatively easy just to regex a p { or li {. I could limit it to to a set number of styles, as really i'm only going to be using p, ul, li , h1/2/3/4/5, a etc. Quote Link to comment Share on other sites More sharing options...
effigy Posted February 23, 2007 Share Posted February 23, 2007 Here's a start: <pre> <?php $css = <<<CSS <style type="text/css"> h1 { font-family: Verdana, Arial, Helvetica, sans-serif; } h2 { text-decoration: none; color: #FFCC00; } p { color: #CC0000; } </style> CSS; function parse_css($css) { preg_match_all('/^\s*(\w+)\s*\{\s*([^}]+?)\s*\}/m', $css, $matches, PREG_SET_ORDER); foreach ($matches as $idx => &$array) { // Remove the whole match. array_shift($matches[$idx]); } return $matches; } $pieces = parse_css($css); print_r($pieces); ?> </pre> Quote Link to comment Share on other sites More sharing options...
Cep Posted February 23, 2007 Share Posted February 23, 2007 Because Google Mail (and other email clients) don't like styles sheets! and unfortunately the only way to get around it is to add inline styles to every tag. Now beacuse the content is dynamic there could be <p> or <ul> all over the place and the user wont be able to add inline styles to each tag, nor should they have to. So, the code will look thorugh the template we create and add those inline styles automatically. Hmm your going to have this problem even with inline styles, its just the way it goes with Yahoo, MSN etc etc. I produce a lot of email shots for our clients and the best thing you can do is to create an embedded stylesheet and XHTML your email document. Quote Link to comment Share on other sites More sharing options...
dazhall Posted March 2, 2007 Author Share Posted March 2, 2007 Thanks for that! Right, so I've modified it a wee bit to get it working more like I'd like it to: <?php $css = '<style type="text/css"> h1 { font-family: Arial, Helvetica, sans-serif; } h2 { text-decoration: none; color: #666666; } p { color: #333333; } p.error { color: #CC0000; } a { color: #green; } </style>'; $html = '<h1>Regex CSS Replacement Test</h1><h2>It\'s Regex with style!</h2><p>As you can clearly see it\'s possible to use regular expresions to search through your style sheet and hard code the syles into the html tags.</p><p class="error">It\'s red good! It all <a href="http://www.moodle.co.uk">links</a> into my plan!</p>'; function parse_css($css,$html) { preg_match_all('/^\s*(\w+)\.*(\w*)\s*\{\s*([^}]+?)\s*\}/m', $css, $matches, PREG_SET_ORDER); foreach ($matches as $idx => $array) { // Remove the whole match. array_shift($matches[$idx]); } foreach ($matches as $match) { if ($match[1]=="") { $open = '<'.$match[0].'>'; $taggedOpen = '<'.$match[0].' style="'.$match[2].'">'; } else { $open = '<'.$match[0].' class="'.$match[1].'">'; $taggedOpen = '<'.$match[0].' style="'.$match[2].'">'; } $html = str_replace($open,$taggedOpen,$html); } return $html; } echo parse_css($css,$html); ?> What I'm trying to do now is get rid of my str_replace in favour of preg_replace. The problem I'm having is catering for tags such as <a> where the 'class' attribute could be either side of the 'href' attribute. I thought I was starting to get the hang of the syntax for regex now, but my attempts haven't quite worked! Quote Link to comment Share on other sites More sharing options...
dazhall Posted March 2, 2007 Author Share Posted March 2, 2007 Now I know this isn't right, but it's the start Ive made so far, what I think I need to do is change the (.*^class) and (.*) to something more restrictive, as (.*^class) gets tags within tags (like an <a> inside a <p>). But it's a start! Any help is appreciated! Quote Link to comment Share on other sites More sharing options...
effigy Posted March 2, 2007 Share Posted March 2, 2007 This isn't perfect--it's not entirely flexible and a callback would be better--but it does what you want: <pre> <?php $css = '<style type="text/css"> h1 { font-family: Arial, Helvetica, sans-serif; } h2 { text-decoration: none; color: #666666; } p.error { color: #CC0000; } p { color: #333333; } a { color: green; } </style>'; $html = '<h1>Regex CSS Replacement Test</h1><h2>It\'s Regex with style!</h2><p>As you can clearly see it\'s possible to use regular expresions to search through your style sheet and hard code the syles into the html tags.</p><p class="error">It\'s red good! It all <a href="http://www.moodle.co.uk">links</a> into my plan!</p>'; function parse_css($css,$html) { preg_match_all('/^\s*(\w+)\.*(\w*)\s*\{\s*([^}]+?)\s*\}/m', $css, $matches, PREG_SET_ORDER); foreach ($matches as $idx => $array) { // Remove the whole match. array_shift($matches[$idx]); } foreach ($matches as $match) { $regex = '/<' . preg_quote($match[0], '/') . '\s?([^>]*)'; if ($match[1]) { $regex .= 'class="' . preg_quote($match[1], '/') . '"([^>]*)'; } $regex .= '\s?>/i'; echo htmlspecialchars($regex), '<br>'; $taggedOpen = '<'.$match[0].' \1 \2 style="'.$match[2].'">'; $html = preg_replace($regex, $taggedOpen, $html); } return $html; } echo parse_css($css,$html); ?> </pre> Quote Link to comment Share on other sites More sharing options...
dazhall Posted March 2, 2007 Author Share Posted March 2, 2007 Thanks again! What I need to do though is modify it so that it works with these styles: <style type="text/css"> h1 { font-family: Arial, Helvetica, sans-serif; } h2 { text-decoration: none; color: #666666; } p.error { color: #CC0000; } p { color: #333333; } a { color: green; } a.error { color: pink; } </style> Like so: <p class="error">It\'s red good! It all <a href="http://www.moodle.co.uk" class="error">links</a> into my plan!</p> Oh sorry, I forgot to post the changes that I made! I got it to this: <?php $css = '<style type="text/css"> h1 { font-family: Arial, Helvetica, sans-serif; } h2 { text-decoration: underline; color: #666666; } p { color: #333333; } p.error { color: #CC0000; } a { color: green; } a.error { color: pink; } </style>'; $html = '<h1>Regex CSS Replacement Test</h1><h2>It\'s Regex with style!</h2><p>As you can clearly see it\'s possible to use regular expresions to search through your style sheet and hard code the syles into the html tags.</p><p class="error">It\'s red good! It all <a href="http://www.moodle.co.uk" class="error">links</a> into my plan!</p>'; function parse_css($css,$html) { preg_match_all('/^\s*(\w+)\.*(\w*)\s*\{\s*([^}]+?)\s*\}/m', $css, $matches, PREG_SET_ORDER); foreach ($matches as $idx => $array) { // Remove the whole match. array_shift($matches[$idx]); } foreach ($matches as $match) { if ($match[1]=="") { $html = preg_replace("/<$match[0](.*^class)>/","<$match[0] style=\"$match[2]\"$1>",$html); } else { $html = preg_replace("/<$match[0](.*)class=[\"|\']$match[1][\"|\'](.*)>/","<$match[0]$1style=\"$match[2]\"$2>",$html); } } return $html; } echo parse_css($css,$html); ?> Quote Link to comment Share on other sites More sharing options...
effigy Posted March 2, 2007 Share Posted March 2, 2007 Changes marked with #####: <?php $css = '<style type="text/css"> h1 { font-family: Arial, Helvetica, sans-serif; } h2 { text-decoration: underline; color: #666666; } p { color: #333333; } p.error { color: #CC0000; } a { color: green; } a.error { color: pink; } </style>'; $html = '<h1>Regex CSS Replacement Test</h1><h2>It\'s Regex with style!</h2><p>As you can clearly see it\'s possible to use regular expresions to search through your style sheet and hard code the syles into the html tags.</p><p class="error">It\'s red good! It all <a href="http://www.moodle.co.uk" class="error">links</a> into my plan!</p>'; function parse_css($css,$html) { preg_match_all('/^\s*(\w+)\.*(\w*)\s*\{\s*([^}]+?)\s*\}/m', $css, $matches, PREG_SET_ORDER); foreach ($matches as $idx => $array) { // Remove the whole match. array_shift($matches[$idx]); } ##### Sort descending so tags with classes come before those without. array_multisort($matches, SORT_DESC); foreach ($matches as $match) { if ($match[1]=="") { ##### Ignore the match if it already contains a style attribute. $html = preg_replace("/<$match[0](((?!style)[^>])*)>/","<$match[0] style=\"$match[2]\"$1>",$html); } else { $html = preg_replace("/<$match[0]([^>]*)class=[\"|\']$match[1][\"|\']([^>]*)>/","<$match[0]$1style=\"$match[2]\"$2>",$html); } } return $html; } echo parse_css($css,$html); ?> Quote Link to comment Share on other sites More sharing options...
dazhall Posted March 5, 2007 Author Share Posted March 5, 2007 Thanks that's great! Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.