我有这个HTML代码:
<p style="padding:0px;">
<strong style="padding:0;margin:0;">hello</strong>
</p>
但它应该成为(对于所有可能的html标签):
<p>
<strong>hello</strong>
</p>
答案 0 :(得分:137)
改编自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>
RegExp细分:
/ # 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
添加引号,并使用替换文字<$1$2>
它应该删除标记名后面的任何文字,直到标记/>
或>
结尾。
请注意这不一定适用于 ALL 输入,因为Anti-HTML + RegExp会告诉您。有一些后备,最值得注意的是<p style=">">
最终会<p>">
以及其他一些问题...我建议将Zend_Filter_StripTags视为更完整的证明代码/属性过滤器PHP
答案 1 :(得分:64)
以下是使用原生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
如果要从所有可能的标签中删除所有可能的属性,请执行
$dom = new DOMDocument;
$dom->loadHTML($html);
$xpath = new DOMXPath($dom);
$nodes = $xpath->query('//@*');
foreach ($nodes as $node) {
$node->parentNode->removeAttribute($node->nodeName);
}
echo $dom->saveHTML();
答案 2 :(得分:9)
我会避免使用正则表达式,因为HTML不是常规语言,而是使用像Simple HTML DOM这样的html解析器
您可以使用attr
获取对象所具有的属性列表。例如:
$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>
答案 3 :(得分:4)
$html_text = '<p>Hello <b onclick="alert(123)" style="color: red">world</b>. <i>Its beautiful day.</i></p>';
$strip_text = strip_tags($html_text, '<b>');
$result = preg_replace('/<(\w+)[^>]*>/', '<$1>', $strip_text);
echo $result;
// Result
string 'Hello <b>world</b>. Its beautiful day.'
答案 4 :(得分:1)
正则表达式对于HTML解析来说太脆弱了。在您的示例中,以下内容将删除您的属性:
echo preg_replace(
"|<(\w+)([^>/]+)?|",
"<$1",
"<p style=\"padding:0px;\">\n<strong style=\"padding:0;margin:0;\">hello</strong>\n</p>\n"
);
<强>更新强>
使第二次捕获可选,不要从结束标记中删除“/”:
|<(\w+)([^>]+)|
至|<(\w+)([^>/]+)?|
证明这个正则表达式有效:
$ phpsh
Starting php
type 'h' or 'help' to see instructions & features
php> $html = '<p style="padding:0px;"><strong style="padding:0;margin:0;">hello<br/></strong></p>';
php> echo preg_replace("|<(\w+)([^>/]+)?|", "<$1", $html);
<p><strong>hello</strong><br/></p>
php> $html = '<strong>hello</strong>';
php> echo preg_replace("|<(\w+)([^>/]+)?|", "<$1", $html);
<strong>hello</strong>
答案 5 :(得分:1)
要明确地做什么andufo想要的,它只是:
$html = preg_replace( "#(<[a-zA-Z0-9]+)[^\>]+>#", "\\1>", $html );
也就是说,他想从开头标签中删除除标签名称之外的任何内容。当然,它不适用于自动关闭标签。
答案 6 :(得分:1)
希望这会有所帮助。它可能不是最快的方式,特别是对于大块的HTML。 如果有人有任何建议让这更快,请告诉我。
function StringEx($str, $start, $end)
{
$str_low = strtolower($str);
$pos_start = strpos($str_low, $start);
$pos_end = strpos($str_low, $end, ($pos_start + strlen($start)));
if($pos_end==0) return false;
if ( ($pos_start !== false) && ($pos_end !== false) )
{
$pos1 = $pos_start + strlen($start);
$pos2 = $pos_end - $pos1;
$RData = substr($str, $pos1, $pos2);
if($RData=='') { return true; }
return $RData;
}
return false;
}
$S = '<'; $E = '>'; while($RData=StringEx($DATA, $S, $E)) { if($RData==true) {$RData='';} $DATA = str_ireplace($S.$RData.$E, '||||||', $DATA); } $DATA = str_ireplace('||||||', $S.$E, $DATA);
答案 7 :(得分:1)
使用 php 的 DOMDocument class(不带 xpath)的另一种方法是迭代给定节点上的属性。请注意,由于 php 处理 DOMNamedNodeMap class 的方式,如果您打算更改它,则必须向后迭代该集合。此行为已在别处讨论过,也在文档注释中注明。在删除或添加元素时,这同样适用于 DOMNodeList class。为了安全起见,我总是用这些对象向后迭代。
这是一个简单的例子:
function scrubAttributes($html, $attributes = []) {
$dom = new DOMDocument();
$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
for ($els = $dom->getElementsByTagname('*'), $i = $els->length - 1; $i >= 0; $i--) {
for ($attrs = $els->item($i)->attributes, $ii = $attrs->length - 1; $ii >= 0; $ii--) {
$els->item($i)->removeAttribute($attrs->item($ii)->name);
}
}
return $dom->saveHTML();
}
这是一个演示:https://3v4l.org/G8VPg
答案 8 :(得分:0)
<?php
$text = '<p>Test paragraph.</p><!-- Comment --> <a href="#fragment">Other text</a>';
echo strip_tags($text);
echo "\n";
// Allow <p> and <a>
echo strip_tags($text, '<p><a>');
?>
答案 9 :(得分:0)
这是摆脱属性的简单方法。它很好地处理格式错误的HTML。
<?php
$string = '<p style="padding:0px;">
<strong style="padding:0;margin:0;">hello</strong>
</p>';
//get all html elements on a line by themselves
$string_html_on_lines = str_replace (array("<",">"),array("\n<",">\n"),$string);
//find lines starting with a '<' and any letters or numbers upto the first space. throw everything after the space away.
$string_attribute_free = preg_replace("/\n(<[\w123456]+)\s.+/i","\n$1>",$string_html_on_lines);
echo $string_attribute_free;
?>