preg_replace移除样式文本/css标签

3

我需要一些关于PHP的帮助,因为我很难摆脱style type="text/css"标签。我想要删除style标签并将其替换为空字符串。

当我尝试这样做时:

if (strpos($inbox_message, '<style type="text/css">') !== false) {
    echo (preg_replace('/<style[^>]*>(([^<]|[<[^\/]|<\/[^s]|<\/s[^t])*)<\/style>/i','',$inbox_message));
}

它仍然会在HTML页面中显示样式标签。
以下是它所显示的内容:
<style type="text/css"> body {position: relative; font-family: Segoe UI; font-size: 12px; } .pageHeader {color: #9C9C9C; font-size: 160%; padding: 0px 0px 6px 0px} .pageHeaderLogo {padding-right: 15px;} .pageHeaderTitle{border-left: 1px solid #CCCCCC; padding: 5px;} .pageFooter {width: 100%; background-color: #f2f2f2; font-size: 12px; font-family: Segoe UI; padding:4px 4px 4px 4px; } .pageFooterLogo {text-align:right; width:100%} .padCells { padding: 0px 6px 0px 0px; } .preHeader {display: none !important; visibility:hidden; opacity:0; color:transparent; height:0; width:0; }</style>

请问您能否给我展示一个使用preg_replace查找style type=text/css标签的例子,以便我可以删除它们?

谢谢。

编辑:抱歉,我意识到我只需要删除样式标签中的body部分,因为我想保留样式中的其他标签。

/*GENERAL*/
    table{width:100%}
    body{background-color:#ebebeb; width: 100%; margin:0; padding:0; -webkit-font-smoothing: antialiased;font-family: "Segoe UI",SegoeUI,"Helvetica Neue",Helvetica,sans serif; -webkit-text-size-adjust: 100%;}
    div.ms-article-container #emailbodyouter .emailbodyinner section{margin:0}
    div.ms-article-container #emailbodyouter .emailbodyinner table div {margin:0}
    div.content-article #emailbodyouter .emailbodyinner section{margin:0}
    div.content-article #emailbodyouter .emailbodyinner table div {margin:0}

你是否也想要删除样式标签本身? - lbrandao
@fromvega 好的,请移除它,因为它会改变正文样式,所以我想移除它。 - chris oojer
我可以使用类似于这样的代码 $inbox_message = str_replace('<style type="text/css"> body {position: relative; font-family: Segoe UI; font-size: 12px; } .pageHeader {color: #9C9C9C; font-size: 160%; padding: 0px 0px 6px 0px} .pageHeaderLogo {padding-right: 15px;} .pageHeaderTitle{border-left: 1px solid #CCCCCC; padding: 5px;} .pageFooter {width: 100%; background-color: #f2f2f2; font-size: 12px; font-family: Segoe UI; padding:4px 4px 4px 4px; } .pageFooterLogo {text-align:right; width:100%} .padCells { padding: 0px 6px 0px 0px; } - chris oojer
@chrisoojer,你的问题在于你的正则表达式太贪婪了,它会从第一个<style>匹配到最后一个</style>,并删除中间的所有内容。 - Nick
但是样式将是随机的,所以我想使用preg_match或preg_replace来删除与style type=text/css一起出现的样式标签本身。.preHeader {display: none !important; visibility:hidden; opacity:0; color:transparent; height:0; width:0; }</style>', '', $inbox_message); - chris oojer
显示剩余2条评论
1个回答

7

直接回答:

$inbox_message = preg_replace('#<style type="text/css">.*?</style>#s', '', $inbox_message);

你不需要检查它是否存在,如果不存在,preg_replace 就不会做任何事情。你不需要担心标签内的内容 —— 非贪婪量词会处理它(只要你没有碰巧遇到嵌套的 <style> 标签,这将是相当罕见的)。而且,如果你选择另一个分隔符,你也不需要担心转义斜杠。

非直接回答: 小心 Zalgo

$doc = new DOMDocument();
$doc->loadHTML($inbox_message);
$xpath = new DOMXpath($doc);
$styles = $xpath->query('//style[@type="text/css"]');
if ($styles) {
  foreach ($styles as $style) {
    $style->parentNode->removeChild($style);
  }
}
$inbox_message = $doc->saveHTML();

编辑 根据问题的变化:由于默认情况下没有 CSS 解析器,我们最终不得不使用正则表达式。像这样的方法应该可以。Zalgo 方法:

$inbox_message = preg_replace_callback('#<style type="text/css">.*?</style>#s', function($match) {
  return preg_replace('#body\s*{(?:[^"}]|"[^"]*")*}#', '', $match[0]);
}, $inbox_message);

反Zalgo方法:

$doc = new DOMDocument();
$doc->loadHTML($inbox_message);
$xpath = new DOMXpath($doc);
$styles = $xpath->query('//style[@type="text/css"]');
if ($styles) {
  foreach ($styles as $style) {
    $style->textContent = preg_replace('#body\s*{(?:[^"}]|"[^"]*")*}#', '', $style->textContent);
  }
}
$inbox_message = $doc->saveHTML();

如果 $styles 是空的,那么 if ($styles) 似乎是多余的,因为 foreach 不会执行任何操作。 - Nick
@Nick 是的,可能我太防御了。 query 可能会返回 FALSE,但只有在查询语句格式错误或上下文不正确时才会如此(尽管我相信查询语句是正确的,并且我没有使用上下文)... :P - Amadan
@Amadan 很抱歉,我只需要删除 body { 这一行,你的代码怎么做到? - chris oojer
@Amadan 我只需要删除页面底部显示的这个 body{background-color:#ebebeb; width: 100%; margin:0; padding:0; -webkit-font-smoothing: antialiased;font-family: "Segoe UI",SegoeUI,"Helvetica Neue",Helvetica,sans serif; -webkit-text-size-adjust: 100%;} - chris oojer
你所说的“显示在页面底部”是什么意思?样式不是显示出来的,而是被应用的。运行我的代码之后,就不应该有样式可以再应用了(当然也不应该有所谓的显示)。你到底想问什么呢?而且,在你的问题中并没有提到“body”这个词吧。。? - Amadan
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接