php删除不包含任何内容的html标记

php删除不包含任何内容的html标记,php,html,regex,html-parsing,Php,Html,Regex,Html Parsing,我正在显示在所见即所得编辑器(未使用外部css)中编写的内容(一个名为$ps并填充html的字符串),其中包含诸如 <p> <span style="font-family: Calibri, sans-serif; font-size: 11pt;"> <br></br> </span> <span style="font-size: 11pt; font-family: Calibri, sans-serif;"&g

我正在显示在所见即所得编辑器(未使用外部css)中编写的内容(一个名为$ps并填充html的字符串),其中包含诸如

<p>

<span style="font-family: Calibri, sans-serif; font-size: 11pt;">
    <br></br>
</span>
<span style="font-size: 11pt; font-family: Calibri, sans-serif;">
</span>

</p>



我想使用php删除它(因为我希望作者继续意外地添加空内容)

到目前为止,我有一个非常低效的代码:

$ps = preg_replace('#class="(.*?)"#', '',$ps);
$ps = preg_replace('#style="(.*?)"#', '',$ps);
$ps = preg_replace('#<br\s*/*>#i', '',$ps);
$ps = preg_replace('#<span\s*/*>#i', '',$ps);
$ps = preg_replace('#<p>\s*</p>#i', '',$ps);
$ps=preg#u replace('#class=“(.*?”)#',''$ps);
$ps=preg#u replace(“#style=“(.*?”#)”,“$ps);
$ps=预替换(“##i”,”$ps);
$ps=预替换(“##i”,”$ps);
$ps=preg_replace(“#\s*

#i”,“$ps”);
这大概是好的一半,留给我的是:

<p>

</p>
<p>

</p>

我怀疑如果空的东西看起来有点不同,它就不能可靠地工作

你能帮我建立一个更好的解决方案,我可以很容易地实施吗?也许是一个有效的正则表达式,与我目前的尝试不同


谢谢大家!

我会使用DOMDocument而不是regex:

$html = '<span style="font-family: Calibri, sans-serif; font-size: 11pt;">...';

$domd = new DOMDocument();
$domd->loadHTML($html);

$domx = new DOMXPath($domd);
$items = $domx->query("//*");

foreach($items as $item) {
  $item->removeAttribute("style");
  $item->removeAttribute("class");
}

echo $domd->saveHTML();
$html='…';
$domd=新的DOMDocument();
$domd->loadHTML($html);
$domx=新的DOMXPath($domd);
$items=$domx->query(“//*”);
foreach($items作为$item){
$item->removeAttribute(“样式”);
$item->removeAttribute(“类”);
}
echo$domd->saveHTML();

您还可以删除空节点,或者需要删除的任何其他节点。

作为对@ovi答案中注释的响应,因为注释中的代码块很难看

您可以运行它,直到它不再从元素集中删除任何内容为止。如果这是一个很长的文档,它会拖得很长,但我想它会起作用

比如说

$changed = true;
while ($changed = true){
  $changed = false;
  foreach($items as $item) {
    if (trim($item->nodeValue) == ''){
      $item->parentNode->removeChild($item);
      $changed = true;
    }
  }
}

我重申,这可能需要相当长的时间。另外,我还没有测试
$item->parentNode->removeChild($item)块。

第一件事优先(不管这是否是一个好方法),preg_replace可以接受一个正则表达式数组。例如:
preg#u replace(数组('#class=“(.*?”)、'#style=“(.*?)”、'#i'、'#i'、'#\s*

#i')、'$ps)我认为应该使用删除空节点。正则表达式不适合HTML。检查这两种SO解决方案。而用正则表达式解析HTML则是一种令人悲伤的方法。当您的用户输入与您的期望不匹配时,您的正则表达式将中断。例如,如果您的

标记位于不同的行上,该怎么办?用正则表达式修改HTML更糟糕。使用合适的HTML解析器。你可能会发现我对一个非常类似的问题的回答很有用:类似于
if(trim($item->nodeValue)=='')$item->parentNode->removeChild($item)可能会这样做,尽管我还没有测试过谢谢大家!这个解决方案几乎完成了。我现在在$html和if(trim($item->nodeValue)='')$item->parentNode->removeChild($item)中使用Umlaute时遇到了问题;仅删除第一个/某些空节点。我还没有弄清楚这取决于什么。@user148585您需要注意先删除哪些内容,或者运行几次。如果一个跨距中有一个空跨距,那么内部跨距应该被移除,但外部跨距可能不会被移除。@wolffer east你能帮我解决这个问题吗?到目前为止,我已经残忍地完成了$domd2->loadHTML($domd->saveHTML());并相应地复制了后续内容,但没有成功。谢谢,我明白你的意思。不幸的是,removeChild最终尝试删除非对象?即使这个循环是查询之后唯一要做的事情……不幸的是,我不是domdocument操作方面的专家。您可以尝试一下
(trim($item->nodeValue)=''&&$child->nodeName!=“#text”)
。不幸的是,这没有奏效。非常感谢你的帮助!